55import 'dart:math' as math;
66
77import 'package:meta/meta.dart' ;
8+ import 'package:ui/src/engine/keyboard_binding.dart' ;
89import 'package:ui/ui.dart' as ui;
910
1011import '../engine.dart' show registerHotRestartListener;
@@ -73,7 +74,7 @@ class SafariPointerEventWorkaround {
7374}
7475
7576class PointerBinding {
76- PointerBinding (this .glassPaneElement)
77+ PointerBinding (this .glassPaneElement, this ._keyboardConverter )
7778 : _pointerDataConverter = PointerDataConverter (),
7879 _detector = const PointerSupportDetector () {
7980 if (isIosSafari) {
@@ -86,9 +87,9 @@ class PointerBinding {
8687 static PointerBinding ? get instance => _instance;
8788 static PointerBinding ? _instance;
8889
89- static void initInstance (DomElement glassPaneElement) {
90+ static void initInstance (DomElement glassPaneElement, KeyboardConverter keyboardConverter ) {
9091 if (_instance == null ) {
91- _instance = PointerBinding (glassPaneElement);
92+ _instance = PointerBinding (glassPaneElement, keyboardConverter );
9293 assert (() {
9394 registerHotRestartListener (_instance! .dispose);
9495 return true ;
@@ -107,6 +108,7 @@ class PointerBinding {
107108
108109 PointerSupportDetector _detector;
109110 final PointerDataConverter _pointerDataConverter;
111+ KeyboardConverter _keyboardConverter;
110112 late _BaseAdapter _adapter;
111113
112114 /// Should be used in tests to define custom detection of pointer support.
@@ -137,15 +139,23 @@ class PointerBinding {
137139 }
138140 }
139141
142+ @visibleForTesting
143+ void debugOverrideKeyboardConverter (KeyboardConverter keyboardConverter) {
144+ _keyboardConverter = keyboardConverter;
145+ _adapter.clearListeners ();
146+ _adapter = _createAdapter ();
147+ _pointerDataConverter.clearPointerState ();
148+ }
149+
140150 _BaseAdapter _createAdapter () {
141151 if (_detector.hasPointerEvents) {
142- return _PointerAdapter (_onPointerData, glassPaneElement, _pointerDataConverter);
152+ return _PointerAdapter (_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter );
143153 }
144154 if (_detector.hasTouchEvents) {
145- return _TouchAdapter (_onPointerData, glassPaneElement, _pointerDataConverter);
155+ return _TouchAdapter (_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter );
146156 }
147157 if (_detector.hasMouseEvents) {
148- return _MouseAdapter (_onPointerData, glassPaneElement, _pointerDataConverter);
158+ return _MouseAdapter (_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter );
149159 }
150160 throw UnsupportedError ('This browser does not support pointer, touch, or mouse events.' );
151161 }
@@ -239,14 +249,20 @@ class _Listener {
239249
240250/// Common functionality that's shared among adapters.
241251abstract class _BaseAdapter {
242- _BaseAdapter (this ._callback, this .glassPaneElement, this ._pointerDataConverter) {
252+ _BaseAdapter (
253+ this ._callback,
254+ this .glassPaneElement,
255+ this ._pointerDataConverter,
256+ this ._keyboardConverter,
257+ ) {
243258 setup ();
244259 }
245260
246261 final List <_Listener > _listeners = < _Listener > [];
247262 final DomElement glassPaneElement;
248263 final _PointerDataCallback _callback;
249264 final PointerDataConverter _pointerDataConverter;
265+ final KeyboardConverter _keyboardConverter;
250266
251267 /// Each subclass is expected to override this method to attach its own event
252268 /// listeners and convert events into pointer events.
@@ -570,7 +586,8 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
570586 _PointerAdapter (
571587 super .callback,
572588 super .glassPaneElement,
573- super .pointerDataConverter
589+ super .pointerDataConverter,
590+ super .keyboardConverter,
574591 );
575592
576593 final Map <int , _ButtonSanitizer > _sanitizers = < int , _ButtonSanitizer > {};
@@ -602,13 +619,27 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
602619 String eventName,
603620 _PointerEventListener handler, {
604621 bool useCapture = true ,
622+ bool checkModifiers = true ,
605623 }) {
606624 addEventListener (target, eventName, (DomEvent event) {
607625 final DomPointerEvent pointerEvent = event as DomPointerEvent ;
626+ if (checkModifiers) {
627+ _checkModifiersState (event);
628+ }
608629 handler (pointerEvent);
609630 }, useCapture: useCapture);
610631 }
611632
633+ void _checkModifiersState (DomPointerEvent event) {
634+ _keyboardConverter.synthesizeModifiersIfNeeded (
635+ event.getModifierState ('Alt' ),
636+ event.getModifierState ('Control' ),
637+ event.getModifierState ('Meta' ),
638+ event.getModifierState ('Shift' ),
639+ event.timeStamp! ,
640+ );
641+ }
642+
612643 @override
613644 void setup () {
614645 _addPointerEventListener (glassPaneElement, 'pointerdown' , (DomPointerEvent event) {
@@ -654,7 +685,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
654685 _convertEventsToPointerData (data: pointerData, event: event, details: details);
655686 _callback (pointerData);
656687 }
657- }, useCapture: false );
688+ }, useCapture: false , checkModifiers : false );
658689
659690 _addPointerEventListener (domWindow, 'pointerup' , (DomPointerEvent event) {
660691 final int device = _getPointerId (event);
@@ -680,7 +711,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
680711 _convertEventsToPointerData (data: pointerData, event: event, details: details);
681712 _callback (pointerData);
682713 }
683- });
714+ }, checkModifiers : false );
684715
685716 _addWheelEventListener ((DomEvent event) {
686717 _handleWheelEvent (event);
@@ -767,21 +798,35 @@ class _TouchAdapter extends _BaseAdapter {
767798 _TouchAdapter (
768799 super .callback,
769800 super .glassPaneElement,
770- super .pointerDataConverter
801+ super .pointerDataConverter,
802+ super .keyboardConverter,
771803 );
772804
773805 final Set <int > _pressedTouches = < int > {};
774806 bool _isTouchPressed (int identifier) => _pressedTouches.contains (identifier);
775807 void _pressTouch (int identifier) { _pressedTouches.add (identifier); }
776808 void _unpressTouch (int identifier) { _pressedTouches.remove (identifier); }
777809
778- void _addTouchEventListener (DomEventTarget target, String eventName, _TouchEventListener handler) {
810+ void _addTouchEventListener (DomEventTarget target, String eventName, _TouchEventListener handler, { bool checkModifiers = true ,} ) {
779811 addEventListener (target, eventName, (DomEvent event) {
780812 final DomTouchEvent touchEvent = event as DomTouchEvent ;
813+ if (checkModifiers) {
814+ _checkModifiersState (event);
815+ }
781816 handler (touchEvent);
782817 });
783818 }
784819
820+ void _checkModifiersState (DomTouchEvent event) {
821+ _keyboardConverter.synthesizeModifiersIfNeeded (
822+ event.altKey,
823+ event.ctrlKey,
824+ event.metaKey,
825+ event.shiftKey,
826+ event.timeStamp! ,
827+ );
828+ }
829+
785830 @override
786831 void setup () {
787832 _addTouchEventListener (glassPaneElement, 'touchstart' , (DomTouchEvent event) {
@@ -910,7 +955,8 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
910955 _MouseAdapter (
911956 super .callback,
912957 super .glassPaneElement,
913- super .pointerDataConverter
958+ super .pointerDataConverter,
959+ super .keyboardConverter,
914960 );
915961
916962 final _ButtonSanitizer _sanitizer = _ButtonSanitizer ();
@@ -920,13 +966,27 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
920966 String eventName,
921967 _MouseEventListener handler, {
922968 bool useCapture = true ,
969+ bool checkModifiers = true ,
923970 }) {
924971 addEventListener (target, eventName, (DomEvent event) {
925972 final DomMouseEvent mouseEvent = event as DomMouseEvent ;
973+ if (checkModifiers) {
974+ _checkModifiersState (event);
975+ }
926976 handler (mouseEvent);
927977 }, useCapture: useCapture);
928978 }
929979
980+ void _checkModifiersState (DomMouseEvent event) {
981+ _keyboardConverter.synthesizeModifiersIfNeeded (
982+ event.getModifierState ('Alt' ),
983+ event.getModifierState ('Control' ),
984+ event.getModifierState ('Meta' ),
985+ event.getModifierState ('Shift' ),
986+ event.timeStamp! ,
987+ );
988+ }
989+
930990 @override
931991 void setup () {
932992 _addMouseEventListener (glassPaneElement, 'mousedown' , (DomMouseEvent event) {
0 commit comments