From 5628ebf662c57e61ef7076af3f2b42e667dadd70 Mon Sep 17 00:00:00 2001 From: Bruno Leroux Date: Mon, 7 Nov 2022 21:41:09 +0100 Subject: [PATCH] [RawKeyboard] Allow inconsistent modifiers for Web (#114499) Co-authored-by: Bruno Leroux --- dev/tools/gen_keycodes/data/keyboard_key.tmpl | 2 +- .../data/web_logical_location_mapping.json | 1 + .../lib/src/services/keyboard_maps.g.dart | 1 + .../lib/src/services/raw_keyboard.dart | 6 ++ .../test/services/raw_keyboard_test.dart | 58 +++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/dev/tools/gen_keycodes/data/keyboard_key.tmpl b/dev/tools/gen_keycodes/data/keyboard_key.tmpl index ce8f758e07b2..36390efd6ab1 100644 --- a/dev/tools/gen_keycodes/data/keyboard_key.tmpl +++ b/dev/tools/gen_keycodes/data/keyboard_key.tmpl @@ -209,7 +209,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// Auto-generated IDs should be a rare occurrence: Flutter supports most keys. /// /// Keys that generate Unicode characters (even if unknown to Flutter) will - /// not return true for `isAutogenerated`, since they will be assigned a + /// not return true for [isAutogenerated], since they will be assigned a /// Unicode-based code that will remain stable. /// /// If Flutter adds support for a previously unsupported key code, the ID it diff --git a/dev/tools/gen_keycodes/data/web_logical_location_mapping.json b/dev/tools/gen_keycodes/data/web_logical_location_mapping.json index dd06fd117987..cdc4e3bf5289 100644 --- a/dev/tools/gen_keycodes/data/web_logical_location_mapping.json +++ b/dev/tools/gen_keycodes/data/web_logical_location_mapping.json @@ -29,5 +29,6 @@ "Shift": ["ShiftLeft", "ShiftLeft", "ShiftRight", null], "Control": ["ControlLeft", "ControlLeft", "ControlRight", null], "Alt": ["AltLeft", "AltLeft", "AltRight", null], + "AltGraph": ["AltGraph", null, "AltGraph", null], "Meta": ["MetaLeft", "MetaLeft", "MetaRight", null] } diff --git a/packages/flutter/lib/src/services/keyboard_maps.g.dart b/packages/flutter/lib/src/services/keyboard_maps.g.dart index 079230c4313d..b94e1c82e532 100644 --- a/packages/flutter/lib/src/services/keyboard_maps.g.dart +++ b/packages/flutter/lib/src/services/keyboard_maps.g.dart @@ -2755,6 +2755,7 @@ const Map> kWebLocationMap = [LogicalKeyboardKey.digit8, null, null, LogicalKeyboardKey.numpad8], '9': [LogicalKeyboardKey.digit9, null, null, LogicalKeyboardKey.numpad9], 'Alt': [LogicalKeyboardKey.altLeft, LogicalKeyboardKey.altLeft, LogicalKeyboardKey.altRight, null], + 'AltGraph': [LogicalKeyboardKey.altGraph, null, LogicalKeyboardKey.altGraph, null], 'ArrowDown': [LogicalKeyboardKey.arrowDown, null, null, LogicalKeyboardKey.numpad2], 'ArrowLeft': [LogicalKeyboardKey.arrowLeft, null, null, LogicalKeyboardKey.numpad4], 'ArrowRight': [LogicalKeyboardKey.arrowRight, null, null, LogicalKeyboardKey.numpad6], diff --git a/packages/flutter/lib/src/services/raw_keyboard.dart b/packages/flutter/lib/src/services/raw_keyboard.dart index 0874f1d5eecf..4f5a0a4d6466 100644 --- a/packages/flutter/lib/src/services/raw_keyboard.dart +++ b/packages/flutter/lib/src/services/raw_keyboard.dart @@ -848,6 +848,12 @@ class RawKeyboard { _keysPressed[event.physicalKey] = logicalKey; } } + // On Web, PhysicalKeyboardKey.altRight can be map to LogicalKeyboardKey.altGraph or + // LogicalKeyboardKey.altRight: + // https://github.com/flutter/flutter/issues/113836 + if (event.data is RawKeyEventDataWeb && event.physicalKey == PhysicalKeyboardKey.altRight) { + _keysPressed[event.physicalKey] = event.logicalKey; + } } } diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 5dcb78341cbc..d73dbb163dff 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -842,6 +842,64 @@ void main() { expect(RawKeyboard.instance.keysPressed, contains(LogicalKeyboardKey.capsLock)); }, skip: isBrowser); // [intended] This is an Android-specific group. + testWidgets('Allows inconsistent modifier for Web - Alt graph', (WidgetTester _) async { + // Regression test for https://github.com/flutter/flutter/issues/113836 + final List events = []; + RawKeyboard.instance.addListener(events.add); + addTearDown(() { + RawKeyboard.instance.removeListener(events.add); + }); + await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + SystemChannels.keyEvent.name, + SystemChannels.keyEvent.codec.encodeMessage(const { + 'type': 'keydown', + 'keymap': 'web', + 'code': 'AltRight', + 'key': 'AltGraph', + 'location': 2, + 'metaState': 0, + 'keyCode': 225, + }), + (ByteData? data) { }, + ); + + expect(events, hasLength(1)); + final RawKeyEvent altRightKey = events[0]; + final RawKeyEventDataWeb data = altRightKey.data as RawKeyEventDataWeb; + expect(data.physicalKey, equals(PhysicalKeyboardKey.altRight)); + expect(data.logicalKey, equals(LogicalKeyboardKey.altGraph)); + expect(RawKeyboard.instance.keysPressed, contains(LogicalKeyboardKey.altGraph)); + }, skip: !isBrowser); // [intended] This is a Browser-specific test. + + testWidgets('Allows inconsistent modifier for Web - Alt right', (WidgetTester _) async { + // Regression test for https://github.com/flutter/flutter/issues/113836 + final List events = []; + RawKeyboard.instance.addListener(events.add); + addTearDown(() { + RawKeyboard.instance.removeListener(events.add); + }); + await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + SystemChannels.keyEvent.name, + SystemChannels.keyEvent.codec.encodeMessage(const { + 'type': 'keydown', + 'keymap': 'web', + 'code': 'AltRight', + 'key': 'Alt', + 'location': 2, + 'metaState': 0, + 'keyCode': 225, + }), + (ByteData? data) { }, + ); + + expect(events, hasLength(1)); + final RawKeyEvent altRightKey = events[0]; + final RawKeyEventDataWeb data = altRightKey.data as RawKeyEventDataWeb; + expect(data.physicalKey, equals(PhysicalKeyboardKey.altRight)); + expect(data.logicalKey, equals(LogicalKeyboardKey.altRight)); + expect(RawKeyboard.instance.keysPressed, contains(LogicalKeyboardKey.altRight)); + }, skip: !isBrowser); // [intended] This is a Browser-specific test. + testWidgets('Dispatch events to all handlers', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); final List logs = [];