diff --git a/dev/manual_tests/lib/raw_keyboard.dart b/dev/manual_tests/lib/raw_keyboard.dart index 72948323c4..8507bf2394 100644 --- a/dev/manual_tests/lib/raw_keyboard.dart +++ b/dev/manual_tests/lib/raw_keyboard.dart @@ -36,10 +36,11 @@ class _HardwareKeyDemoState extends State { super.dispose(); } - void _handleKeyEvent(RawKeyEvent event) { + bool _handleKeyEvent(FocusNode node, RawKeyEvent event) { setState(() { _event = event; }); + return false; } String _asHex(int value) => value != null ? '0x${value.toRadixString(16)}' : 'null'; @@ -53,9 +54,10 @@ class _HardwareKeyDemoState extends State { @override Widget build(BuildContext context) { final TextTheme textTheme = Theme.of(context).textTheme; - return RawKeyboardListener( + return Focus( focusNode: _focusNode, onKey: _handleKeyEvent, + autofocus: true, child: AnimatedBuilder( animation: _focusNode, builder: (BuildContext context, Widget child) { @@ -87,6 +89,9 @@ class _HardwareKeyDemoState extends State { dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})')); dataText.add(Text('scanCode: ${data.scanCode} (${_asHex(data.scanCode)})')); dataText.add(Text('metaState: ${data.metaState} (${_asHex(data.metaState)})')); + dataText.add(Text('source: ${data.eventSource} (${_asHex(data.eventSource)})')); + dataText.add(Text('vendorId: ${data.vendorId} (${_asHex(data.vendorId)})')); + dataText.add(Text('productId: ${data.productId} (${_asHex(data.productId)})')); dataText.add(Text('flags: ${data.flags} (${_asHex(data.flags)})')); } else if (data is RawKeyEventDataFuchsia) { dataText.add(Text('codePoint: ${data.codePoint} (${_asHex(data.codePoint)})')); @@ -118,7 +123,7 @@ class _HardwareKeyDemoState extends State { } } return DefaultTextStyle( - style: textTheme.headline, + style: textTheme.subhead, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: dataText, diff --git a/dev/tools/gen_keycodes/bin/gen_keycodes.dart b/dev/tools/gen_keycodes/bin/gen_keycodes.dart index dd1d6c304a..4e04faa76d 100644 --- a/dev/tools/gen_keycodes/bin/gen_keycodes.dart +++ b/dev/tools/gen_keycodes/bin/gen_keycodes.dart @@ -52,6 +52,12 @@ Future main(List rawArguments) async { 'read. If --chromium-hid-codes is not specified, the input will be read ' 'from the correct file in the Chromium repository.', ); + argParser.addOption( + 'supplemental-hid-codes', + defaultsTo: path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'supplemental_hid_codes.inc'), + help: "The path to where the supplemental HID codes that don't appear in the " + 'Chromium map should be read.', + ); argParser.addOption( 'android-keycodes', defaultsTo: null, @@ -140,6 +146,9 @@ Future main(List rawArguments) async { hidCodes = File(parsedArguments['chromium-hid-codes']).readAsStringSync(); } + final String supplementalHidCodes = File(parsedArguments['supplemental-hid-codes']).readAsStringSync(); + hidCodes = '$hidCodes\n$supplementalHidCodes'; + String androidKeyCodes; if (parsedArguments['android-keycodes'] == null) { androidKeyCodes = await getAndroidKeyCodes(); diff --git a/dev/tools/gen_keycodes/data/key_data.json b/dev/tools/gen_keycodes/data/key_data.json index 8ea2f21823..7aee204085 100644 --- a/dev/tools/gen_keycodes/data/key_data.json +++ b/dev/tools/gen_keycodes/data/key_data.json @@ -3794,13 +3794,17 @@ "select": { "names": { "domkey": "Select", - "android": null, + "android": [ + "DPAD_CENTER" + ], "english": "Select", "chromium": "select", "glfw": null }, "scanCodes": { - "android": null, + "android": [ + 353 + ], "usb": 458871, "linux": 132, "xkb": 140, @@ -3808,7 +3812,9 @@ "macos": null }, "keyCodes": { - "android": null, + "android": [ + 23 + ], "glfw": null } }, @@ -6355,5 +6361,858 @@ "android": null, "glfw": null } + }, + "gameButton1": { + "names": { + "domkey": "GameButton1", + "android": [ + "BUTTON_1" + ], + "english": "Game Button 1", + "chromium": "button1", + "glfw": null + }, + "scanCodes": { + "android": [ + 256, + 288 + ], + "usb": 341761, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 188 + ], + "glfw": null + } + }, + "gameButton2": { + "names": { + "domkey": "GameButton2", + "android": [ + "BUTTON_2" + ], + "english": "Game Button 2", + "chromium": "button2", + "glfw": null + }, + "scanCodes": { + "android": [ + 257, + 289 + ], + "usb": 341762, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 189 + ], + "glfw": null + } + }, + "gameButton3": { + "names": { + "domkey": "GameButton3", + "android": [ + "BUTTON_3" + ], + "english": "Game Button 3", + "chromium": "button3", + "glfw": null + }, + "scanCodes": { + "android": [ + 258, + 290 + ], + "usb": 341763, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 190 + ], + "glfw": null + } + }, + "gameButton4": { + "names": { + "domkey": "GameButton4", + "android": [ + "BUTTON_4" + ], + "english": "Game Button 4", + "chromium": "button4", + "glfw": null + }, + "scanCodes": { + "android": [ + 259, + 291 + ], + "usb": 341764, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 191 + ], + "glfw": null + } + }, + "gameButton5": { + "names": { + "domkey": "GameButton5", + "android": [ + "BUTTON_5" + ], + "english": "Game Button 5", + "chromium": "button5", + "glfw": null + }, + "scanCodes": { + "android": [ + 260, + 292 + ], + "usb": 341765, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 192 + ], + "glfw": null + } + }, + "gameButton6": { + "names": { + "domkey": "GameButton6", + "android": [ + "BUTTON_6" + ], + "english": "Game Button 6", + "chromium": "button6", + "glfw": null + }, + "scanCodes": { + "android": [ + 261, + 293 + ], + "usb": 341766, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 193 + ], + "glfw": null + } + }, + "gameButton7": { + "names": { + "domkey": "GameButton7", + "android": [ + "BUTTON_7" + ], + "english": "Game Button 7", + "chromium": "button7", + "glfw": null + }, + "scanCodes": { + "android": [ + 262, + 294 + ], + "usb": 341767, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 194 + ], + "glfw": null + } + }, + "gameButton8": { + "names": { + "domkey": "GameButton8", + "android": [ + "BUTTON_8" + ], + "english": "Game Button 8", + "chromium": "button8", + "glfw": null + }, + "scanCodes": { + "android": [ + 263, + 295 + ], + "usb": 341768, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 195 + ], + "glfw": null + } + }, + "gameButton9": { + "names": { + "domkey": "GameButton9", + "android": [ + "BUTTON_9" + ], + "english": "Game Button 9", + "chromium": "button9", + "glfw": null + }, + "scanCodes": { + "android": [ + 264, + 296 + ], + "usb": 341769, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 196 + ], + "glfw": null + } + }, + "gameButton10": { + "names": { + "domkey": "GameButton10", + "android": [ + "BUTTON_10" + ], + "english": "Game Button 10", + "chromium": "button10", + "glfw": null + }, + "scanCodes": { + "android": [ + 265, + 297 + ], + "usb": 341770, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 197 + ], + "glfw": null + } + }, + "gameButton11": { + "names": { + "domkey": "GameButton11", + "android": [ + "BUTTON_11" + ], + "english": "Game Button 11", + "chromium": "button11", + "glfw": null + }, + "scanCodes": { + "android": [ + 266, + 298 + ], + "usb": 341771, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 198 + ], + "glfw": null + } + }, + "gameButton12": { + "names": { + "domkey": "GameButton12", + "android": [ + "BUTTON_12" + ], + "english": "Game Button 12", + "chromium": "button12", + "glfw": null + }, + "scanCodes": { + "android": [ + 267, + 299 + ], + "usb": 341772, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 199 + ], + "glfw": null + } + }, + "gameButton13": { + "names": { + "domkey": "GameButton13", + "android": [ + "BUTTON_13" + ], + "english": "Game Button 13", + "chromium": "button13", + "glfw": null + }, + "scanCodes": { + "android": [ + 268, + 300 + ], + "usb": 341773, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 200 + ], + "glfw": null + } + }, + "gameButton14": { + "names": { + "domkey": "GameButton14", + "android": [ + "BUTTON_14" + ], + "english": "Game Button 14", + "chromium": "button14", + "glfw": null + }, + "scanCodes": { + "android": [ + 269, + 301 + ], + "usb": 341774, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 201 + ], + "glfw": null + } + }, + "gameButton15": { + "names": { + "domkey": "GameButton15", + "android": [ + "BUTTON_15" + ], + "english": "Game Button 15", + "chromium": "button15", + "glfw": null + }, + "scanCodes": { + "android": [ + 270, + 302 + ], + "usb": 341775, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 202 + ], + "glfw": null + } + }, + "gameButton16": { + "names": { + "domkey": "GameButton16", + "android": [ + "BUTTON_16" + ], + "english": "Game Button 16", + "chromium": "button16", + "glfw": null + }, + "scanCodes": { + "android": [ + 271, + 303 + ], + "usb": 341776, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 203 + ], + "glfw": null + } + }, + "gameButtonA": { + "names": { + "domkey": "GameButtonA", + "android": [ + "BUTTON_A" + ], + "english": "Game Button A", + "chromium": "buttonA", + "glfw": null + }, + "scanCodes": { + "android": [ + 304 + ], + "usb": 341777, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 96 + ], + "glfw": null + } + }, + "gameButtonB": { + "names": { + "domkey": "GameButtonB", + "android": [ + "BUTTON_B" + ], + "english": "Game Button B", + "chromium": "buttonB", + "glfw": null + }, + "scanCodes": { + "android": [ + 305 + ], + "usb": 341778, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 97 + ], + "glfw": null + } + }, + "gameButtonC": { + "names": { + "domkey": "GameButtonC", + "android": [ + "BUTTON_C" + ], + "english": "Game Button C", + "chromium": "buttonC", + "glfw": null + }, + "scanCodes": { + "android": [ + 306 + ], + "usb": 341779, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 98 + ], + "glfw": null + } + }, + "gameButtonLeft1": { + "names": { + "domkey": "GameButtonLeft1", + "android": [ + "BUTTON_L1" + ], + "english": "Game Button Left 1", + "chromium": "buttonL1", + "glfw": null + }, + "scanCodes": { + "android": [ + 310 + ], + "usb": 341780, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 102 + ], + "glfw": null + } + }, + "gameButtonLeft2": { + "names": { + "domkey": "GameButtonLeft2", + "android": [ + "BUTTON_L2" + ], + "english": "Game Button Left 2", + "chromium": "buttonL2", + "glfw": null + }, + "scanCodes": { + "android": [ + 312 + ], + "usb": 341781, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 104 + ], + "glfw": null + } + }, + "gameButtonMode": { + "names": { + "domkey": "GameButtonMode", + "android": [ + "BUTTON_MODE" + ], + "english": "Game Button Mode", + "chromium": "buttonMode", + "glfw": null + }, + "scanCodes": { + "android": [ + 316 + ], + "usb": 341782, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 110 + ], + "glfw": null + } + }, + "gameButtonRight1": { + "names": { + "domkey": "GameButtonRight1", + "android": [ + "BUTTON_R1" + ], + "english": "Game Button Right 1", + "chromium": "buttonR1", + "glfw": null + }, + "scanCodes": { + "android": [ + 311 + ], + "usb": 341783, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 103 + ], + "glfw": null + } + }, + "gameButtonRight2": { + "names": { + "domkey": "GameButtonRight2", + "android": [ + "BUTTON_R2" + ], + "english": "Game Button Right 2", + "chromium": "buttonR2", + "glfw": null + }, + "scanCodes": { + "android": [ + 313 + ], + "usb": 341784, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 105 + ], + "glfw": null + } + }, + "gameButtonSelect": { + "names": { + "domkey": "GameButtonSelect", + "android": [ + "BUTTON_SELECT" + ], + "english": "Game Button Select", + "chromium": "buttonSelect", + "glfw": null + }, + "scanCodes": { + "android": [ + 314 + ], + "usb": 341785, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 109 + ], + "glfw": null + } + }, + "gameButtonStart": { + "names": { + "domkey": "GameButtonStart", + "android": [ + "BUTTON_START" + ], + "english": "Game Button Start", + "chromium": "buttonStart", + "glfw": null + }, + "scanCodes": { + "android": [ + 315 + ], + "usb": 341786, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 108 + ], + "glfw": null + } + }, + "gameButtonThumbLeft": { + "names": { + "domkey": "GameButtonThumbLeft", + "android": [ + "BUTTON_THUMBL" + ], + "english": "Game Button Thumb Left", + "chromium": "buttonThumbl", + "glfw": null + }, + "scanCodes": { + "android": [ + 317 + ], + "usb": 341787, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 106 + ], + "glfw": null + } + }, + "gameButtonThumbRight": { + "names": { + "domkey": "GameButtonThumbRight", + "android": [ + "BUTTON_THUMBR" + ], + "english": "Game Button Thumb Right", + "chromium": "buttonThumbr", + "glfw": null + }, + "scanCodes": { + "android": [ + 318 + ], + "usb": 341788, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 107 + ], + "glfw": null + } + }, + "gameButtonX": { + "names": { + "domkey": "GameButtonX", + "android": [ + "BUTTON_X" + ], + "english": "Game Button X", + "chromium": "buttonX", + "glfw": null + }, + "scanCodes": { + "android": [ + 307 + ], + "usb": 341789, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 99 + ], + "glfw": null + } + }, + "gameButtonY": { + "names": { + "domkey": "GameButtonY", + "android": [ + "BUTTON_Y" + ], + "english": "Game Button Y", + "chromium": "buttonY", + "glfw": null + }, + "scanCodes": { + "android": [ + 308 + ], + "usb": 341790, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 100 + ], + "glfw": null + } + }, + "gameButtonZ": { + "names": { + "domkey": "GameButtonZ", + "android": [ + "BUTTON_Z" + ], + "english": "Game Button Z", + "chromium": "buttonZ", + "glfw": null + }, + "scanCodes": { + "android": [ + 309 + ], + "usb": 341791, + "linux": null, + "xkb": null, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": [ + 101 + ], + "glfw": null + } } } \ No newline at end of file diff --git a/dev/tools/gen_keycodes/data/key_name_to_android_name.json b/dev/tools/gen_keycodes/data/key_name_to_android_name.json index f51ec02005..856a4f9f64 100644 --- a/dev/tools/gen_keycodes/data/key_name_to_android_name.json +++ b/dev/tools/gen_keycodes/data/key_name_to_android_name.json @@ -90,6 +90,37 @@ "f24": ["F24"], "find": ["FIND"], "fn": ["FUNCTION"], + "gameButton1": ["BUTTON_1"], + "gameButton2": ["BUTTON_2"], + "gameButton3": ["BUTTON_3"], + "gameButton4": ["BUTTON_4"], + "gameButton5": ["BUTTON_5"], + "gameButton6": ["BUTTON_6"], + "gameButton7": ["BUTTON_7"], + "gameButton8": ["BUTTON_8"], + "gameButton9": ["BUTTON_9"], + "gameButton10": ["BUTTON_10"], + "gameButton11": ["BUTTON_11"], + "gameButton12": ["BUTTON_12"], + "gameButton13": ["BUTTON_13"], + "gameButton14": ["BUTTON_14"], + "gameButton15": ["BUTTON_15"], + "gameButton16": ["BUTTON_16"], + "gameButtonA": ["BUTTON_A"], + "gameButtonB": ["BUTTON_B"], + "gameButtonC": ["BUTTON_C"], + "gameButtonLeft1": ["BUTTON_L1"], + "gameButtonLeft2": ["BUTTON_L2"], + "gameButtonMode": ["BUTTON_MODE"], + "gameButtonRight1": ["BUTTON_R1"], + "gameButtonRight2": ["BUTTON_R2"], + "gameButtonSelect": ["BUTTON_SELECT"], + "gameButtonStart": ["BUTTON_START"], + "gameButtonThumbLeft": ["BUTTON_THUMBL"], + "gameButtonThumbRight": ["BUTTON_THUMBR"], + "gameButtonX": ["BUTTON_X"], + "gameButtonY": ["BUTTON_Y"], + "gameButtonZ": ["BUTTON_Z"], "goBack": ["BACK"], "goHome": ["HOME"], "groupNext": ["LANGUAGE_SWITCH"], @@ -200,6 +231,7 @@ "quote": ["APOSTROPHE"], "redo": ["REDO"], "scrollLock": ["SCROLL_LOCK"], + "select": ["DPAD_CENTER"], "semicolon": ["SEMICOLON"], "settings": ["SETTINGS"], "shiftLeft": ["SHIFT_LEFT"], diff --git a/dev/tools/gen_keycodes/data/supplemental_hid_codes.inc b/dev/tools/gen_keycodes/data/supplemental_hid_codes.inc new file mode 100644 index 0000000000..da271bc806 --- /dev/null +++ b/dev/tools/gen_keycodes/data/supplemental_hid_codes.inc @@ -0,0 +1,45 @@ + // These are supplemental key codes to be added to those that Chromium + // defines. Since the web doesn't have game controller buttons defined in the + // same way, these map USB HID codes for game controller buttons to + // Android/Linux button names. + // + // The HID codes here are not real USB HID codes, because the USB HID standard + // doesn't define game controller buttons in this way. It defines only two + // button "collections" (fire/jump and trigger), with the button number for + // each collection sent as extra data. Since we're just using USB HID as a + // convenient namespace, and not using these HID codes for interfacing with a + // USB protocol, we can define new ones to enumerate the buttons. These don't + // collide with any currently defined HID codes. + // + // USB HID evdev XKB Win Mac DOMKey Code + USB_KEYMAP(0x05ff01, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton1", BUTTON_1), + USB_KEYMAP(0x05ff02, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton2", BUTTON_2), + USB_KEYMAP(0x05ff03, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton3", BUTTON_3), + USB_KEYMAP(0x05ff04, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton4", BUTTON_4), + USB_KEYMAP(0x05ff05, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton5", BUTTON_5), + USB_KEYMAP(0x05ff06, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton6", BUTTON_6), + USB_KEYMAP(0x05ff07, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton7", BUTTON_7), + USB_KEYMAP(0x05ff08, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton8", BUTTON_8), + USB_KEYMAP(0x05ff09, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton9", BUTTON_9), + USB_KEYMAP(0x05ff0a, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton10", BUTTON_10), + USB_KEYMAP(0x05ff0b, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton11", BUTTON_11), + USB_KEYMAP(0x05ff0c, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton12", BUTTON_12), + USB_KEYMAP(0x05ff0d, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton13", BUTTON_13), + USB_KEYMAP(0x05ff0e, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton14", BUTTON_14), + USB_KEYMAP(0x05ff0f, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton15", BUTTON_15), + USB_KEYMAP(0x05ff10, 0x0000, 0x0000, 0x0000, 0xffff, "GameButton16", BUTTON_16), + USB_KEYMAP(0x05ff11, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonA", BUTTON_A), + USB_KEYMAP(0x05ff12, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonB", BUTTON_B), + USB_KEYMAP(0x05ff13, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonC", BUTTON_C), + USB_KEYMAP(0x05ff14, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonLeft1", BUTTON_L1), + USB_KEYMAP(0x05ff15, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonLeft2", BUTTON_L2), + USB_KEYMAP(0x05ff16, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonMode", BUTTON_MODE), + USB_KEYMAP(0x05ff17, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonRight1", BUTTON_R1), + USB_KEYMAP(0x05ff18, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonRight2", BUTTON_R2), + USB_KEYMAP(0x05ff19, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonSelect", BUTTON_SELECT), + USB_KEYMAP(0x05ff1a, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonStart", BUTTON_START), + USB_KEYMAP(0x05ff1b, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonThumbLeft", BUTTON_THUMBL), + USB_KEYMAP(0x05ff1c, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonThumbRight", BUTTON_THUMBR), + USB_KEYMAP(0x05ff1d, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonX", BUTTON_X), + USB_KEYMAP(0x05ff1e, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonY", BUTTON_Y), + USB_KEYMAP(0x05ff1f, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonZ", BUTTON_Z), diff --git a/dev/tools/gen_keycodes/lib/key_data.dart b/dev/tools/gen_keycodes/lib/key_data.dart index 3b9c8cac0f..71492ca3c5 100644 --- a/dev/tools/gen_keycodes/lib/key_data.dart +++ b/dev/tools/gen_keycodes/lib/key_data.dart @@ -375,7 +375,7 @@ class Key { static String getCommentName(String constantName) { String upperCamel = lowerCamelToUpperCamel(constantName); - upperCamel = upperCamel.replaceAllMapped(RegExp(r'(Digit|Numpad|Lang)([0-9]+)'), (Match match) => '${match.group(1)} ${match.group(2)}'); + upperCamel = upperCamel.replaceAllMapped(RegExp(r'(Digit|Numpad|Lang|Button|Left|Right)([0-9]+)'), (Match match) => '${match.group(1)} ${match.group(2)}'); return upperCamel.replaceAllMapped(RegExp(r'([A-Z])'), (Match match) => ' ${match.group(1)}').trim(); } diff --git a/packages/flutter/lib/src/services/keyboard_key.dart b/packages/flutter/lib/src/services/keyboard_key.dart index bc69d8c406..0f88afbd99 100644 --- a/packages/flutter/lib/src/services/keyboard_key.dart +++ b/packages/flutter/lib/src/services/keyboard_key.dart @@ -1455,6 +1455,161 @@ class LogicalKeyboardKey extends KeyboardKey { /// See the function [RawKeyEvent.logicalKey] for more information. static const LogicalKeyboardKey showAllWindows = LogicalKeyboardKey(0x001000c029f, debugName: kReleaseMode ? null : 'Show All Windows'); + /// Represents the logical "Game Button 1" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton1 = LogicalKeyboardKey(0x00100053701, debugName: kReleaseMode ? null : 'Game Button 1'); + + /// Represents the logical "Game Button 2" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton2 = LogicalKeyboardKey(0x00100053702, debugName: kReleaseMode ? null : 'Game Button 2'); + + /// Represents the logical "Game Button 3" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton3 = LogicalKeyboardKey(0x00100053703, debugName: kReleaseMode ? null : 'Game Button 3'); + + /// Represents the logical "Game Button 4" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton4 = LogicalKeyboardKey(0x00100053704, debugName: kReleaseMode ? null : 'Game Button 4'); + + /// Represents the logical "Game Button 5" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton5 = LogicalKeyboardKey(0x00100053705, debugName: kReleaseMode ? null : 'Game Button 5'); + + /// Represents the logical "Game Button 6" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton6 = LogicalKeyboardKey(0x00100053706, debugName: kReleaseMode ? null : 'Game Button 6'); + + /// Represents the logical "Game Button 7" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton7 = LogicalKeyboardKey(0x00100053707, debugName: kReleaseMode ? null : 'Game Button 7'); + + /// Represents the logical "Game Button 8" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton8 = LogicalKeyboardKey(0x00100053708, debugName: kReleaseMode ? null : 'Game Button 8'); + + /// Represents the logical "Game Button 9" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton9 = LogicalKeyboardKey(0x00100053709, debugName: kReleaseMode ? null : 'Game Button 9'); + + /// Represents the logical "Game Button 10" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton10 = LogicalKeyboardKey(0x0010005370a, debugName: kReleaseMode ? null : 'Game Button 10'); + + /// Represents the logical "Game Button 11" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton11 = LogicalKeyboardKey(0x0010005370b, debugName: kReleaseMode ? null : 'Game Button 11'); + + /// Represents the logical "Game Button 12" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton12 = LogicalKeyboardKey(0x0010005370c, debugName: kReleaseMode ? null : 'Game Button 12'); + + /// Represents the logical "Game Button 13" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton13 = LogicalKeyboardKey(0x0010005370d, debugName: kReleaseMode ? null : 'Game Button 13'); + + /// Represents the logical "Game Button 14" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton14 = LogicalKeyboardKey(0x0010005370e, debugName: kReleaseMode ? null : 'Game Button 14'); + + /// Represents the logical "Game Button 15" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton15 = LogicalKeyboardKey(0x0010005370f, debugName: kReleaseMode ? null : 'Game Button 15'); + + /// Represents the logical "Game Button 16" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButton16 = LogicalKeyboardKey(0x00100053710, debugName: kReleaseMode ? null : 'Game Button 16'); + + /// Represents the logical "Game Button A" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonA = LogicalKeyboardKey(0x00100053711, debugName: kReleaseMode ? null : 'Game Button A'); + + /// Represents the logical "Game Button B" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonB = LogicalKeyboardKey(0x00100053712, debugName: kReleaseMode ? null : 'Game Button B'); + + /// Represents the logical "Game Button C" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonC = LogicalKeyboardKey(0x00100053713, debugName: kReleaseMode ? null : 'Game Button C'); + + /// Represents the logical "Game Button Left 1" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonLeft1 = LogicalKeyboardKey(0x00100053714, debugName: kReleaseMode ? null : 'Game Button Left 1'); + + /// Represents the logical "Game Button Left 2" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonLeft2 = LogicalKeyboardKey(0x00100053715, debugName: kReleaseMode ? null : 'Game Button Left 2'); + + /// Represents the logical "Game Button Mode" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonMode = LogicalKeyboardKey(0x00100053716, debugName: kReleaseMode ? null : 'Game Button Mode'); + + /// Represents the logical "Game Button Right 1" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonRight1 = LogicalKeyboardKey(0x00100053717, debugName: kReleaseMode ? null : 'Game Button Right 1'); + + /// Represents the logical "Game Button Right 2" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonRight2 = LogicalKeyboardKey(0x00100053718, debugName: kReleaseMode ? null : 'Game Button Right 2'); + + /// Represents the logical "Game Button Select" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonSelect = LogicalKeyboardKey(0x00100053719, debugName: kReleaseMode ? null : 'Game Button Select'); + + /// Represents the logical "Game Button Start" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonStart = LogicalKeyboardKey(0x0010005371a, debugName: kReleaseMode ? null : 'Game Button Start'); + + /// Represents the logical "Game Button Thumb Left" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonThumbLeft = LogicalKeyboardKey(0x0010005371b, debugName: kReleaseMode ? null : 'Game Button Thumb Left'); + + /// Represents the logical "Game Button Thumb Right" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonThumbRight = LogicalKeyboardKey(0x0010005371c, debugName: kReleaseMode ? null : 'Game Button Thumb Right'); + + /// Represents the logical "Game Button X" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonX = LogicalKeyboardKey(0x0010005371d, debugName: kReleaseMode ? null : 'Game Button X'); + + /// Represents the logical "Game Button Y" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonY = LogicalKeyboardKey(0x0010005371e, debugName: kReleaseMode ? null : 'Game Button Y'); + + /// Represents the logical "Game Button Z" key on the keyboard. + /// + /// See the function [RawKeyEvent.logicalKey] for more information. + static const LogicalKeyboardKey gameButtonZ = LogicalKeyboardKey(0x0010005371f, debugName: kReleaseMode ? null : 'Game Button Z'); + /// Represents the logical "Shift" key on the keyboard. /// /// This key represents the union of the keys {shiftLeft, shiftRight} when @@ -1720,6 +1875,37 @@ class LogicalKeyboardKey extends KeyboardKey { 0x01000c028c: mailSend, 0x01000c029d: keyboardLayoutSelect, 0x01000c029f: showAllWindows, + 0x0100053701: gameButton1, + 0x0100053702: gameButton2, + 0x0100053703: gameButton3, + 0x0100053704: gameButton4, + 0x0100053705: gameButton5, + 0x0100053706: gameButton6, + 0x0100053707: gameButton7, + 0x0100053708: gameButton8, + 0x0100053709: gameButton9, + 0x010005370a: gameButton10, + 0x010005370b: gameButton11, + 0x010005370c: gameButton12, + 0x010005370d: gameButton13, + 0x010005370e: gameButton14, + 0x010005370f: gameButton15, + 0x0100053710: gameButton16, + 0x0100053711: gameButtonA, + 0x0100053712: gameButtonB, + 0x0100053713: gameButtonC, + 0x0100053714: gameButtonLeft1, + 0x0100053715: gameButtonLeft2, + 0x0100053716: gameButtonMode, + 0x0100053717: gameButtonRight1, + 0x0100053718: gameButtonRight2, + 0x0100053719: gameButtonSelect, + 0x010005371a: gameButtonStart, + 0x010005371b: gameButtonThumbLeft, + 0x010005371c: gameButtonThumbRight, + 0x010005371d: gameButtonX, + 0x010005371e: gameButtonY, + 0x010005371f: gameButtonZ, 0x201000700e1: shift, 0x201000700e3: meta, 0x201000700e2: alt, @@ -3139,6 +3325,192 @@ class PhysicalKeyboardKey extends KeyboardKey { /// See the function [RawKeyEvent.physicalKey] for more information. static const PhysicalKeyboardKey showAllWindows = PhysicalKeyboardKey(0x000c029f, debugName: kReleaseMode ? null : 'Show All Windows'); + /// Represents the location of the "Game Button 1" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton1 = PhysicalKeyboardKey(0x00053701, debugName: kReleaseMode ? null : 'Game Button 1'); + + /// Represents the location of the "Game Button 2" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton2 = PhysicalKeyboardKey(0x00053702, debugName: kReleaseMode ? null : 'Game Button 2'); + + /// Represents the location of the "Game Button 3" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton3 = PhysicalKeyboardKey(0x00053703, debugName: kReleaseMode ? null : 'Game Button 3'); + + /// Represents the location of the "Game Button 4" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton4 = PhysicalKeyboardKey(0x00053704, debugName: kReleaseMode ? null : 'Game Button 4'); + + /// Represents the location of the "Game Button 5" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton5 = PhysicalKeyboardKey(0x00053705, debugName: kReleaseMode ? null : 'Game Button 5'); + + /// Represents the location of the "Game Button 6" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton6 = PhysicalKeyboardKey(0x00053706, debugName: kReleaseMode ? null : 'Game Button 6'); + + /// Represents the location of the "Game Button 7" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton7 = PhysicalKeyboardKey(0x00053707, debugName: kReleaseMode ? null : 'Game Button 7'); + + /// Represents the location of the "Game Button 8" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton8 = PhysicalKeyboardKey(0x00053708, debugName: kReleaseMode ? null : 'Game Button 8'); + + /// Represents the location of the "Game Button 9" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton9 = PhysicalKeyboardKey(0x00053709, debugName: kReleaseMode ? null : 'Game Button 9'); + + /// Represents the location of the "Game Button 10" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton10 = PhysicalKeyboardKey(0x0005370a, debugName: kReleaseMode ? null : 'Game Button 10'); + + /// Represents the location of the "Game Button 11" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton11 = PhysicalKeyboardKey(0x0005370b, debugName: kReleaseMode ? null : 'Game Button 11'); + + /// Represents the location of the "Game Button 12" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton12 = PhysicalKeyboardKey(0x0005370c, debugName: kReleaseMode ? null : 'Game Button 12'); + + /// Represents the location of the "Game Button 13" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton13 = PhysicalKeyboardKey(0x0005370d, debugName: kReleaseMode ? null : 'Game Button 13'); + + /// Represents the location of the "Game Button 14" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton14 = PhysicalKeyboardKey(0x0005370e, debugName: kReleaseMode ? null : 'Game Button 14'); + + /// Represents the location of the "Game Button 15" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton15 = PhysicalKeyboardKey(0x0005370f, debugName: kReleaseMode ? null : 'Game Button 15'); + + /// Represents the location of the "Game Button 16" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButton16 = PhysicalKeyboardKey(0x00053710, debugName: kReleaseMode ? null : 'Game Button 16'); + + /// Represents the location of the "Game Button A" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonA = PhysicalKeyboardKey(0x00053711, debugName: kReleaseMode ? null : 'Game Button A'); + + /// Represents the location of the "Game Button B" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonB = PhysicalKeyboardKey(0x00053712, debugName: kReleaseMode ? null : 'Game Button B'); + + /// Represents the location of the "Game Button C" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonC = PhysicalKeyboardKey(0x00053713, debugName: kReleaseMode ? null : 'Game Button C'); + + /// Represents the location of the "Game Button Left 1" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonLeft1 = PhysicalKeyboardKey(0x00053714, debugName: kReleaseMode ? null : 'Game Button Left 1'); + + /// Represents the location of the "Game Button Left 2" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonLeft2 = PhysicalKeyboardKey(0x00053715, debugName: kReleaseMode ? null : 'Game Button Left 2'); + + /// Represents the location of the "Game Button Mode" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonMode = PhysicalKeyboardKey(0x00053716, debugName: kReleaseMode ? null : 'Game Button Mode'); + + /// Represents the location of the "Game Button Right 1" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonRight1 = PhysicalKeyboardKey(0x00053717, debugName: kReleaseMode ? null : 'Game Button Right 1'); + + /// Represents the location of the "Game Button Right 2" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonRight2 = PhysicalKeyboardKey(0x00053718, debugName: kReleaseMode ? null : 'Game Button Right 2'); + + /// Represents the location of the "Game Button Select" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonSelect = PhysicalKeyboardKey(0x00053719, debugName: kReleaseMode ? null : 'Game Button Select'); + + /// Represents the location of the "Game Button Start" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonStart = PhysicalKeyboardKey(0x0005371a, debugName: kReleaseMode ? null : 'Game Button Start'); + + /// Represents the location of the "Game Button Thumb Left" key on a + /// generalized keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonThumbLeft = PhysicalKeyboardKey(0x0005371b, debugName: kReleaseMode ? null : 'Game Button Thumb Left'); + + /// Represents the location of the "Game Button Thumb Right" key on a + /// generalized keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonThumbRight = PhysicalKeyboardKey(0x0005371c, debugName: kReleaseMode ? null : 'Game Button Thumb Right'); + + /// Represents the location of the "Game Button X" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonX = PhysicalKeyboardKey(0x0005371d, debugName: kReleaseMode ? null : 'Game Button X'); + + /// Represents the location of the "Game Button Y" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonY = PhysicalKeyboardKey(0x0005371e, debugName: kReleaseMode ? null : 'Game Button Y'); + + /// Represents the location of the "Game Button Z" key on a generalized + /// keyboard. + /// + /// See the function [RawKeyEvent.physicalKey] for more information. + static const PhysicalKeyboardKey gameButtonZ = PhysicalKeyboardKey(0x0005371f, debugName: kReleaseMode ? null : 'Game Button Z'); + // A list of all the predefined constant PhysicalKeyboardKeys so that they // can be searched. static const Map _knownPhysicalKeys = { @@ -3376,5 +3748,36 @@ class PhysicalKeyboardKey extends KeyboardKey { 0x000c028c: mailSend, 0x000c029d: keyboardLayoutSelect, 0x000c029f: showAllWindows, + 0x00053701: gameButton1, + 0x00053702: gameButton2, + 0x00053703: gameButton3, + 0x00053704: gameButton4, + 0x00053705: gameButton5, + 0x00053706: gameButton6, + 0x00053707: gameButton7, + 0x00053708: gameButton8, + 0x00053709: gameButton9, + 0x0005370a: gameButton10, + 0x0005370b: gameButton11, + 0x0005370c: gameButton12, + 0x0005370d: gameButton13, + 0x0005370e: gameButton14, + 0x0005370f: gameButton15, + 0x00053710: gameButton16, + 0x00053711: gameButtonA, + 0x00053712: gameButtonB, + 0x00053713: gameButtonC, + 0x00053714: gameButtonLeft1, + 0x00053715: gameButtonLeft2, + 0x00053716: gameButtonMode, + 0x00053717: gameButtonRight1, + 0x00053718: gameButtonRight2, + 0x00053719: gameButtonSelect, + 0x0005371a: gameButtonStart, + 0x0005371b: gameButtonThumbLeft, + 0x0005371c: gameButtonThumbRight, + 0x0005371d: gameButtonX, + 0x0005371e: gameButtonY, + 0x0005371f: gameButtonZ, }; } diff --git a/packages/flutter/lib/src/services/keyboard_maps.dart b/packages/flutter/lib/src/services/keyboard_maps.dart index 175e9a186b..d5b3cb50f2 100644 --- a/packages/flutter/lib/src/services/keyboard_maps.dart +++ b/packages/flutter/lib/src/services/keyboard_maps.dart @@ -116,6 +116,7 @@ const Map kAndroidToLogicalKey = kAndroidToLogicalKey = kAndroidToPhysicalKey = kAndroidToPhysicalKey = kFuchsiaToLogicalKey = kFuchsiaToPhysicalKey = + /// for the numerical values of the `source`. Many of these constants are also + /// replicated as static constants in this class. + final int eventSource; + + /// The vendor ID of the device that produced the event. + /// + /// See + /// for the numerical values of the `vendorId`. + final int vendorId; + + /// The product ID of the device that produced the event. + /// + /// See + /// for the numerical values of the `productId`. + final int productId; + + // The source code that indicates that an event came from a joystick. + // from https://developer.android.com/reference/android/view/InputDevice.html#SOURCE_JOYSTICK + static const int _sourceJoystick = 0x01000010; + // Android only reports a single code point for the key label. @override String get keyLabel => plainCodePoint == 0 ? null : String.fromCharCode(plainCodePoint & _kCombiningCharacterMask); @override - PhysicalKeyboardKey get physicalKey => kAndroidToPhysicalKey[scanCode] ?? PhysicalKeyboardKey.none; + PhysicalKeyboardKey get physicalKey { + if (kAndroidToPhysicalKey.containsKey(scanCode)) { + return kAndroidToPhysicalKey[scanCode] ?? PhysicalKeyboardKey.none; + } + + // Android sends DPAD_UP, etc. as the keyCode for joystick DPAD events, but + // it doesn't set the scanCode for those, so we have to detect this, and set + // our own DPAD physical keys. The logical key will still match "arrowUp", + // etc. + if (eventSource & _sourceJoystick == _sourceJoystick) { + final LogicalKeyboardKey foundKey = kAndroidToLogicalKey[keyCode]; + if (foundKey == LogicalKeyboardKey.arrowUp) { + return PhysicalKeyboardKey.arrowUp; + } + if (foundKey == LogicalKeyboardKey.arrowDown) { + return PhysicalKeyboardKey.arrowDown; + } + if (foundKey == LogicalKeyboardKey.arrowLeft) { + return PhysicalKeyboardKey.arrowLeft; + } + if (foundKey == LogicalKeyboardKey.arrowRight) { + return PhysicalKeyboardKey.arrowRight; + } + } + return PhysicalKeyboardKey.none; + } @override LogicalKeyboardKey get logicalKey { diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index fec0a66bad..02e2ade5ec 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -39,6 +39,7 @@ void main() { 'codePoint': 0x44, 'scanCode': 0x20, 'metaState': modifier, + 'source': 0x101, // Keyboard source. }); final RawKeyEventDataAndroid data = event.data; for (ModifierKey key in ModifierKey.values) { @@ -73,6 +74,7 @@ void main() { 'codePoint': 0x44, 'scanCode': 0x20, 'metaState': modifier | RawKeyEventDataAndroid.modifierFunction, + 'source': 0x101, // Keyboard source. }); final RawKeyEventDataAndroid data = event.data; for (ModifierKey key in ModifierKey.values) { @@ -109,6 +111,7 @@ void main() { 'character': 'A', 'scanCode': 30, 'metaState': 0x0, + 'source': 0x101, // Keyboard source. }); final RawKeyEventDataAndroid data = keyAEvent.data; expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA)); @@ -124,6 +127,7 @@ void main() { 'character': null, 'scanCode': 1, 'metaState': 0x0, + 'source': 0x101, // Keyboard source. }); final RawKeyEventDataAndroid data = escapeKeyEvent.data; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); @@ -140,12 +144,64 @@ void main() { 'character': null, 'scanCode': 42, 'metaState': RawKeyEventDataAndroid.modifierLeftShift, + 'source': 0x101, // Keyboard source. }); final RawKeyEventDataAndroid data = shiftLeftKeyEvent.data; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); expect(data.keyLabel, isNull); }); + test('DPAD keys from a joystick give physical key mappings', () { + final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'android', + 'keyCode': 20, + 'plainCodePoint': 0, + 'codePoint': 0, + 'character': null, + 'scanCode': 0, + 'metaState': 0, + 'source': 0x1000010, // Joystick source. + }); + final RawKeyEventDataAndroid data = joystickDpadDown.data; + expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowDown)); + expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); + expect(data.keyLabel, isNull); + }); + test('Arrow keys from a keyboard give correct physical key mappings', () { + final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'android', + 'keyCode': 20, + 'plainCodePoint': 0, + 'codePoint': 0, + 'character': null, + 'scanCode': 108, + 'metaState': 0, + 'source': 0x101, // Keyboard source. + }); + final RawKeyEventDataAndroid data = joystickDpadDown.data; + expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowDown)); + expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); + expect(data.keyLabel, isNull); + }); + test('DPAD center from a game pad gives physical key mappings', () { + final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'android', + 'keyCode': 23, // DPAD_CENTER code. + 'plainCodePoint': 0, + 'codePoint': 0, + 'character': null, + 'scanCode': 317, // Left side thumb joystick center click button. + 'metaState': 0, + 'source': 0x501, // Gamepad and keyboard source. + }); + final RawKeyEventDataAndroid data = joystickDpadCenter.data; + expect(data.physicalKey, equals(PhysicalKeyboardKey.gameButtonThumbLeft)); + expect(data.logicalKey, equals(LogicalKeyboardKey.select)); + expect(data.keyLabel, isNull); + }); }); group('RawKeyEventDataFuchsia', () { const Map modifierTests = {