@@ -18,6 +18,7 @@ import 'pointer_binding/event_position_helper.dart';
1818import 'pointer_converter.dart' ;
1919import 'safe_browser_api.dart' ;
2020import 'semantics.dart' ;
21+ import 'window.dart' ;
2122
2223/// Set this flag to true to log all the browser events.
2324const bool _debugLogPointerEvents = false ;
@@ -73,21 +74,31 @@ int convertButtonToButtons(int button) {
7374/// Wrapping the Safari iOS workaround that adds a dummy event listener
7475/// More info about the issue and workaround: https://github.com/flutter/flutter/issues/70858
7576class SafariPointerEventWorkaround {
76- static SafariPointerEventWorkaround instance = SafariPointerEventWorkaround () ;
77+ DomEventListener ? _listener ;
7778
7879 void workAroundMissingPointerEvents () {
79- domDocument.addEventListener ('touchstart' , createDomEventListener ((DomEvent event) {}));
80+ _listener = createDomEventListener ((_) {});
81+ domDocument.addEventListener ('touchstart' , _listener);
82+ }
83+
84+ void dispose () {
85+ if (_listener != null ) {
86+ domDocument.removeEventListener ('touchstart' , _listener);
87+ }
8088 }
8189}
8290
8391class PointerBinding {
8492 PointerBinding (
85- this .flutterViewElement,
86- this ._keyboardConverter, [
87- this ._detector = const PointerSupportDetector (),
88- ]) : _pointerDataConverter = PointerDataConverter () {
93+ this .view,
94+ this ._keyboardConverter, {
95+ PointerSupportDetector detector = const PointerSupportDetector (),
96+ SafariPointerEventWorkaround ? safariWorkaround,
97+ }) : _pointerDataConverter = PointerDataConverter (),
98+ _detector = detector {
8999 if (isIosSafari) {
90- SafariPointerEventWorkaround .instance.workAroundMissingPointerEvents ();
100+ _safariWorkaround = safariWorkaround ?? SafariPointerEventWorkaround ();
101+ _safariWorkaround! .workAroundMissingPointerEvents ();
91102 }
92103 _adapter = _createAdapter ();
93104 }
@@ -96,9 +107,9 @@ class PointerBinding {
96107 static PointerBinding ? get instance => _instance;
97108 static PointerBinding ? _instance;
98109
99- static void initInstance (DomElement flutterViewElement , KeyboardConverter keyboardConverter) {
110+ static void initInstance (EngineFlutterView view , KeyboardConverter keyboardConverter) {
100111 if (_instance == null ) {
101- _instance = PointerBinding (flutterViewElement , keyboardConverter);
112+ _instance = PointerBinding (view , keyboardConverter);
102113 assert (() {
103114 registerHotRestartListener (_instance! .dispose);
104115 return true ;
@@ -108,37 +119,28 @@ class PointerBinding {
108119
109120 final ClickDebouncer clickDebouncer = ClickDebouncer ();
110121
122+ SafariPointerEventWorkaround ? _safariWorkaround;
123+
111124 /// Performs necessary clean up for PointerBinding including removing event listeners
112125 /// and clearing the existing pointer state
113126 void dispose () {
114- _adapter.clearListeners ();
127+ _adapter.dispose ();
115128 _pointerDataConverter.clearPointerState ();
129+ _safariWorkaround? .dispose ();
116130 clickDebouncer.reset ();
117131 }
118132
119- final DomElement flutterViewElement;
133+ final EngineFlutterView view;
134+ DomElement get rootElement => view.dom.rootElement;
120135
121136 final PointerSupportDetector _detector;
122137 final PointerDataConverter _pointerDataConverter;
123- KeyboardConverter _keyboardConverter;
138+ final KeyboardConverter _keyboardConverter;
124139 late _BaseAdapter _adapter;
125140
126- @visibleForTesting
127- void debugReset () {
128- _adapter.clearListeners ();
129- _adapter = _createAdapter ();
130- _pointerDataConverter.clearPointerState ();
131- }
132-
133- @visibleForTesting
134- void debugOverrideKeyboardConverter (KeyboardConverter keyboardConverter) {
135- _keyboardConverter = keyboardConverter;
136- debugReset ();
137- }
138-
139141 _BaseAdapter _createAdapter () {
140142 if (_detector.hasPointerEvents) {
141- return _PointerAdapter (clickDebouncer.onPointerData, flutterViewElement , _pointerDataConverter, _keyboardConverter);
143+ return _PointerAdapter (clickDebouncer.onPointerData, view , _pointerDataConverter, _keyboardConverter);
142144 }
143145 throw UnsupportedError (
144146 'This browser does not support pointer events which '
@@ -470,27 +472,29 @@ class _Listener {
470472abstract class _BaseAdapter {
471473 _BaseAdapter (
472474 this ._callback,
473- this .flutterViewElement ,
475+ this ._view ,
474476 this ._pointerDataConverter,
475477 this ._keyboardConverter,
476478 ) {
477479 setup ();
478480 }
479481
480482 final List <_Listener > _listeners = < _Listener > [];
481- final DomElement flutterViewElement ;
483+ final EngineFlutterView _view ;
482484 final _PointerDataCallback _callback;
483485 final PointerDataConverter _pointerDataConverter;
484486 final KeyboardConverter _keyboardConverter;
485487 DomWheelEvent ? _lastWheelEvent;
486488 bool _lastWheelEventWasTrackpad = false ;
487489
490+ DomElement get _rootElement => _view.dom.rootElement;
491+
488492 /// Each subclass is expected to override this method to attach its own event
489493 /// listeners and convert events into pointer events.
490494 void setup ();
491495
492- /// Remove all active event listeners.
493- void clearListeners () {
496+ /// Cleans up all event listeners attached by this adapter .
497+ void dispose () {
494498 for (final _Listener listener in _listeners) {
495499 listener.unregister ();
496500 }
@@ -499,7 +503,7 @@ abstract class _BaseAdapter {
499503
500504 /// Adds a listener for the given [eventName] to [target] .
501505 ///
502- /// Generally speaking, down and leave events should use [flutterViewElement ]
506+ /// Generally speaking, down and leave events should use [_rootElement ]
503507 /// as the [target] , while move and up events should use [domWindow]
504508 /// instead, because the browser doesn't fire the latter two for DOM elements
505509 /// when the pointer is outside the window.
@@ -512,7 +516,7 @@ abstract class _BaseAdapter {
512516 if (_debugLogPointerEvents) {
513517 if (domInstanceOfString (event, 'PointerEvent' )) {
514518 final DomPointerEvent pointerEvent = event as DomPointerEvent ;
515- final ui.Offset offset = computeEventOffsetToTarget (event, flutterViewElement );
519+ final ui.Offset offset = computeEventOffsetToTarget (event, _view );
516520 print ('${pointerEvent .type } '
517521 '${offset .dx .toStringAsFixed (1 )},'
518522 '${offset .dy .toStringAsFixed (1 )}' );
@@ -636,25 +640,25 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
636640 deltaX *= _defaultScrollLineHeight! ;
637641 deltaY *= _defaultScrollLineHeight! ;
638642 case domDeltaPage:
639- deltaX *= ui.window .physicalSize.width;
640- deltaY *= ui.window .physicalSize.height;
643+ deltaX *= _view .physicalSize.width;
644+ deltaY *= _view .physicalSize.height;
641645 case domDeltaPixel:
642646 if (operatingSystem == OperatingSystem .macOs && (isSafari || isFirefox)) {
643647 // Safari and Firefox seem to report delta in logical pixels while
644648 // Chrome uses physical pixels.
645- deltaX *= ui.window .devicePixelRatio;
646- deltaY *= ui.window .devicePixelRatio;
649+ deltaX *= _view .devicePixelRatio;
650+ deltaY *= _view .devicePixelRatio;
647651 }
648652 default :
649653 break ;
650654 }
651655
652656 final List <ui.PointerData > data = < ui.PointerData > [];
653- final ui.Offset offset = computeEventOffsetToTarget (event, flutterViewElement );
657+ final ui.Offset offset = computeEventOffsetToTarget (event, _view );
654658 bool ignoreCtrlKey = false ;
655659 if (operatingSystem == OperatingSystem .macOs) {
656- ignoreCtrlKey = (KeyboardBinding .instance ? .converter. keyIsPressed (kPhysicalControlLeft) ?? false ) ||
657- (KeyboardBinding .instance ? .converter. keyIsPressed (kPhysicalControlRight) ?? false );
660+ ignoreCtrlKey = (_keyboardConverter. keyIsPressed (kPhysicalControlLeft)) ||
661+ (_keyboardConverter. keyIsPressed (kPhysicalControlRight));
658662 }
659663 if (event.ctrlKey && ! ignoreCtrlKey) {
660664 _pointerDataConverter.convert (
@@ -664,8 +668,8 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
664668 kind: kind,
665669 signalKind: ui.PointerSignalKind .scale,
666670 device: deviceId,
667- physicalX: offset.dx * ui.window .devicePixelRatio,
668- physicalY: offset.dy * ui.window .devicePixelRatio,
671+ physicalX: offset.dx * _view .devicePixelRatio,
672+ physicalY: offset.dy * _view .devicePixelRatio,
669673 buttons: event.buttons! .toInt (),
670674 pressure: 1.0 ,
671675 pressureMax: 1.0 ,
@@ -679,8 +683,8 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
679683 kind: kind,
680684 signalKind: ui.PointerSignalKind .scroll,
681685 device: deviceId,
682- physicalX: offset.dx * ui.window .devicePixelRatio,
683- physicalY: offset.dy * ui.window .devicePixelRatio,
686+ physicalX: offset.dx * _view .devicePixelRatio,
687+ physicalY: offset.dy * _view .devicePixelRatio,
684688 buttons: event.buttons! .toInt (),
685689 pressure: 1.0 ,
686690 pressureMax: 1.0 ,
@@ -696,7 +700,7 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
696700 void _addWheelEventListener (DartDomEventListener handler) {
697701 _listeners.add (_Listener .register (
698702 event: 'wheel' ,
699- target: flutterViewElement ,
703+ target: _rootElement ,
700704 handler: handler,
701705 passive: false ,
702706 ));
@@ -886,7 +890,7 @@ typedef _PointerEventListener = dynamic Function(DomPointerEvent event);
886890class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
887891 _PointerAdapter (
888892 super .callback,
889- super .flutterViewElement ,
893+ super .view ,
890894 super .pointerDataConverter,
891895 super .keyboardConverter,
892896 );
@@ -942,7 +946,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
942946
943947 @override
944948 void setup () {
945- _addPointerEventListener (flutterViewElement , 'pointerdown' , (DomPointerEvent event) {
949+ _addPointerEventListener (_rootElement , 'pointerdown' , (DomPointerEvent event) {
946950 final int device = _getPointerId (event);
947951 final List <ui.PointerData > pointerData = < ui.PointerData > [];
948952 final _ButtonSanitizer sanitizer = _ensureSanitizer (device);
@@ -977,7 +981,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
977981 _callback (event, pointerData);
978982 });
979983
980- _addPointerEventListener (flutterViewElement , 'pointerleave' , (DomPointerEvent event) {
984+ _addPointerEventListener (_rootElement , 'pointerleave' , (DomPointerEvent event) {
981985 final int device = _getPointerId (event);
982986 final _ButtonSanitizer sanitizer = _ensureSanitizer (device);
983987 final List <ui.PointerData > pointerData = < ui.PointerData > [];
@@ -1006,7 +1010,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
10061010
10071011 // A browser fires cancel event if it concludes the pointer will no longer
10081012 // be able to generate events (example: device is deactivated)
1009- _addPointerEventListener (flutterViewElement , 'pointercancel' , (DomPointerEvent event) {
1013+ _addPointerEventListener (_rootElement , 'pointercancel' , (DomPointerEvent event) {
10101014 final int device = _getPointerId (event);
10111015 if (_hasSanitizer (device)) {
10121016 final List <ui.PointerData > pointerData = < ui.PointerData > [];
@@ -1033,16 +1037,16 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
10331037 final double tilt = _computeHighestTilt (event);
10341038 final Duration timeStamp = _BaseAdapter ._eventTimeStampToDuration (event.timeStamp! );
10351039 final num ? pressure = event.pressure;
1036- final ui.Offset offset = computeEventOffsetToTarget (event, flutterViewElement );
1040+ final ui.Offset offset = computeEventOffsetToTarget (event, _view );
10371041 _pointerDataConverter.convert (
10381042 data,
10391043 change: details.change,
10401044 timeStamp: timeStamp,
10411045 kind: kind,
10421046 signalKind: ui.PointerSignalKind .none,
10431047 device: _getPointerId (event),
1044- physicalX: offset.dx * ui.window .devicePixelRatio,
1045- physicalY: offset.dy * ui.window .devicePixelRatio,
1048+ physicalX: offset.dx * _view .devicePixelRatio,
1049+ physicalY: offset.dy * _view .devicePixelRatio,
10461050 buttons: details.buttons,
10471051 pressure: pressure == null ? 0.0 : pressure.toDouble (),
10481052 pressureMax: 1.0 ,
0 commit comments