blob: 378d534ab8f96d35acd6d479b898aa93c2825713 [file] [log] [blame] [edit]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// See: https://github.com/dart-lang/linter/issues/2921
// ignore_for_file: use_late_for_private_fields_and_variables
part of dart.ui;
const int kImplicitViewId = 0;
class FlutterView {
FlutterView._(this.viewId, this.platformDispatcher);
/// The opaque ID for this view.
final Object viewId;
/// The platform dispatcher that this view is registered with, and gets its
/// information from.
final PlatformDispatcher platformDispatcher;
ViewConfiguration get _viewConfiguration {
final PlatformDispatcher engineDispatcher = platformDispatcher;
assert(engineDispatcher.windowConfigurations.containsKey(viewId));
return engineDispatcher.windowConfigurations[viewId] ??
const ViewConfiguration();
}
double get devicePixelRatio => _viewConfiguration.devicePixelRatio;
Rect get physicalGeometry => _viewConfiguration.geometry;
Size get physicalSize => _viewConfiguration.geometry.size;
ViewPadding get viewInsets => _viewConfiguration.viewInsets;
ViewPadding get viewPadding => _viewConfiguration.viewPadding;
ViewPadding get systemGestureInsets => _viewConfiguration.systemGestureInsets;
ViewPadding get padding => _viewConfiguration.padding;
GestureSettings get gestureSettings => _viewConfiguration.gestureSettings;
List<DisplayFeature> get displayFeatures => _viewConfiguration.displayFeatures;
void render(Scene scene) {
// TODO(yjbanov): implement a basic preroll for better benchmark realism.
}
void updateSemantics(SemanticsUpdate update) {
platformDispatcher.updateSemantics(update);
}
}
class SingletonFlutterWindow extends FlutterView {
SingletonFlutterWindow._(Object windowId, PlatformDispatcher platformDispatcher)
: super._(windowId, platformDispatcher) {
platformDispatcher._updateLifecycleState('resumed');
_updateWindowMetrics(
true, // isInitializing
0, // id
1.0, // devicePixelRatio
// 4k
_screenWidth, // width
_screenHeight, // height
0, // viewPaddingTop
0, // viewPaddingRight
0, // viewPaddingBottom
0, // viewPaddingLeft
0, // viewInsetTop
0, // viewInsetRight
0, // viewInsetBottom
0, // viewInsetLeft
0, // systemGestureInsetTop
0, // systemGestureInsetRight
0, // systemGestureInsetBottom
0, // systemGestureInsetLeft
0, // double physicalTouchSlop,
const <double>[], // List<double> displayFeaturesBounds,
const <int>[], // List<int> displayFeaturesType,
const <int>[], // List<int> displayFeaturesState,
);
}
VoidCallback? get onMetricsChanged => platformDispatcher.onMetricsChanged;
set onMetricsChanged(VoidCallback? callback) {
platformDispatcher.onMetricsChanged = callback;
}
Locale get locale => platformDispatcher.locale;
List<Locale> get locales => platformDispatcher.locales;
Locale? computePlatformResolvedLocale(List<Locale> supportedLocales) {
return platformDispatcher.computePlatformResolvedLocale(supportedLocales);
}
VoidCallback? get onLocaleChanged => platformDispatcher.onLocaleChanged;
set onLocaleChanged(VoidCallback? callback) {
platformDispatcher.onLocaleChanged = callback;
}
String get initialLifecycleState => platformDispatcher.initialLifecycleState;
double get textScaleFactor => platformDispatcher.textScaleFactor;
bool get alwaysUse24HourFormat => platformDispatcher.alwaysUse24HourFormat;
VoidCallback? get onTextScaleFactorChanged => platformDispatcher.onTextScaleFactorChanged;
set onTextScaleFactorChanged(VoidCallback? callback) {
platformDispatcher.onTextScaleFactorChanged = callback;
}
Brightness get platformBrightness => platformDispatcher.platformBrightness;
VoidCallback? get onPlatformBrightnessChanged => platformDispatcher.onPlatformBrightnessChanged;
set onPlatformBrightnessChanged(VoidCallback? callback) {
platformDispatcher.onPlatformBrightnessChanged = callback;
}
FrameCallback? get onBeginFrame => platformDispatcher.onBeginFrame;
set onBeginFrame(FrameCallback? callback) {
platformDispatcher.onBeginFrame = callback;
}
VoidCallback? get onDrawFrame => platformDispatcher.onDrawFrame;
set onDrawFrame(VoidCallback? callback) {
platformDispatcher.onDrawFrame = callback;
}
TimingsCallback? get onReportTimings => platformDispatcher.onReportTimings;
set onReportTimings(TimingsCallback? callback) {
platformDispatcher.onReportTimings = callback;
}
PointerDataPacketCallback? get onPointerDataPacket => platformDispatcher.onPointerDataPacket;
set onPointerDataPacket(PointerDataPacketCallback? callback) {
platformDispatcher.onPointerDataPacket = callback;
}
String get defaultRouteName => platformDispatcher.defaultRouteName;
void scheduleFrame() => platformDispatcher.scheduleFrame();
bool get semanticsEnabled => platformDispatcher.semanticsEnabled;
VoidCallback? get onSemanticsEnabledChanged => platformDispatcher.onSemanticsEnabledChanged;
set onSemanticsEnabledChanged(VoidCallback? callback) {
platformDispatcher.onSemanticsEnabledChanged = callback;
}
SemanticsActionCallback? get onSemanticsAction => platformDispatcher.onSemanticsAction;
set onSemanticsAction(SemanticsActionCallback? callback) {
platformDispatcher.onSemanticsAction = callback;
}
AccessibilityFeatures get accessibilityFeatures => platformDispatcher.accessibilityFeatures;
VoidCallback? get onAccessibilityFeaturesChanged => platformDispatcher.onAccessibilityFeaturesChanged;
set onAccessibilityFeaturesChanged(VoidCallback? callback) {
platformDispatcher.onAccessibilityFeaturesChanged = callback;
}
@override
void updateSemantics(SemanticsUpdate update) => platformDispatcher.updateSemantics(update);
void sendPlatformMessage(String name,
ByteData? data,
PlatformMessageResponseCallback? callback) {
platformDispatcher.sendPlatformMessage(name, data, callback);
}
PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage;
set onPlatformMessage(PlatformMessageCallback? callback) {
platformDispatcher.onPlatformMessage = callback;
}
void setIsolateDebugName(String name) => PlatformDispatcher.instance.setIsolateDebugName(name);
}
/// Additional accessibility features that may be enabled by the platform.
///
/// It is not possible to enable these settings from Flutter, instead they are
/// used by the platform to indicate that additional accessibility features are
/// enabled.
//
// When changes are made to this class, the equivalent APIs in each of the
// embedders *must* be updated.
class AccessibilityFeatures {
const AccessibilityFeatures._(this._index);
static const int _kAccessibleNavigation = 1 << 0;
static const int _kInvertColorsIndex = 1 << 1;
static const int _kDisableAnimationsIndex = 1 << 2;
static const int _kBoldTextIndex = 1 << 3;
static const int _kReduceMotionIndex = 1 << 4;
static const int _kHighContrastIndex = 1 << 5;
// A bitfield which represents each enabled feature.
final int _index;
/// Whether there is a running accessibility service which is changing the
/// interaction model of the device.
///
/// For example, TalkBack on Android and VoiceOver on iOS enable this flag.
bool get accessibleNavigation => _kAccessibleNavigation & _index != 0;
/// The platform is inverting the colors of the application.
bool get invertColors => _kInvertColorsIndex & _index != 0;
/// The platform is requesting that animations be disabled or simplified.
bool get disableAnimations => _kDisableAnimationsIndex & _index != 0;
/// The platform is requesting that text be rendered at a bold font weight.
///
/// Only supported on iOS.
bool get boldText => _kBoldTextIndex & _index != 0;
/// The platform is requesting that certain animations be simplified and
/// parallax effects removed.
///
/// Only supported on iOS.
bool get reduceMotion => _kReduceMotionIndex & _index != 0;
/// The platform is requesting that UI be rendered with darker colors.
///
/// Only supported on iOS.
bool get highContrast => _kHighContrastIndex & _index != 0;
@override
String toString() {
final List<String> features = <String>[];
if (accessibleNavigation)
features.add('accessibleNavigation');
if (invertColors)
features.add('invertColors');
if (disableAnimations)
features.add('disableAnimations');
if (boldText)
features.add('boldText');
if (reduceMotion)
features.add('reduceMotion');
if (highContrast)
features.add('highContrast');
return 'AccessibilityFeatures$features';
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
return other is AccessibilityFeatures
&& other._index == _index;
}
@override
int get hashCode => _index.hashCode;
}
/// Describes the contrast of a theme or color palette.
enum Brightness {
/// The color is dark and will require a light text color to achieve readable
/// contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,
/// The color is light and will require a dark text color to achieve readable
/// contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}
/// The [SingletonFlutterWindow] representing the main window for applications
/// where there is only one window, such as applications designed for
/// single-display mobile devices.
///
/// Applications that are designed to use more than one window should interact
/// with the `WidgetsBinding.instance.platformDispatcher` instead.
///
/// Consider avoiding static references to this singleton through
/// [PlatformDispatcher.instance] and instead prefer using a binding for
/// dependency resolution such as `WidgetsBinding.instance.window`.
///
/// Static access of this `window` object means that Flutter has few, if any
/// options to fake or mock the given object in tests. Even in cases where Dart
/// offers special language constructs to forcefully shadow such properties,
/// those mechanisms would only be reasonable for tests and they would not be
/// reasonable for a future of Flutter where we legitimately want to select an
/// appropriate implementation at runtime.
///
/// The only place that `WidgetsBinding.instance.window` is inappropriate is if
/// access to these APIs is required before the binding is initialized by
/// invoking `runApp()` or `WidgetsFlutterBinding.instance.ensureInitialized()`.
/// In that case, it is necessary (though unfortunate) to use the
/// [PlatformDispatcher.instance] object statically.
///
/// See also:
///
/// * [PlatformDispatcher.views], contains the current list of Flutter windows
/// belonging to the application, including top level application windows like
/// this one.
final SingletonFlutterWindow window = SingletonFlutterWindow._(0, PlatformDispatcher.instance);
class GestureSettings {
const GestureSettings({
this.physicalTouchSlop,
this.physicalDoubleTapSlop,
});
final double? physicalTouchSlop;
final double? physicalDoubleTapSlop;
GestureSettings copyWith({
double? physicalTouchSlop,
double? physicalDoubleTapSlop,
}) {
return GestureSettings(
physicalTouchSlop: physicalTouchSlop ?? this.physicalTouchSlop,
physicalDoubleTapSlop: physicalDoubleTapSlop ?? this.physicalDoubleTapSlop,
);
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is GestureSettings &&
other.physicalTouchSlop == physicalTouchSlop &&
other.physicalDoubleTapSlop == physicalDoubleTapSlop;
}
@override
int get hashCode => Object.hash(physicalTouchSlop, physicalDoubleTapSlop);
@override
String toString() => 'GestureSettings(physicalTouchSlop: $physicalTouchSlop, physicalDoubleTapSlop: $physicalDoubleTapSlop)';
}