@@ -288,41 +288,81 @@ class _SanitizedDetails {
288288class _ButtonSanitizer {
289289 int _pressedButtons = 0 ;
290290
291- // Transform html.PointerEvent.buttons to Flutter's PointerEvent buttons.
291+ /// Transform [ html.PointerEvent.buttons] to Flutter's PointerEvent buttons.
292292 int _htmlButtonsToFlutterButtons (int buttons) {
293293 // Flutter's button definition conveniently matches that of JavaScript
294294 // from primary button (0x1) to forward button (0x10), which allows us to
295295 // avoid transforming it bit by bit.
296296 return buttons & _kButtonsMask;
297297 }
298298
299- List <_SanitizedDetails > sanitizeDownEvent ({@required int buttons}) {
300- final List <_SanitizedDetails > result = < _SanitizedDetails > [];
301- // TODO(flutter_web): Remove this temporary fix for right click
302- // on web platform once context gesture is implemented.
299+ /// Given [html.PointerEvent.button] and [html.PointerEvent.buttons] , tries to
300+ /// infer the correct value for Flutter buttons.
301+ int _inferDownFlutterButtons (int button, int buttons) {
302+ if (buttons == 0 && button > - 1 ) {
303+ // In some cases, the browser sends `buttons:0` in a down event. In such
304+ // case, we try to infer the value from `button`.
305+ buttons = convertButtonToButtons (button);
306+ }
307+ return _htmlButtonsToFlutterButtons (buttons);
308+ }
309+
310+ List <_SanitizedDetails > sanitizeDownEvent ({
311+ @required int button,
312+ @required int buttons,
313+ }) {
314+ // If the pointer is already down, we just send a move event with the new
315+ // `buttons` value.
303316 if (_pressedButtons != 0 ) {
304- _pressedButtons = 0 ;
305- result.add (_SanitizedDetails (
306- change: ui.PointerChange .up,
307- buttons: 0 ,
308- ));
317+ return sanitizeMoveEvent (buttons: buttons);
309318 }
310- _pressedButtons = _htmlButtonsToFlutterButtons (buttons);
311- result.add (_SanitizedDetails (
312- change: ui.PointerChange .down,
313- buttons: _pressedButtons,
314- ));
315- return result;
319+
320+ _pressedButtons = _inferDownFlutterButtons (button, buttons);
321+ return < _SanitizedDetails > [
322+ _SanitizedDetails (
323+ change: ui.PointerChange .down,
324+ buttons: _pressedButtons,
325+ )
326+ ];
316327 }
317328
318329 List <_SanitizedDetails > sanitizeMoveEvent ({@required int buttons}) {
319- _pressedButtons = _htmlButtonsToFlutterButtons (buttons);
320- return < _SanitizedDetails > [_SanitizedDetails (
321- change: _pressedButtons == 0
322- ? ui.PointerChange .hover
323- : ui.PointerChange .move,
324- buttons: _pressedButtons,
325- )];
330+ final int newPressedButtons = _htmlButtonsToFlutterButtons (buttons);
331+ // This could happen when the context menu is active and the user clicks
332+ // RMB somewhere else. The browser sends a down event with `buttons:0`.
333+ //
334+ // In this case, we keep the old `buttons` value so we don't confuse the
335+ // framework.
336+ if (_pressedButtons != 0 && newPressedButtons == 0 ) {
337+ return < _SanitizedDetails > [
338+ _SanitizedDetails (
339+ change: ui.PointerChange .move,
340+ buttons: _pressedButtons,
341+ )
342+ ];
343+ }
344+
345+ // This could happen when the user clicks RMB then moves the mouse quickly.
346+ // The brower sends a move event with `buttons:2` even though there's no
347+ // buttons down yet.
348+ if (_pressedButtons == 0 && newPressedButtons != 0 ) {
349+ return < _SanitizedDetails > [
350+ _SanitizedDetails (
351+ change: ui.PointerChange .hover,
352+ buttons: _pressedButtons,
353+ )
354+ ];
355+ }
356+
357+ _pressedButtons = newPressedButtons;
358+ return < _SanitizedDetails > [
359+ _SanitizedDetails (
360+ change: _pressedButtons == 0
361+ ? ui.PointerChange .hover
362+ : ui.PointerChange .move,
363+ buttons: _pressedButtons,
364+ )
365+ ];
326366 }
327367
328368 List <_SanitizedDetails > sanitizeUpEvent () {
@@ -396,7 +436,11 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
396436 _addPointerEventListener ('pointerdown' , (html.PointerEvent event) {
397437 final int device = event.pointerId;
398438 final List <ui.PointerData > pointerData = < ui.PointerData > [];
399- final List <_SanitizedDetails > detailsList = _ensureSanitizer (device).sanitizeDownEvent (buttons: event.buttons);
439+ final List <_SanitizedDetails > detailsList =
440+ _ensureSanitizer (device).sanitizeDownEvent (
441+ button: event.button,
442+ buttons: event.buttons,
443+ );
400444 _convertEventsToPointerData (data: pointerData, event: event, detailsList: detailsList);
401445 _callback (pointerData);
402446 });
@@ -697,10 +741,11 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
697741 void setup () {
698742 _addMouseEventListener ('mousedown' , (html.MouseEvent event) {
699743 final List <ui.PointerData > pointerData = < ui.PointerData > [];
700- final bool isStartOfDrag = event.buttons == convertButtonToButtons (event.button);
701- final List <_SanitizedDetails > sanitizedDetails = isStartOfDrag ?
702- _sanitizer.sanitizeDownEvent (buttons: event.buttons) :
703- _sanitizer.sanitizeMoveEvent (buttons: event.buttons);
744+ final List <_SanitizedDetails > sanitizedDetails =
745+ _sanitizer.sanitizeDownEvent (
746+ button: event.button,
747+ buttons: event.buttons,
748+ );
704749 _convertEventsToPointerData (data: pointerData, event: event, detailsList: sanitizedDetails);
705750 _callback (pointerData);
706751 });
0 commit comments