[Web] Synthesize key events for shift key on pointer events. (flutter/engine#36724)

This commit is contained in:
Bruno Leroux 2022-10-21 08:02:14 +02:00 committed by GitHub
parent b938b28387
commit 31b251007a
4 changed files with 449 additions and 21 deletions

View File

@ -323,8 +323,8 @@ class FlutterViewEmbedder {
_sceneHostElement!.style.opacity = '0.3';
}
PointerBinding.initInstance(glassPaneElement);
KeyboardBinding.initInstance();
PointerBinding.initInstance(glassPaneElement, KeyboardBinding.instance!.converter);
if (domWindow.visualViewport == null && isWebKit) {
// Older Safari versions sometimes give us bogus innerWidth/innerHeight

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;
import '../engine.dart' show registerHotRestartListener;
@ -30,6 +31,16 @@ final int _kLogicalShiftLeft = kWebLogicalLocationMap['Shift']![_kLocationLeft]!
final int _kLogicalShiftRight = kWebLogicalLocationMap['Shift']![_kLocationRight]!;
final int _kLogicalMetaLeft = kWebLogicalLocationMap['Meta']![_kLocationLeft]!;
final int _kLogicalMetaRight = kWebLogicalLocationMap['Meta']![_kLocationRight]!;
final int _kPhysicalAltLeft = kWebToPhysicalKey['AltLeft']!;
final int _kPhysicalAltRight = kWebToPhysicalKey['AltRight']!;
final int _kPhysicalControlLeft = kWebToPhysicalKey['ControlLeft']!;
final int _kPhysicalControlRight = kWebToPhysicalKey['ControlRight']!;
final int _kPhysicalShiftLeft = kWebToPhysicalKey['ShiftLeft']!;
final int _kPhysicalShiftRight = kWebToPhysicalKey['ShiftRight']!;
final int _kPhysicalMetaLeft = kWebToPhysicalKey['MetaLeft']!;
final int _kPhysicalMetaRight = kWebToPhysicalKey['MetaRight']!;
// Map logical keys for modifier keys to the functions that can get their
// modifier flag out of an event.
final Map<int, _ModifierGetter> _kLogicalKeyToModifierGetter = <int, _ModifierGetter>{
@ -106,6 +117,7 @@ class KeyboardBinding {
}
}
KeyboardConverter get converter => _converter;
late final KeyboardConverter _converter;
final Map<String, DomEventListener> _listeners = <String, DomEventListener>{};
@ -559,4 +571,107 @@ class KeyboardConverter {
_dispatchKeyData = null;
}
}
// Synthesize modifier keys up or down events only when the known pressing states are different.
void synthesizeModifiersIfNeeded(
bool altPressed,
bool controlPressed,
bool metaPressed,
bool shiftPressed,
num eventTimestamp,
) {
_synthesizeModifierIfNeeded(
_kPhysicalAltLeft,
_kPhysicalAltRight,
_kLogicalAltLeft,
_kLogicalAltRight,
altPressed ? ui.KeyEventType.down : ui.KeyEventType.up,
eventTimestamp,
);
_synthesizeModifierIfNeeded(
_kPhysicalControlLeft,
_kPhysicalControlRight,
_kLogicalControlLeft,
_kLogicalControlRight,
controlPressed ? ui.KeyEventType.down : ui.KeyEventType.up,
eventTimestamp,
);
_synthesizeModifierIfNeeded(
_kPhysicalMetaLeft,
_kPhysicalMetaRight,
_kLogicalMetaLeft,
_kLogicalMetaRight,
metaPressed ? ui.KeyEventType.down : ui.KeyEventType.up,
eventTimestamp,
);
_synthesizeModifierIfNeeded(
_kPhysicalShiftLeft,
_kPhysicalShiftRight,
_kLogicalShiftLeft,
_kLogicalShiftRight,
shiftPressed ? ui.KeyEventType.down : ui.KeyEventType.up,
eventTimestamp,
);
}
void _synthesizeModifierIfNeeded(
int physicalLeft,
int physicalRight,
int logicalLeft,
int logicalRight,
ui.KeyEventType type,
num domTimestamp,
) {
final bool leftPressed = _pressingRecords.containsKey(physicalLeft);
final bool rightPressed = _pressingRecords.containsKey(physicalRight);
final bool alreadyPressed = leftPressed || rightPressed;
final bool synthesizeDown = type == ui.KeyEventType.down && !alreadyPressed;
final bool synthesizeUp = type == ui.KeyEventType.up && alreadyPressed;
// Synthesize a down event only for the left key if right and left are not pressed
if (synthesizeDown) {
_synthesizeKeyDownEvent(domTimestamp, physicalLeft, logicalLeft);
}
// Synthesize an up event for left key if pressed
if (synthesizeUp && leftPressed) {
_synthesizeKeyUpEvent(domTimestamp, physicalLeft, logicalLeft);
}
// Synthesize an up event for right key if pressed
if (synthesizeUp && rightPressed) {
_synthesizeKeyUpEvent(domTimestamp, physicalRight, logicalRight);
}
}
void _synthesizeKeyDownEvent(num domTimestamp, int physical, int logical) {
performDispatchKeyData(ui.KeyData(
timeStamp: _eventTimeStampToDuration(domTimestamp),
type: ui.KeyEventType.down,
physical: physical,
logical: logical,
character: null,
synthesized: true,
));
// Update pressing state
_pressingRecords[physical] = logical;
}
void _synthesizeKeyUpEvent(num domTimestamp, int physical, int logical) {
performDispatchKeyData(ui.KeyData(
timeStamp: _eventTimeStampToDuration(domTimestamp),
type: ui.KeyEventType.up,
physical: physical,
logical: logical,
character: null,
synthesized: true,
));
// Update pressing states
_pressingRecords.remove(physical);
}
@visibleForTesting
bool debugKeyIsPressed(int physical) {
return _pressingRecords.containsKey(physical);
}
}

View File

@ -5,6 +5,7 @@
import 'dart:math' as math;
import 'package:meta/meta.dart';
import 'package:ui/src/engine/keyboard_binding.dart';
import 'package:ui/ui.dart' as ui;
import '../engine.dart' show registerHotRestartListener;
@ -73,7 +74,7 @@ class SafariPointerEventWorkaround {
}
class PointerBinding {
PointerBinding(this.glassPaneElement)
PointerBinding(this.glassPaneElement, this._keyboardConverter)
: _pointerDataConverter = PointerDataConverter(),
_detector = const PointerSupportDetector() {
if (isIosSafari) {
@ -86,9 +87,9 @@ class PointerBinding {
static PointerBinding? get instance => _instance;
static PointerBinding? _instance;
static void initInstance(DomElement glassPaneElement) {
static void initInstance(DomElement glassPaneElement, KeyboardConverter keyboardConverter) {
if (_instance == null) {
_instance = PointerBinding(glassPaneElement);
_instance = PointerBinding(glassPaneElement, keyboardConverter);
assert(() {
registerHotRestartListener(_instance!.dispose);
return true;
@ -107,6 +108,7 @@ class PointerBinding {
PointerSupportDetector _detector;
final PointerDataConverter _pointerDataConverter;
KeyboardConverter _keyboardConverter;
late _BaseAdapter _adapter;
/// Should be used in tests to define custom detection of pointer support.
@ -137,15 +139,23 @@ class PointerBinding {
}
}
@visibleForTesting
void debugOverrideKeyboardConverter(KeyboardConverter keyboardConverter) {
_keyboardConverter = keyboardConverter;
_adapter.clearListeners();
_adapter = _createAdapter();
_pointerDataConverter.clearPointerState();
}
_BaseAdapter _createAdapter() {
if (_detector.hasPointerEvents) {
return _PointerAdapter(_onPointerData, glassPaneElement, _pointerDataConverter);
return _PointerAdapter(_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter);
}
if (_detector.hasTouchEvents) {
return _TouchAdapter(_onPointerData, glassPaneElement, _pointerDataConverter);
return _TouchAdapter(_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter);
}
if (_detector.hasMouseEvents) {
return _MouseAdapter(_onPointerData, glassPaneElement, _pointerDataConverter);
return _MouseAdapter(_onPointerData, glassPaneElement, _pointerDataConverter, _keyboardConverter);
}
throw UnsupportedError('This browser does not support pointer, touch, or mouse events.');
}
@ -239,7 +249,12 @@ class _Listener {
/// Common functionality that's shared among adapters.
abstract class _BaseAdapter {
_BaseAdapter(this._callback, this.glassPaneElement, this._pointerDataConverter) {
_BaseAdapter(
this._callback,
this.glassPaneElement,
this._pointerDataConverter,
this._keyboardConverter,
) {
setup();
}
@ -247,6 +262,7 @@ abstract class _BaseAdapter {
final DomElement glassPaneElement;
final _PointerDataCallback _callback;
final PointerDataConverter _pointerDataConverter;
final KeyboardConverter _keyboardConverter;
/// Each subclass is expected to override this method to attach its own event
/// listeners and convert events into pointer events.
@ -570,7 +586,8 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
_PointerAdapter(
super.callback,
super.glassPaneElement,
super.pointerDataConverter
super.pointerDataConverter,
super.keyboardConverter,
);
final Map<int, _ButtonSanitizer> _sanitizers = <int, _ButtonSanitizer>{};
@ -602,13 +619,27 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
String eventName,
_PointerEventListener handler, {
bool useCapture = true,
bool checkModifiers = true,
}) {
addEventListener(target, eventName, (DomEvent event) {
final DomPointerEvent pointerEvent = event as DomPointerEvent;
if (checkModifiers) {
_checkModifiersState(event);
}
handler(pointerEvent);
}, useCapture: useCapture);
}
void _checkModifiersState(DomPointerEvent event) {
_keyboardConverter.synthesizeModifiersIfNeeded(
event.getModifierState('Alt'),
event.getModifierState('Control'),
event.getModifierState('Meta'),
event.getModifierState('Shift'),
event.timeStamp!,
);
}
@override
void setup() {
_addPointerEventListener(glassPaneElement, 'pointerdown', (DomPointerEvent event) {
@ -654,7 +685,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
_convertEventsToPointerData(data: pointerData, event: event, details: details);
_callback(pointerData);
}
}, useCapture: false);
}, useCapture: false, checkModifiers: false);
_addPointerEventListener(domWindow, 'pointerup', (DomPointerEvent event) {
final int device = _getPointerId(event);
@ -680,7 +711,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
_convertEventsToPointerData(data: pointerData, event: event, details: details);
_callback(pointerData);
}
});
}, checkModifiers: false);
_addWheelEventListener((DomEvent event) {
_handleWheelEvent(event);
@ -767,7 +798,8 @@ class _TouchAdapter extends _BaseAdapter {
_TouchAdapter(
super.callback,
super.glassPaneElement,
super.pointerDataConverter
super.pointerDataConverter,
super.keyboardConverter,
);
final Set<int> _pressedTouches = <int>{};
@ -775,13 +807,26 @@ class _TouchAdapter extends _BaseAdapter {
void _pressTouch(int identifier) { _pressedTouches.add(identifier); }
void _unpressTouch(int identifier) { _pressedTouches.remove(identifier); }
void _addTouchEventListener(DomEventTarget target, String eventName, _TouchEventListener handler) {
void _addTouchEventListener(DomEventTarget target, String eventName, _TouchEventListener handler, {bool checkModifiers = true,}) {
addEventListener(target, eventName, (DomEvent event) {
final DomTouchEvent touchEvent = event as DomTouchEvent;
if (checkModifiers) {
_checkModifiersState(event);
}
handler(touchEvent);
});
}
void _checkModifiersState(DomTouchEvent event) {
_keyboardConverter.synthesizeModifiersIfNeeded(
event.altKey,
event.ctrlKey,
event.metaKey,
event.shiftKey,
event.timeStamp!,
);
}
@override
void setup() {
_addTouchEventListener(glassPaneElement, 'touchstart', (DomTouchEvent event) {
@ -910,7 +955,8 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
_MouseAdapter(
super.callback,
super.glassPaneElement,
super.pointerDataConverter
super.pointerDataConverter,
super.keyboardConverter,
);
final _ButtonSanitizer _sanitizer = _ButtonSanitizer();
@ -920,13 +966,27 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
String eventName,
_MouseEventListener handler, {
bool useCapture = true,
bool checkModifiers = true,
}) {
addEventListener(target, eventName, (DomEvent event) {
final DomMouseEvent mouseEvent = event as DomMouseEvent;
if (checkModifiers) {
_checkModifiersState(event);
}
handler(mouseEvent);
}, useCapture: useCapture);
}
void _checkModifiersState(DomMouseEvent event) {
_keyboardConverter.synthesizeModifiersIfNeeded(
event.getModifierState('Alt'),
event.getModifierState('Control'),
event.getModifierState('Meta'),
event.getModifierState('Shift'),
event.timeStamp!,
);
}
@override
void setup() {
_addMouseEventListener(glassPaneElement, 'mousedown', (DomMouseEvent event) {

View File

@ -9,6 +9,8 @@ import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import '../keyboard_converter_test.dart';
const int _kNoButtonChange = -1;
const PointerSupportDetector _defaultSupportDetector = PointerSupportDetector();
@ -46,6 +48,13 @@ void testMain() {
dpi = window.devicePixelRatio;
});
KeyboardConverter createKeyboardConverter(List<ui.KeyData> keyDataList) {
return KeyboardConverter((ui.KeyData key) {
keyDataList.add(key);
return true;
});
}
test('ios workaround', () {
debugEmulateIosSafari = true;
addTearDown(() {
@ -55,7 +64,9 @@ void testMain() {
final MockSafariPointerEventWorkaround mockSafariPointer =
MockSafariPointerEventWorkaround();
SafariPointerEventWorkaround.instance = mockSafariPointer;
final PointerBinding instance = PointerBinding(createDomHTMLDivElement());
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
final PointerBinding instance = PointerBinding(createDomHTMLDivElement(), keyboardConverter);
expect(mockSafariPointer.workAroundInvoked, isIosSafari);
instance.dispose();
}, skip: !isSafari);
@ -507,6 +518,248 @@ void testMain() {
},
);
_testEach<_BasicEventContext>(
<_BasicEventContext>[
_PointerEventContext(),
_MouseEventContext(),
_TouchEventContext(),
],
'synthesize modifier keys left down event if left or right are not pressed',
(_BasicEventContext context) {
PointerBinding.instance!.debugOverrideDetector(context);
// Should synthesize a modifier left key down event when DOM event indicates
// that the modifier key is pressed and known pressing state doesn't contain
// the modifier left key nor the modifier right key.
void shouldSynthesizeLeftDownIfNotPressed(String key) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final int logicalLeft = kWebLogicalLocationMap[key]![kLocationLeft]!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), false);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), false);
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 1);
expectKeyData(keyDataList.last,
type: ui.KeyEventType.down,
physical: physicalLeft,
logical: logicalLeft,
character: null,
synthesized: true,
);
}
context.altPressed = true;
shouldSynthesizeLeftDownIfNotPressed('Alt');
context.unpressAllModifiers();
context.ctrlPressed = true;
shouldSynthesizeLeftDownIfNotPressed('Control');
context.unpressAllModifiers();
context.metaPressed = true;
shouldSynthesizeLeftDownIfNotPressed('Meta');
context.unpressAllModifiers();
context.shiftPressed = true;
shouldSynthesizeLeftDownIfNotPressed('Shift');
context.unpressAllModifiers();
},
);
_testEach<_BasicEventContext>(
<_BasicEventContext>[
_PointerEventContext(),
_MouseEventContext(),
_TouchEventContext(),
],
'should not synthesize modifier keys down event if left or right are pressed',
(_BasicEventContext context) {
PointerBinding.instance!.debugOverrideDetector(context);
// Should not synthesize a modifier down event when DOM event indicates
// that the modifier key is pressed and known pressing state contains
// the modifier left key.
void shouldNotSynthesizeDownIfLeftPressed(String key, int modifiers) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
keyboardConverter.handleEvent(keyDownEvent('${key}Left', key, modifiers, kLocationLeft));
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), true);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), false);
keyDataList.clear(); // Remove key data generated by handleEvent
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 0);
}
// Should not synthesize a modifier down event when DOM event indicates
// that the modifier key is pressed and known pressing state contains
// the modifier right key.
void shouldNotSynthesizeDownIfRightPressed(String key, int modifiers) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
keyboardConverter.handleEvent(keyDownEvent('${key}Right', key, modifiers, kLocationRight));
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), false);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), true);
keyDataList.clear(); // Remove key data generated by handleEvent
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 0);
}
context.altPressed = true;
shouldNotSynthesizeDownIfLeftPressed('Alt', kAlt);
shouldNotSynthesizeDownIfRightPressed('Alt', kAlt);
context.unpressAllModifiers();
context.ctrlPressed = true;
shouldNotSynthesizeDownIfLeftPressed('Control', kCtrl);
shouldNotSynthesizeDownIfRightPressed('Control', kCtrl);
context.unpressAllModifiers();
context.metaPressed = true;
shouldNotSynthesizeDownIfLeftPressed('Meta', kMeta);
shouldNotSynthesizeDownIfRightPressed('Meta', kMeta);
context.unpressAllModifiers();
context.shiftPressed = true;
shouldNotSynthesizeDownIfLeftPressed('Shift', kShift);
shouldNotSynthesizeDownIfRightPressed('Shift', kShift);
context.unpressAllModifiers();
},
);
_testEach<_BasicEventContext>(
<_BasicEventContext>[
_PointerEventContext(),
_MouseEventContext(),
_TouchEventContext(),
],
'synthesize modifier keys up event if left or right are pressed',
(_BasicEventContext context) {
PointerBinding.instance!.debugOverrideDetector(context);
// Should synthesize a modifier left key up event when DOM event indicates
// that the modifier key is not pressed and known pressing state contains
// the modifier left key.
void shouldSynthesizeLeftUpIfLeftPressed(String key, int modifiers) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final int logicalLeft = kWebLogicalLocationMap[key]![kLocationLeft]!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
keyboardConverter.handleEvent(keyDownEvent('${key}Left', key, modifiers, kLocationLeft));
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), true);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), false);
keyDataList.clear(); // Remove key data generated by handleEvent
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 1);
expectKeyData(keyDataList.last,
type: ui.KeyEventType.up,
physical: physicalLeft,
logical: logicalLeft,
character: null,
synthesized: true,
);
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), false);
}
// Should synthesize a modifier right key up event when DOM event indicates
// that the modifier key is not pressed and known pressing state contains
// the modifier right key.
void shouldSynthesizeRightUpIfRightPressed(String key, int modifiers) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final int logicalRight = kWebLogicalLocationMap[key]![kLocationRight]!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
keyboardConverter.handleEvent(keyDownEvent('${key}Right', key, modifiers, kLocationRight));
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), false);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), true);
keyDataList.clear(); // Remove key data generated by handleEvent
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 1);
expectKeyData(keyDataList.last,
type: ui.KeyEventType.up,
physical: physicalRight,
logical: logicalRight,
character: null,
synthesized: true,
);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), false);
}
context.altPressed = false;
shouldSynthesizeLeftUpIfLeftPressed('Alt', kAlt);
shouldSynthesizeRightUpIfRightPressed('Alt', kAlt);
context.ctrlPressed = false;
shouldSynthesizeLeftUpIfLeftPressed('Control', kCtrl);
shouldSynthesizeRightUpIfRightPressed('Control', kCtrl);
context.metaPressed = false;
shouldSynthesizeLeftUpIfLeftPressed('Meta', kMeta);
shouldSynthesizeRightUpIfRightPressed('Meta', kMeta);
context.shiftPressed = false;
shouldSynthesizeLeftUpIfLeftPressed('Shift', kShift);
shouldSynthesizeRightUpIfRightPressed('Shift', kShift);
},
);
_testEach<_BasicEventContext>(
<_BasicEventContext>[
_PointerEventContext(),
_MouseEventContext(),
_TouchEventContext(),
],
'should not synthesize modifier keys up event if left or right are not pressed',
(_BasicEventContext context) {
PointerBinding.instance!.debugOverrideDetector(context);
// Should not synthesize a modifier up event when DOM event indicates
// that the modifier key is not pressed and known pressing state does
// not contain the modifier left key nor the modifier right key.
void shouldNotSynthesizeUpIfNotPressed(String key) {
final int physicalLeft = kWebToPhysicalKey['${key}Left']!;
final int physicalRight = kWebToPhysicalKey['${key}Right']!;
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter keyboardConverter = createKeyboardConverter(keyDataList);
PointerBinding.instance!.debugOverrideKeyboardConverter(keyboardConverter);
expect(keyboardConverter.debugKeyIsPressed(physicalLeft), false);
expect(keyboardConverter.debugKeyIsPressed(physicalRight), false);
keyDataList.clear(); // Remove key data generated by handleEvent
glassPane.dispatchEvent(context.primaryDown());
expect(keyDataList.length, 0);
}
context.altPressed = false;
shouldNotSynthesizeUpIfNotPressed('Alt');
context.ctrlPressed = false;
shouldNotSynthesizeUpIfNotPressed('Control');
context.metaPressed = false;
shouldNotSynthesizeUpIfNotPressed('Meta');
context.shiftPressed = false;
shouldNotSynthesizeUpIfNotPressed('Shift');
},
);
_testEach<_ButtonedEventMixin>(
<_ButtonedEventMixin>[
if (!isIosSafari) _PointerEventContext(),
@ -2466,7 +2719,7 @@ abstract class _BasicEventContext implements PointerSupportDetector {
bool altPressed = false;
bool ctrlPressed = false;
bool metaPressed = false;
bool shitPressed = false;
bool shiftPressed = false;
// Generate an event that is:
//
@ -2490,14 +2743,14 @@ abstract class _BasicEventContext implements PointerSupportDetector {
altPressed = true;
ctrlPressed = true;
metaPressed = true;
shitPressed = true;
shiftPressed = true;
}
void unpressAllModifiers() {
altPressed = false;
ctrlPressed = false;
metaPressed = false;
shitPressed = false;
shiftPressed = false;
}
}
@ -2687,7 +2940,7 @@ class _TouchEventContext extends _BasicEventContext
'altKey': altPressed,
'ctrlKey': ctrlPressed,
'metaKey': metaPressed,
'shiftKey': shitPressed,
'shiftKey': shiftPressed,
},
);
}
@ -2826,7 +3079,7 @@ class _MouseEventContext extends _BasicEventContext
'altKey': altPressed,
'ctrlKey': ctrlPressed,
'metaKey': metaPressed,
'shiftKey': shitPressed,
'shiftKey': shiftPressed,
}
];
return js_util.callConstructor<DomMouseEvent>(
@ -2908,7 +3161,7 @@ class _PointerEventContext extends _BasicEventContext
'altKey': altPressed,
'ctrlKey': ctrlPressed,
'metaKey': metaPressed,
'shiftKey': shitPressed,
'shiftKey': shiftPressed,
});
}