@@ -101,20 +101,45 @@ class PointerSupportDetector {
101101 'pointers:$hasPointerEvents , touch:$hasTouchEvents , mouse:$hasMouseEvents ' ;
102102}
103103
104+ class _PressedButton {
105+ const _PressedButton (this .deviceId, this .button);
106+
107+ // The id of the device pressing the button.
108+ final int deviceId;
109+
110+ // The id of the button being pressed.
111+ final int button;
112+
113+ bool operator == (other) {
114+ if (other is ! _PressedButton ) return false ;
115+ final _PressedButton otherButton = other;
116+ return deviceId == otherButton.deviceId && button == otherButton.button;
117+ }
118+
119+ int get hashCode => ((13801 + deviceId) * 37 ) + button;
120+ }
121+
104122/// Common functionality that's shared among adapters.
105123abstract class BaseAdapter {
106124 static final Map <String , html.EventListener > _listeners =
107125 < String , html.EventListener > {};
108126
109127 final DomRenderer domRenderer;
110128 PointerDataCallback _callback;
111- Map <int , bool > _isDownMap = < int , bool > {};
112- bool _isButtonDown (int button) {
113- return _isDownMap[button] == true ;
129+
130+ // A set of the buttons that are currently being pressed.
131+ Set <_PressedButton > _pressedButtons = Set <_PressedButton >();
132+
133+ bool _isButtonDown (int device, int button) {
134+ return _pressedButtons.contains (_PressedButton (device, button));
114135 }
115136
116- void _updateButtonDownState (int button, bool value) {
117- _isDownMap[button] = value;
137+ void _updateButtonDownState (int device, int button, bool value) {
138+ if (value) {
139+ _pressedButtons.add (_PressedButton (device, button));
140+ } else {
141+ _pressedButtons.remove (_PressedButton (device, button));
142+ }
118143 }
119144
120145 BaseAdapter (this ._callback, this .domRenderer) {
@@ -129,7 +154,7 @@ abstract class BaseAdapter {
129154 void clearListeners () {
130155 final html.Element glassPane = domRenderer.glassPaneElement;
131156 _listeners.forEach ((String eventName, html.EventListener listener) {
132- glassPane.removeEventListener (eventName, listener);
157+ glassPane.removeEventListener (eventName, listener, true );
133158 });
134159 _listeners.clear ();
135160 }
@@ -170,6 +195,14 @@ int _pointerButtonFromHtmlEvent(html.Event event) {
170195 return _kPrimaryMouseButton;
171196}
172197
198+ int _deviceFromHtmlEvent (event) {
199+ if (event is html.PointerEvent ) {
200+ final html.PointerEvent pointerEvent = event;
201+ return pointerEvent.pointerId;
202+ }
203+ return _mouseDeviceId;
204+ }
205+
173206/// Adapter class to be used with browsers that support native pointer events.
174207class PointerAdapter extends BaseAdapter {
175208 PointerAdapter (PointerDataCallback callback, DomRenderer domRenderer)
@@ -179,12 +212,13 @@ class PointerAdapter extends BaseAdapter {
179212 void _setup () {
180213 _addEventListener ('pointerdown' , (html.Event event) {
181214 final int pointerButton = _pointerButtonFromHtmlEvent (event);
182- if (_isButtonDown (pointerButton)) {
215+ final int device = _deviceFromHtmlEvent (event);
216+ if (_isButtonDown (device, pointerButton)) {
183217 // TODO(flutter_web): Remove this temporary fix for right click
184218 // on web platform once context guesture is implemented.
185219 _callback (_convertEventToPointerData (ui.PointerChange .up, event));
186220 }
187- _updateButtonDownState (pointerButton, true );
221+ _updateButtonDownState (device, pointerButton, true );
188222 _callback (_convertEventToPointerData (ui.PointerChange .down, event));
189223 });
190224
@@ -195,8 +229,9 @@ class PointerAdapter extends BaseAdapter {
195229 // Change this when context gesture is implemented in flutter framework.
196230 final html.PointerEvent pointerEvent = event;
197231 final int pointerButton = _pointerButtonFromHtmlEvent (pointerEvent);
232+ final int device = _deviceFromHtmlEvent (event);
198233 final List <ui.PointerData > data = _convertEventToPointerData (
199- _isButtonDown (pointerButton)
234+ _isButtonDown (device, pointerButton)
200235 ? ui.PointerChange .move
201236 : ui.PointerChange .hover,
202237 pointerEvent);
@@ -214,18 +249,20 @@ class PointerAdapter extends BaseAdapter {
214249 // The pointer could have been released by a `pointerout` event, in which
215250 // case `pointerup` should have no effect.
216251 final int pointerButton = _pointerButtonFromHtmlEvent (event);
217- if (! _isButtonDown (pointerButton)) {
252+ final int device = _deviceFromHtmlEvent (event);
253+ if (! _isButtonDown (device, pointerButton)) {
218254 return ;
219255 }
220- _updateButtonDownState (pointerButton, false );
256+ _updateButtonDownState (device, pointerButton, false );
221257 _callback (_convertEventToPointerData (ui.PointerChange .up, event));
222258 });
223259
224260 // A browser fires cancel event if it concludes the pointer will no longer
225261 // be able to generate events (example: device is deactivated)
226262 _addEventListener ('pointercancel' , (html.Event event) {
227263 final int pointerButton = _pointerButtonFromHtmlEvent (event);
228- _updateButtonDownState (pointerButton, false );
264+ final int device = _deviceFromHtmlEvent (event);
265+ _updateButtonDownState (pointerButton, device, false );
229266 _callback (_convertEventToPointerData (ui.PointerChange .cancel, event));
230267 });
231268
@@ -308,13 +345,14 @@ class TouchAdapter extends BaseAdapter {
308345 @override
309346 void _setup () {
310347 _addEventListener ('touchstart' , (html.Event event) {
311- _updateButtonDownState (_kPrimaryMouseButton, true );
348+ _updateButtonDownState (
349+ _deviceFromHtmlEvent (event), _kPrimaryMouseButton, true );
312350 _callback (_convertEventToPointerData (ui.PointerChange .down, event));
313351 });
314352
315353 _addEventListener ('touchmove' , (html.Event event) {
316354 event.preventDefault (); // Prevents standard overscroll on iOS/Webkit.
317- if (! _isButtonDown (_kPrimaryMouseButton)) {
355+ if (! _isButtonDown (_deviceFromHtmlEvent (event), _kPrimaryMouseButton)) {
318356 return ;
319357 }
320358 _callback (_convertEventToPointerData (ui.PointerChange .move, event));
@@ -324,7 +362,8 @@ class TouchAdapter extends BaseAdapter {
324362 // On Safari Mobile, the keyboard does not show unless this line is
325363 // added.
326364 event.preventDefault ();
327- _updateButtonDownState (_kPrimaryMouseButton, false );
365+ _updateButtonDownState (
366+ _deviceFromHtmlEvent (event), _kPrimaryMouseButton, false );
328367 _callback (_convertEventToPointerData (ui.PointerChange .up, event));
329368 });
330369
@@ -372,27 +411,30 @@ class MouseAdapter extends BaseAdapter {
372411 void _setup () {
373412 _addEventListener ('mousedown' , (html.Event event) {
374413 final int pointerButton = _pointerButtonFromHtmlEvent (event);
375- if (_isButtonDown (pointerButton)) {
414+ final int device = _deviceFromHtmlEvent (event);
415+ if (_isButtonDown (device, pointerButton)) {
376416 // TODO(flutter_web): Remove this temporary fix for right click
377417 // on web platform once context guesture is implemented.
378418 _callback (_convertEventToPointerData (ui.PointerChange .up, event));
379419 }
380- _updateButtonDownState (pointerButton, true );
420+ _updateButtonDownState (device, pointerButton, true );
381421 _callback (_convertEventToPointerData (ui.PointerChange .down, event));
382422 });
383423
384424 _addEventListener ('mousemove' , (html.Event event) {
385425 final int pointerButton = _pointerButtonFromHtmlEvent (event);
426+ final int device = _deviceFromHtmlEvent (event);
386427 final List <ui.PointerData > data = _convertEventToPointerData (
387- _isButtonDown (pointerButton)
428+ _isButtonDown (device, pointerButton)
388429 ? ui.PointerChange .move
389430 : ui.PointerChange .hover,
390431 event);
391432 _callback (data);
392433 });
393434
394435 _addEventListener ('mouseup' , (html.Event event) {
395- _updateButtonDownState (_pointerButtonFromHtmlEvent (event), false );
436+ final int device = _deviceFromHtmlEvent (event);
437+ _updateButtonDownState (device, _pointerButtonFromHtmlEvent (event), false );
396438 _callback (_convertEventToPointerData (ui.PointerChange .up, event));
397439 });
398440
0 commit comments