mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fixing synthesizing keys for multiple keys pressed down on flutter web (flutter/engine#19632)
This commit is contained in:
parent
f6a0c426f9
commit
2faca2ac4e
@ -91,8 +91,7 @@ class Keyboard {
|
||||
|
||||
final String timerKey = keyboardEvent.code!;
|
||||
|
||||
// Don't synthesize a keyup event for modifier keys because the browser always
|
||||
// sends a keyup event for those.
|
||||
// Don't handle synthesizing a keyup event for modifier keys
|
||||
if (!_isModifierKey(event)) {
|
||||
// When the user enters a browser/system shortcut (e.g. `cmd+alt+i`) the
|
||||
// browser doesn't send a keyup for it. This puts the framework in a
|
||||
@ -103,7 +102,10 @@ class Keyboard {
|
||||
// event within a specific duration ([_keydownCancelDuration]) we assume
|
||||
// the user has released the key and we synthesize a keyup event.
|
||||
_keydownTimers[timerKey]?.cancel();
|
||||
if (event.type == 'keydown') {
|
||||
|
||||
// Only keys affected by modifiers, require synthesizing
|
||||
// because the browser always sends a keyup event otherwise
|
||||
if (event.type == 'keydown' && _isAffectedByModifiers(event)) {
|
||||
_keydownTimers[timerKey] = Timer(_keydownCancelDuration, () {
|
||||
_keydownTimers.remove(timerKey);
|
||||
_synthesizeKeyup(event);
|
||||
@ -185,4 +187,11 @@ bool _isModifierKey(html.KeyboardEvent event) {
|
||||
return key == 'Meta' || key == 'Shift' || key == 'Alt' || key == 'Control';
|
||||
}
|
||||
|
||||
/// Returns true if the [event] is been affects by any of the modifiers key
|
||||
///
|
||||
/// This is a strong indication that this key is been used for a shortcut
|
||||
bool _isAffectedByModifiers(html.KeyboardEvent event) {
|
||||
return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;
|
||||
}
|
||||
|
||||
void _noopCallback(ByteData? data) {}
|
||||
|
||||
@ -473,18 +473,37 @@ void testMain() {
|
||||
}
|
||||
messages.clear();
|
||||
|
||||
// When repeat events stop for a long-enough period of time, a keyup
|
||||
// should be synthesized.
|
||||
Keyboard.instance.dispose();
|
||||
},
|
||||
);
|
||||
|
||||
testFakeAsync(
|
||||
'do not synthesize keyup when keys are not affected by meta modifiers',
|
||||
(FakeAsync async) {
|
||||
Keyboard.initialize();
|
||||
|
||||
List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
|
||||
ui.window.onPlatformMessage = (String channel, ByteData data,
|
||||
ui.PlatformMessageResponseCallback callback) {
|
||||
messages.add(const JSONMessageCodec().decodeMessage(data));
|
||||
};
|
||||
|
||||
dispatchKeyboardEvent(
|
||||
'keydown',
|
||||
key: 'i',
|
||||
code: 'KeyI',
|
||||
);
|
||||
dispatchKeyboardEvent(
|
||||
'keydown',
|
||||
key: 'o',
|
||||
code: 'KeyO',
|
||||
);
|
||||
messages.clear();
|
||||
|
||||
// Wait for a long-enough period of time and no events
|
||||
// should be synthesized
|
||||
async.elapse(Duration(seconds: 3));
|
||||
expect(messages, <Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
'type': 'keyup',
|
||||
'keymap': 'web',
|
||||
'key': 'i',
|
||||
'code': 'KeyI',
|
||||
'metaState': 0x0,
|
||||
}
|
||||
]);
|
||||
expect(messages, hasLength(0));
|
||||
|
||||
Keyboard.instance.dispose();
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user