-
Notifications
You must be signed in to change notification settings - Fork 6k
[web] De-singletonize MouseCursor for multi-view #45295
Changes from 5 commits
231aedd
f4b93f7
6348d51
567299e
b803c12
c109a91
b29c5f6
1b949ec
48c2216
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,8 @@ import 'package:ui/ui_web/src/ui_web.dart' as ui_web; | |
| import '../engine.dart' show DimensionsProvider, registerHotRestartListener, renderer; | ||
| import 'display.dart'; | ||
| import 'dom.dart'; | ||
| import 'embedder.dart'; | ||
| import 'mouse/cursor.dart'; | ||
| import 'navigation/history.dart'; | ||
| import 'platform_dispatcher.dart'; | ||
| import 'services.dart'; | ||
|
|
@@ -29,8 +31,17 @@ const bool debugPrintPlatformMessages = false; | |
| /// The view ID for the implicit flutter view provided by the platform. | ||
| const int kImplicitViewId = 0; | ||
|
|
||
| /// Represents all views in the Flutter Web Engine. | ||
| /// | ||
| /// In addition to everything defined in [ui.FlutterView], this class adds | ||
| /// a few web-specific properties. | ||
| abstract class EngineFlutterView extends ui.FlutterView { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this interface here, but I don't think it needs to Also, I think this should be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thought here was that So the hierarchy becomes:
We can! We already use it in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahhh, I gotcha. The advantage of the current version:
Is that we're only extending the base classes defined by the core of the engine. In my mind that means that if there's an upcoming change in the base structure of classes in package:ui, it should be easier for (Of course, it depends on the changes, so our class extensions might not matter too much!) |
||
| MouseCursor get mouseCursor; | ||
| DomElement get rootElement; | ||
| } | ||
|
|
||
| /// The Web implementation of [ui.SingletonFlutterWindow]. | ||
| class EngineFlutterWindow extends ui.SingletonFlutterWindow { | ||
| class EngineFlutterWindow extends ui.SingletonFlutterWindow implements EngineFlutterView { | ||
| EngineFlutterWindow(this.viewId, this.platformDispatcher) { | ||
| platformDispatcher.viewData[viewId] = this; | ||
| platformDispatcher.windowConfigurations[viewId] = const ViewConfiguration(); | ||
|
|
@@ -53,6 +64,12 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow { | |
| @override | ||
| final EnginePlatformDispatcher platformDispatcher; | ||
|
|
||
| @override | ||
| late final MouseCursor mouseCursor = MouseCursor(this); | ||
|
ditman marked this conversation as resolved.
Outdated
|
||
|
|
||
| @override | ||
| DomElement get rootElement => flutterViewEmbedder.flutterViewElement; | ||
|
|
||
| /// Handles the browser history integration to allow users to use the back | ||
| /// button, etc. | ||
| BrowserHistory get browserHistory { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| // 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. | ||
|
|
||
| import 'package:test/bootstrap/browser.dart'; | ||
| import 'package:test/test.dart'; | ||
| import 'package:ui/src/engine.dart'; | ||
| import 'package:ui/ui.dart' as ui; | ||
|
|
||
| void main() { | ||
| internalBootstrapBrowserTest(() => testMain); | ||
| } | ||
|
|
||
| void testMain() { | ||
| group('$MouseCursor', () { | ||
| test('sets correct `cursor` style on root element', () { | ||
| final DomElement rootViewElement = createDomElement('div'); | ||
| final MockFlutterView view = MockFlutterView() | ||
| ..rootElement = rootViewElement; | ||
| final MouseCursor mouseCursor = MouseCursor(view); | ||
|
|
||
| mouseCursor.activateSystemCursor('alias'); | ||
| expect(rootViewElement.style.cursor, 'alias'); | ||
|
|
||
| mouseCursor.activateSystemCursor('move'); | ||
| expect(rootViewElement.style.cursor, 'move'); | ||
|
|
||
| mouseCursor.activateSystemCursor('precise'); | ||
| expect(rootViewElement.style.cursor, 'crosshair'); | ||
|
|
||
| mouseCursor.activateSystemCursor('resizeDownRight'); | ||
| expect(rootViewElement.style.cursor, 'se-resize'); | ||
| }); | ||
|
|
||
| test('handles unknown cursor type', () { | ||
| final DomElement rootViewElement = createDomElement('div'); | ||
| final MockFlutterView view = MockFlutterView() | ||
| ..rootElement = rootViewElement; | ||
| final MouseCursor mouseCursor = MouseCursor(view); | ||
|
|
||
| mouseCursor.activateSystemCursor('unknown'); | ||
| expect(rootViewElement.style.cursor, 'default'); | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| class MockFlutterView implements EngineFlutterView { | ||
| @override | ||
| late DomElement rootElement; | ||
|
|
||
| @override | ||
| double get devicePixelRatio => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ui.Display get display => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| List<ui.DisplayFeature> get displayFeatures => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ui.GestureSettings get gestureSettings => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| MouseCursor get mouseCursor => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ViewPadding get padding => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ui.Rect get physicalGeometry => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ui.Size get physicalSize => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ui.PlatformDispatcher get platformDispatcher => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| void render(ui.Scene scene) { | ||
| throw UnimplementedError(); | ||
| } | ||
|
|
||
| @override | ||
| ViewPadding get systemGestureInsets => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| void updateSemantics(ui.SemanticsUpdate update) { | ||
| throw UnimplementedError(); | ||
| } | ||
|
|
||
| @override | ||
| int get viewId => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ViewPadding get viewInsets => throw UnimplementedError(); | ||
|
|
||
| @override | ||
| ViewPadding get viewPadding => throw UnimplementedError(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the class that represents all views in the Flutter Web Engine is
EngineFlutterWindow(that's the type that was used to define theimplicitView, for example), right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EngineFlutterWindowis a misnomer. It should be calledEngineSingletonFlutterWindow(it actually extendsui.SingletonFlutterWindow). Views in the multi-view world shouldn't inherit from this singleton class. They should inherit directly fromui.FlutterView(and implementEngineFlutterViewto satisfy all the web-specific needs).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a follow up PR to rename this class to make it clear that it's a singleton: #45981