diff --git a/lib/ui/fixtures/ui_test.dart b/lib/ui/fixtures/ui_test.dart index 09caf203097dd..0aff1775688b7 100644 --- a/lib/ui/fixtures/ui_test.dart +++ b/lib/ui/fixtures/ui_test.dart @@ -539,33 +539,7 @@ void hooksTests() async { }); await test('PlatformDispatcher.view getter returns view with provided ID', () { - const int viewId = 123456789; - _callHook( - '_updateWindowMetrics', - 21, - viewId, // window Id - 1.0, // devicePixelRatio - 800.0, // width - 600.0, // height - 50.0, // paddingTop - 0.0, // paddingRight - 40.0, // paddingBottom - 0.0, // paddingLeft - 0.0, // insetTop - 0.0, // insetRight - 0.0, // insetBottom - 0.0, // insetLeft - 0.0, // systemGestureInsetTop - 0.0, // systemGestureInsetRight - 0.0, // systemGestureInsetBottom - 0.0, // systemGestureInsetLeft - 22.0, // physicalTouchSlop - [], // display features bounds - [], // display features types - [], // display features states - 0, // Display ID - ); - + const int viewId = 0; expectEquals(PlatformDispatcher.instance.view(id: viewId)?.viewId, viewId); }); diff --git a/lib/ui/platform_dispatcher.dart b/lib/ui/platform_dispatcher.dart index 47eb65cab3363..d529fac09e1d7 100644 --- a/lib/ui/platform_dispatcher.dart +++ b/lib/ui/platform_dispatcher.dart @@ -66,6 +66,14 @@ typedef ErrorCallback = bool Function(Object exception, StackTrace stackTrace); // A gesture setting value that indicates it has not been set by the engine. const double _kUnsetGestureSetting = -1.0; +// The view ID of PlatformDispatcher.implicitView. This is an +// implementation detail that may change at any time. Apps +// should always use PlatformDispatcher.implicitView to determine +// the current implicit view, if any. +// +// Keep this in sync with kImplicitViewId in window/platform_configuration.cc. +const int _kImplicitViewId = 0; + // A message channel to receive KeyData from the platform. // // See embedder.cc::kFlutterKeyDataChannel for more information. @@ -185,9 +193,6 @@ class PlatformDispatcher { /// otherwise. FlutterView? view({required int id}) => _views[id]; - // A map of opaque platform view identifiers to view configurations. - final Map _viewConfigurations = {}; - /// The [FlutterView] provided by the engine if the platform is unable to /// create windows, or, for backwards compatibility. /// @@ -213,7 +218,7 @@ class PlatformDispatcher { /// * [View.of], for accessing the current view. /// * [PlatformDispatcher.views] for a list of all [FlutterView]s provided /// by the platform. - FlutterView? get implicitView => _implicitViewEnabled() ? _views[0] : null; + FlutterView? get implicitView => _implicitViewEnabled() ? _views[_kImplicitViewId] : null; @Native(symbol: 'PlatformConfigurationNativeApi::ImplicitViewEnabled') external static bool _implicitViewEnabled(); @@ -281,13 +286,7 @@ class PlatformDispatcher { List displayFeaturesState, int displayId, ) { - final _ViewConfiguration previousConfiguration = - _viewConfigurations[id] ?? const _ViewConfiguration(); - if (!_views.containsKey(id)) { - _views[id] = FlutterView._(id, this); - } - _viewConfigurations[id] = previousConfiguration.copyWith( - view: _views[id], + final _ViewConfiguration viewConfiguration = _ViewConfiguration( devicePixelRatio: devicePixelRatio, geometry: Rect.fromLTWH(0.0, 0.0, width, height), viewPadding: ViewPadding._( @@ -314,7 +313,6 @@ class PlatformDispatcher { bottom: math.max(0.0, systemGestureInsetBottom), left: math.max(0.0, systemGestureInsetLeft), ), - // -1 is used as a sentinel for an undefined touch slop gestureSettings: GestureSettings( physicalTouchSlop: physicalTouchSlop == _kUnsetGestureSetting ? null : physicalTouchSlop, ), @@ -326,6 +324,17 @@ class PlatformDispatcher { ), displayId: displayId, ); + + final FlutterView? view = _views[id]; + if (id == _kImplicitViewId && view == null) { + // TODO(goderbauer): Remove the implicit creation of the implicit view + // when we have an addView API and the implicit view is added via that. + _views[id] = FlutterView._(id, this, viewConfiguration); + } else { + assert(view != null); + view!._viewConfiguration = viewConfiguration; + } + _invoke(onMetricsChanged, _onMetricsChangedZone); } @@ -1362,10 +1371,8 @@ class _PlatformConfiguration { /// An immutable view configuration. class _ViewConfiguration { const _ViewConfiguration({ - this.view, this.devicePixelRatio = 1.0, this.geometry = Rect.zero, - this.visible = false, this.viewInsets = ViewPadding.zero, this.viewPadding = ViewPadding.zero, this.systemGestureInsets = ViewPadding.zero, @@ -1375,37 +1382,6 @@ class _ViewConfiguration { this.displayId = 0, }); - /// Copy this configuration with some fields replaced. - _ViewConfiguration copyWith({ - FlutterView? view, - double? devicePixelRatio, - Rect? geometry, - bool? visible, - ViewPadding? viewInsets, - ViewPadding? viewPadding, - ViewPadding? systemGestureInsets, - ViewPadding? padding, - GestureSettings? gestureSettings, - List? displayFeatures, - int? displayId, - }) { - return _ViewConfiguration( - view: view ?? this.view, - devicePixelRatio: devicePixelRatio ?? this.devicePixelRatio, - geometry: geometry ?? this.geometry, - visible: visible ?? this.visible, - viewInsets: viewInsets ?? this.viewInsets, - viewPadding: viewPadding ?? this.viewPadding, - systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets, - padding: padding ?? this.padding, - gestureSettings: gestureSettings ?? this.gestureSettings, - displayFeatures: displayFeatures ?? this.displayFeatures, - displayId: displayId ?? this.displayId, - ); - } - - final FlutterView? view; - /// The identifier for a display for this view, in /// [PlatformDispatcher._displays]. final int displayId; @@ -1417,9 +1393,6 @@ class _ViewConfiguration { /// window, in logical pixels. final Rect geometry; - /// Whether or not the view is currently visible on the screen. - final bool visible; - /// The number of physical pixels on each side of the display rectangle into /// which the view can render, but over which the operating system will likely /// place system UI, such as the keyboard, that fully obscures any content. @@ -1488,7 +1461,7 @@ class _ViewConfiguration { @override String toString() { - return '$runtimeType[view: $view, geometry: $geometry]'; + return '$runtimeType[geometry: $geometry]'; } } diff --git a/lib/ui/window.dart b/lib/ui/window.dart index 321e1a792aa9f..63b7f74b8b5a7 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -86,7 +86,7 @@ class Display { /// that in the [padding], which is always safe to use for such /// calculations. class FlutterView { - FlutterView._(this.viewId, this.platformDispatcher); + FlutterView._(this.viewId, this.platformDispatcher, this._viewConfiguration); /// The opaque ID for this view. final int viewId; @@ -96,10 +96,8 @@ class FlutterView { final PlatformDispatcher platformDispatcher; /// The configuration of this view. - _ViewConfiguration get _viewConfiguration { - assert(platformDispatcher._viewConfigurations.containsKey(viewId)); - return platformDispatcher._viewConfigurations[viewId]!; - } + // TODO(goderbauer): remove ignore when https://github.com/dart-lang/linter/issues/4562 is fixed. + _ViewConfiguration _viewConfiguration; // ignore: prefer_final_fields /// The [Display] this view is drawn in. Display get display { @@ -373,6 +371,9 @@ class FlutterView { @Native)>(symbol: 'PlatformConfigurationNativeApi::UpdateSemantics') external static void _updateSemantics(_NativeSemanticsUpdate update); + + @override + String toString() => 'FlutterView(id: $viewId)'; } /// Deprecated. Will be removed in a future version of Flutter. @@ -405,8 +406,15 @@ class SingletonFlutterWindow extends FlutterView { 'Deprecated to prepare for the upcoming multi-window support. ' 'This feature was deprecated after v3.7.0-32.0.pre.' ) - SingletonFlutterWindow._(super.windowId, super.platformDispatcher) - : super._(); + SingletonFlutterWindow._() : super._( + _kImplicitViewId, + PlatformDispatcher.instance, + const _ViewConfiguration(), + ); + + // Gets its configuration from the FlutterView with the same ID if it exists. + @override + _ViewConfiguration get _viewConfiguration => platformDispatcher._views[viewId]?._viewConfiguration ?? super._viewConfiguration; /// A callback that is invoked whenever the [devicePixelRatio], /// [physicalSize], [padding], [viewInsets], [PlatformDispatcher.views], or @@ -1016,7 +1024,7 @@ enum Brightness { 'Deprecated to prepare for the upcoming multi-window support. ' 'This feature was deprecated after v3.7.0-32.0.pre.' ) -final SingletonFlutterWindow window = SingletonFlutterWindow._(0, PlatformDispatcher.instance); +final SingletonFlutterWindow window = SingletonFlutterWindow._(); /// Additional data available on each flutter frame. class FrameData { diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index fe6ff03d62b69..8d11b747fd53b 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -22,6 +22,7 @@ namespace flutter { namespace { +// Keep this in sync with _kImplicitViewId in ../platform_dispatcher.dart. constexpr int kImplicitViewId = 0; Dart_Handle ToByteData(const fml::Mapping& buffer) { diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index f51c6501cf29c..a0c98c441ea3e 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -89,4 +89,10 @@ void main() { expect(display.refreshRate, 60); expect(display.size, implicitView.physicalSize); }); + + test('FlutterView.toString contains the viewId', () { + final FlutterView flutterView = PlatformDispatcher.instance.implicitView!; + expect(flutterView.viewId, 0); + expect(flutterView.toString(), 'FlutterView(id: 0)'); + }); }