diff --git a/dev/tools/gen_keycodes/bin/gen_keycodes.dart b/dev/tools/gen_keycodes/bin/gen_keycodes.dart index c8fdf13b84..25164c15ec 100644 --- a/dev/tools/gen_keycodes/bin/gen_keycodes.dart +++ b/dev/tools/gen_keycodes/bin/gen_keycodes.dart @@ -49,6 +49,11 @@ Future getGlfwKeyCodes() async { return await http.read(keyCodesUri); } +Future getGtkKeyCodes() async { + final Uri keyCodesUri = Uri.parse('https://gitlab.gnome.org/GNOME/gtk/-/raw/master/gdk/gdkkeysyms.h'); + return await http.read(keyCodesUri); +} + Future main(List rawArguments) async { final ArgParser argParser = ArgParser(); argParser.addOption( @@ -90,6 +95,13 @@ Future main(List rawArguments) async { 'If --glfw-keycodes is not specified, the input will be read from the ' 'correct file in the GLFW github repository.', ); + argParser.addOption( + 'gtk-keycodes', + defaultsTo: null, + help: 'The path to where the GTK keycodes header file should be read. ' + 'If --gtk-keycodes is not specified, the input will be read from the ' + 'correct file in the GTK repository.', + ); argParser.addOption( 'windows-keycodes', defaultsTo: null, @@ -107,6 +119,11 @@ Future main(List rawArguments) async { defaultsTo: path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'key_name_to_glfw_name.json'), help: 'The path to where the GLFW keycode to DomKey mapping is.', ); + argParser.addOption( + 'gtk-domkey', + defaultsTo: path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'key_name_to_gtk_name.json'), + help: 'The path to where the GTK keycode to DomKey mapping is.', + ); argParser.addOption( 'data', defaultsTo: path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'key_data.json'), @@ -187,6 +204,13 @@ Future main(List rawArguments) async { glfwKeyCodes = File(parsedArguments['glfw-keycodes'] as String).readAsStringSync(); } + String gtkKeyCodes; + if (parsedArguments['gtk-keycodes'] == null) { + gtkKeyCodes = await getGtkKeyCodes(); + } else { + gtkKeyCodes = File(parsedArguments['gtk-keycodes'] as String).readAsStringSync(); + } + String windowsKeyCodes; if (parsedArguments['windows-keycodes'] == null) { windowsKeyCodes = await getWindowsKeyCodes(); @@ -196,9 +220,10 @@ Future main(List rawArguments) async { final String windowsToDomKey = File(parsedArguments['windows-domkey'] as String).readAsStringSync(); final String glfwToDomKey = File(parsedArguments['glfw-domkey'] as String).readAsStringSync(); + final String gtkToDomKey = File(parsedArguments['gtk-domkey'] as String).readAsStringSync(); final String androidToDomKey = File(parsedArguments['android-domkey'] as String).readAsStringSync(); - data = KeyData(hidCodes, androidScanCodes, androidKeyCodes, androidToDomKey, glfwKeyCodes, glfwToDomKey, windowsKeyCodes, windowsToDomKey); + data = KeyData(hidCodes, androidScanCodes, androidKeyCodes, androidToDomKey, glfwKeyCodes, glfwToDomKey, gtkKeyCodes, gtkToDomKey, windowsKeyCodes, windowsToDomKey); const JsonEncoder encoder = JsonEncoder.withIndent(' '); File(parsedArguments['data'] as String).writeAsStringSync(encoder.convert(data.toJson())); @@ -221,7 +246,7 @@ Future main(List rawArguments) async { await mapsFile.writeAsString(generator.generateKeyboardMaps()); final CcCodeGenerator ccCodeGenerator = CcCodeGenerator(data); - for (final String platform in ['android', 'darwin', 'glfw', 'fuchsia', 'linux', 'windows']) { + for (final String platform in ['android', 'darwin', 'glfw', 'gtk', 'fuchsia', 'linux', 'windows']) { final File platformFile = File(path.join(flutterRoot.path, '..', path.join('engine', 'src', 'flutter', 'shell', 'platform', platform, 'keycodes', 'keyboard_map_$platform.h'))); if (!platformFile.existsSync()) { platformFile.createSync(recursive: true); diff --git a/dev/tools/gen_keycodes/data/key_data.json b/dev/tools/gen_keycodes/data/key_data.json index 5179151e06..e5c291cc7c 100644 --- a/dev/tools/gen_keycodes/data/key_data.json +++ b/dev/tools/gen_keycodes/data/key_data.json @@ -8,6 +8,7 @@ "english": "None", "chromium": "none", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -23,6 +24,7 @@ 0 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -33,6 +35,10 @@ "english": "Hyper", "chromium": "hyper", "glfw": null, + "gtk": [ + "Hyper_L", + "Hyper_R" + ], "windows": null }, "scanCodes": { @@ -46,6 +52,10 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65517, + 65518 + ], "windows": null } }, @@ -56,6 +66,10 @@ "english": "Super Key", "chromium": "super", "glfw": null, + "gtk": [ + "Super_L", + "Super_R" + ], "windows": null }, "scanCodes": { @@ -69,6 +83,10 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65515, + 65516 + ], "windows": null } }, @@ -79,6 +97,7 @@ "english": "Fn Lock", "chromium": "fnLock", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -92,6 +111,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -104,6 +124,9 @@ "english": "Suspend", "chromium": "suspend", "glfw": null, + "gtk": [ + "Suspend" + ], "windows": null }, "scanCodes": { @@ -119,6 +142,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025191 + ], "windows": null } }, @@ -129,6 +155,9 @@ "english": "Resume", "chromium": "resume", "glfw": null, + "gtk": [ + "Resume" + ], "windows": null }, "scanCodes": { @@ -142,6 +171,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -152,6 +182,7 @@ "english": "Turbo", "chromium": "turbo", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -165,6 +196,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -175,6 +207,7 @@ "english": "Privacy Screen Toggle", "chromium": "privacyScreenToggle", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -188,6 +221,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -200,6 +234,9 @@ "english": "Sleep", "chromium": "sleep", "glfw": null, + "gtk": [ + "Sleep" + ], "windows": [ "SLEEP" ] @@ -219,6 +256,9 @@ 223 ], "glfw": null, + "gtk": [ + 269025071 + ], "windows": [ 95 ] @@ -233,6 +273,9 @@ "english": "Wake Up", "chromium": "wakeUp", "glfw": null, + "gtk": [ + "WakeUp" + ], "windows": null }, "scanCodes": { @@ -250,6 +293,9 @@ 224 ], "glfw": null, + "gtk": [ + 269025067 + ], "windows": null } }, @@ -260,6 +306,7 @@ "english": "Display Toggle Int Ext", "chromium": "displayToggleIntExt", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -273,6 +320,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -283,6 +331,7 @@ "english": "Usb Reserved", "chromium": "usbReserved", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -296,6 +345,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -306,6 +356,7 @@ "english": "Usb Error Roll Over", "chromium": "usbErrorRollOver", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -319,6 +370,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -329,6 +381,7 @@ "english": "Usb Post Fail", "chromium": "usbPostFail", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -342,6 +395,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -352,6 +406,7 @@ "english": "Usb Error Undefined", "chromium": "usbErrorUndefined", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -365,6 +420,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -379,6 +435,9 @@ "glfw": [ "A" ], + "gtk": [ + "A" + ], "windows": [ "A" ] @@ -400,6 +459,9 @@ "glfw": [ 65 ], + "gtk": [ + 65 + ], "windows": [ 65 ] @@ -416,6 +478,9 @@ "glfw": [ "B" ], + "gtk": [ + "B" + ], "windows": [ "B" ] @@ -437,6 +502,9 @@ "glfw": [ 66 ], + "gtk": [ + 66 + ], "windows": [ 66 ] @@ -453,6 +521,9 @@ "glfw": [ "C" ], + "gtk": [ + "C" + ], "windows": [ "C" ] @@ -474,6 +545,9 @@ "glfw": [ 67 ], + "gtk": [ + 67 + ], "windows": [ 67 ] @@ -490,6 +564,9 @@ "glfw": [ "D" ], + "gtk": [ + "D" + ], "windows": [ "D" ] @@ -511,6 +588,9 @@ "glfw": [ 68 ], + "gtk": [ + 68 + ], "windows": [ 68 ] @@ -527,6 +607,9 @@ "glfw": [ "E" ], + "gtk": [ + "E" + ], "windows": [ "E" ] @@ -548,6 +631,9 @@ "glfw": [ 69 ], + "gtk": [ + 69 + ], "windows": [ 69 ] @@ -564,6 +650,9 @@ "glfw": [ "F" ], + "gtk": [ + "F" + ], "windows": [ "F" ] @@ -585,6 +674,9 @@ "glfw": [ 70 ], + "gtk": [ + 70 + ], "windows": [ 70 ] @@ -601,6 +693,9 @@ "glfw": [ "G" ], + "gtk": [ + "G" + ], "windows": [ "G" ] @@ -622,6 +717,9 @@ "glfw": [ 71 ], + "gtk": [ + 71 + ], "windows": [ 71 ] @@ -638,6 +736,9 @@ "glfw": [ "H" ], + "gtk": [ + "H" + ], "windows": [ "H" ] @@ -659,6 +760,9 @@ "glfw": [ 72 ], + "gtk": [ + 72 + ], "windows": [ 72 ] @@ -675,6 +779,9 @@ "glfw": [ "I" ], + "gtk": [ + "I" + ], "windows": [ "I" ] @@ -696,6 +803,9 @@ "glfw": [ 73 ], + "gtk": [ + 73 + ], "windows": [ 73 ] @@ -712,6 +822,9 @@ "glfw": [ "J" ], + "gtk": [ + "J" + ], "windows": [ "J" ] @@ -733,6 +846,9 @@ "glfw": [ 74 ], + "gtk": [ + 74 + ], "windows": [ 74 ] @@ -749,6 +865,9 @@ "glfw": [ "K" ], + "gtk": [ + "K" + ], "windows": [ "K" ] @@ -770,6 +889,9 @@ "glfw": [ 75 ], + "gtk": [ + 75 + ], "windows": [ 75 ] @@ -786,6 +908,9 @@ "glfw": [ "L" ], + "gtk": [ + "L" + ], "windows": [ "L" ] @@ -807,6 +932,9 @@ "glfw": [ 76 ], + "gtk": [ + 76 + ], "windows": [ 76 ] @@ -823,6 +951,9 @@ "glfw": [ "M" ], + "gtk": [ + "M" + ], "windows": [ "M" ] @@ -844,6 +975,9 @@ "glfw": [ 77 ], + "gtk": [ + 77 + ], "windows": [ 77 ] @@ -860,6 +994,9 @@ "glfw": [ "N" ], + "gtk": [ + "N" + ], "windows": [ "N" ] @@ -881,6 +1018,9 @@ "glfw": [ 78 ], + "gtk": [ + 78 + ], "windows": [ 78 ] @@ -897,6 +1037,9 @@ "glfw": [ "O" ], + "gtk": [ + "O" + ], "windows": [ "O" ] @@ -918,6 +1061,9 @@ "glfw": [ 79 ], + "gtk": [ + 79 + ], "windows": [ 79 ] @@ -934,6 +1080,9 @@ "glfw": [ "P" ], + "gtk": [ + "P" + ], "windows": [ "P" ] @@ -955,6 +1104,9 @@ "glfw": [ 80 ], + "gtk": [ + 80 + ], "windows": [ 80 ] @@ -971,6 +1123,9 @@ "glfw": [ "Q" ], + "gtk": [ + "Q" + ], "windows": [ "Q" ] @@ -992,6 +1147,9 @@ "glfw": [ 81 ], + "gtk": [ + 81 + ], "windows": [ 81 ] @@ -1008,6 +1166,9 @@ "glfw": [ "R" ], + "gtk": [ + "R" + ], "windows": [ "R" ] @@ -1029,6 +1190,9 @@ "glfw": [ 82 ], + "gtk": [ + 82 + ], "windows": [ 82 ] @@ -1045,6 +1209,9 @@ "glfw": [ "S" ], + "gtk": [ + "S" + ], "windows": [ "S" ] @@ -1066,6 +1233,9 @@ "glfw": [ 83 ], + "gtk": [ + 83 + ], "windows": [ 83 ] @@ -1082,6 +1252,9 @@ "glfw": [ "T" ], + "gtk": [ + "T" + ], "windows": [ "T" ] @@ -1103,6 +1276,9 @@ "glfw": [ 84 ], + "gtk": [ + 84 + ], "windows": [ 84 ] @@ -1119,6 +1295,9 @@ "glfw": [ "U" ], + "gtk": [ + "U" + ], "windows": [ "U" ] @@ -1140,6 +1319,9 @@ "glfw": [ 85 ], + "gtk": [ + 85 + ], "windows": [ 85 ] @@ -1156,6 +1338,9 @@ "glfw": [ "V" ], + "gtk": [ + "V" + ], "windows": [ "V" ] @@ -1177,6 +1362,9 @@ "glfw": [ 86 ], + "gtk": [ + 86 + ], "windows": [ 86 ] @@ -1193,6 +1381,9 @@ "glfw": [ "W" ], + "gtk": [ + "W" + ], "windows": [ "W" ] @@ -1214,6 +1405,9 @@ "glfw": [ 87 ], + "gtk": [ + 87 + ], "windows": [ 87 ] @@ -1230,6 +1424,9 @@ "glfw": [ "X" ], + "gtk": [ + "X" + ], "windows": [ "X" ] @@ -1251,6 +1448,9 @@ "glfw": [ 88 ], + "gtk": [ + 88 + ], "windows": [ 88 ] @@ -1267,6 +1467,9 @@ "glfw": [ "Y" ], + "gtk": [ + "Y" + ], "windows": [ "Y" ] @@ -1288,6 +1491,9 @@ "glfw": [ 89 ], + "gtk": [ + 89 + ], "windows": [ 89 ] @@ -1304,6 +1510,9 @@ "glfw": [ "Z" ], + "gtk": [ + "Z" + ], "windows": [ "Z" ] @@ -1325,6 +1534,9 @@ "glfw": [ 90 ], + "gtk": [ + 90 + ], "windows": [ 90 ] @@ -1341,6 +1553,9 @@ "glfw": [ "1" ], + "gtk": [ + "1" + ], "windows": null }, "scanCodes": { @@ -1360,6 +1575,9 @@ "glfw": [ 49 ], + "gtk": [ + 49 + ], "windows": null } }, @@ -1374,6 +1592,9 @@ "glfw": [ "2" ], + "gtk": [ + "2" + ], "windows": null }, "scanCodes": { @@ -1393,6 +1614,9 @@ "glfw": [ 50 ], + "gtk": [ + 50 + ], "windows": null } }, @@ -1407,6 +1631,9 @@ "glfw": [ "3" ], + "gtk": [ + "3" + ], "windows": null }, "scanCodes": { @@ -1426,6 +1653,9 @@ "glfw": [ 51 ], + "gtk": [ + 51 + ], "windows": null } }, @@ -1440,6 +1670,9 @@ "glfw": [ "4" ], + "gtk": [ + "4" + ], "windows": null }, "scanCodes": { @@ -1459,6 +1692,9 @@ "glfw": [ 52 ], + "gtk": [ + 52 + ], "windows": null } }, @@ -1473,6 +1709,9 @@ "glfw": [ "5" ], + "gtk": [ + "5" + ], "windows": null }, "scanCodes": { @@ -1492,6 +1731,9 @@ "glfw": [ 53 ], + "gtk": [ + 53 + ], "windows": null } }, @@ -1506,6 +1748,9 @@ "glfw": [ "6" ], + "gtk": [ + "6" + ], "windows": null }, "scanCodes": { @@ -1525,6 +1770,9 @@ "glfw": [ 54 ], + "gtk": [ + 54 + ], "windows": null } }, @@ -1539,6 +1787,9 @@ "glfw": [ "7" ], + "gtk": [ + "7" + ], "windows": null }, "scanCodes": { @@ -1558,6 +1809,9 @@ "glfw": [ 55 ], + "gtk": [ + 55 + ], "windows": null } }, @@ -1572,6 +1826,9 @@ "glfw": [ "8" ], + "gtk": [ + "8" + ], "windows": null }, "scanCodes": { @@ -1591,6 +1848,9 @@ "glfw": [ 56 ], + "gtk": [ + 56 + ], "windows": null } }, @@ -1605,6 +1865,9 @@ "glfw": [ "9" ], + "gtk": [ + "9" + ], "windows": null }, "scanCodes": { @@ -1624,6 +1887,9 @@ "glfw": [ 57 ], + "gtk": [ + 57 + ], "windows": null } }, @@ -1638,6 +1904,9 @@ "glfw": [ "0" ], + "gtk": [ + "0" + ], "windows": null }, "scanCodes": { @@ -1657,6 +1926,9 @@ "glfw": [ 48 ], + "gtk": [ + 48 + ], "windows": null } }, @@ -1671,6 +1943,10 @@ "glfw": [ "ENTER" ], + "gtk": [ + "Return", + "Enter" + ], "windows": [ "RETURN" ] @@ -1692,6 +1968,9 @@ "glfw": [ 257 ], + "gtk": [ + 65293 + ], "windows": [ 13 ] @@ -1708,6 +1987,9 @@ "glfw": [ "ESCAPE" ], + "gtk": [ + "Escape" + ], "windows": [ "ESCAPE" ] @@ -1729,6 +2011,9 @@ "glfw": [ 256 ], + "gtk": [ + 65307 + ], "windows": [ 27 ] @@ -1745,6 +2030,9 @@ "glfw": [ "BACKSPACE" ], + "gtk": [ + "BackSpace" + ], "windows": [ "BACK" ] @@ -1766,6 +2054,9 @@ "glfw": [ 259 ], + "gtk": [ + 65288 + ], "windows": [ 8 ] @@ -1782,6 +2073,10 @@ "glfw": [ "TAB" ], + "gtk": [ + "Tab", + "KP_Tab" + ], "windows": [ "TAB" ] @@ -1803,6 +2098,10 @@ "glfw": [ 258 ], + "gtk": [ + 65289, + 65417 + ], "windows": [ 9 ] @@ -1819,6 +2118,10 @@ "glfw": [ "SPACE" ], + "gtk": [ + "space", + "KP_Space" + ], "windows": [ "SPACE" ] @@ -1840,6 +2143,10 @@ "glfw": [ 32 ], + "gtk": [ + 32, + 65408 + ], "windows": [ 32 ] @@ -1856,6 +2163,9 @@ "glfw": [ "MINUS" ], + "gtk": [ + "minus" + ], "windows": [ "OEM_MINUS" ] @@ -1877,6 +2187,9 @@ "glfw": [ 45 ], + "gtk": [ + 45 + ], "windows": [ 189 ] @@ -1893,6 +2206,9 @@ "glfw": [ "EQUAL" ], + "gtk": [ + "equal" + ], "windows": [ "OEM_PLUS" ] @@ -1914,6 +2230,9 @@ "glfw": [ 61 ], + "gtk": [ + 61 + ], "windows": [ 187 ] @@ -1930,6 +2249,9 @@ "glfw": [ "LEFT_BRACKET" ], + "gtk": [ + "bracketleft" + ], "windows": [ "OEM_4" ] @@ -1951,6 +2273,9 @@ "glfw": [ 91 ], + "gtk": [ + 91 + ], "windows": [ 219 ] @@ -1967,6 +2292,9 @@ "glfw": [ "RIGHT_BRACKET" ], + "gtk": [ + "bracketright" + ], "windows": [ "OEM_6" ] @@ -1988,6 +2316,9 @@ "glfw": [ 93 ], + "gtk": [ + 93 + ], "windows": [ 221 ] @@ -2004,6 +2335,9 @@ "glfw": [ "BACKSLASH" ], + "gtk": [ + "backslash" + ], "windows": [ "OEM_5" ] @@ -2026,6 +2360,9 @@ "glfw": [ 92 ], + "gtk": [ + 92 + ], "windows": [ 220 ] @@ -2042,6 +2379,9 @@ "glfw": [ "SEMICOLON" ], + "gtk": [ + "semicolon" + ], "windows": [ "OEM_1" ] @@ -2063,6 +2403,9 @@ "glfw": [ 59 ], + "gtk": [ + 59 + ], "windows": [ 186 ] @@ -2079,6 +2422,9 @@ "glfw": [ "APOSTROPHE" ], + "gtk": [ + "apostrophe" + ], "windows": [ "OEM_7" ] @@ -2100,6 +2446,9 @@ "glfw": [ 39 ], + "gtk": [ + 39 + ], "windows": [ 222 ] @@ -2116,6 +2465,9 @@ "glfw": [ "GRAVE_ACCENT" ], + "gtk": [ + "quoteleft" + ], "windows": null }, "scanCodes": { @@ -2135,6 +2487,9 @@ "glfw": [ 96 ], + "gtk": [ + 96 + ], "windows": null } }, @@ -2149,6 +2504,9 @@ "glfw": [ "COMMA" ], + "gtk": [ + "comma" + ], "windows": [ "OEM_COMMA" ] @@ -2170,6 +2528,9 @@ "glfw": [ 44 ], + "gtk": [ + 44 + ], "windows": [ 188 ] @@ -2186,6 +2547,9 @@ "glfw": [ "PERIOD" ], + "gtk": [ + "period" + ], "windows": [ "OEM_PERIOD" ] @@ -2207,6 +2571,9 @@ "glfw": [ 46 ], + "gtk": [ + 46 + ], "windows": [ 190 ] @@ -2223,6 +2590,9 @@ "glfw": [ "SLASH" ], + "gtk": [ + "slash" + ], "windows": [ "OEM_2" ] @@ -2244,6 +2614,9 @@ "glfw": [ 47 ], + "gtk": [ + 47 + ], "windows": [ 191 ] @@ -2260,6 +2633,9 @@ "glfw": [ "CAPS_LOCK" ], + "gtk": [ + "Caps_Lock" + ], "windows": [ "CAPITAL" ] @@ -2281,6 +2657,9 @@ "glfw": [ 280 ], + "gtk": [ + 65509 + ], "windows": [ 20 ] @@ -2297,6 +2676,10 @@ "glfw": [ "F1" ], + "gtk": [ + "F1", + "KP_F1" + ], "windows": [ "F1" ] @@ -2318,6 +2701,10 @@ "glfw": [ 290 ], + "gtk": [ + 65470, + 65425 + ], "windows": [ 112 ] @@ -2334,6 +2721,10 @@ "glfw": [ "F2" ], + "gtk": [ + "F2", + "KP_F2" + ], "windows": [ "F2" ] @@ -2355,6 +2746,10 @@ "glfw": [ 291 ], + "gtk": [ + 65471, + 65426 + ], "windows": [ 113 ] @@ -2371,6 +2766,10 @@ "glfw": [ "F3" ], + "gtk": [ + "F3", + "KP_F3" + ], "windows": [ "F3" ] @@ -2392,6 +2791,10 @@ "glfw": [ 292 ], + "gtk": [ + 65472, + 65427 + ], "windows": [ 114 ] @@ -2408,6 +2811,10 @@ "glfw": [ "F4" ], + "gtk": [ + "F4", + "KP_F4" + ], "windows": [ "F4" ] @@ -2429,6 +2836,10 @@ "glfw": [ 293 ], + "gtk": [ + 65473, + 65428 + ], "windows": [ 115 ] @@ -2445,6 +2856,9 @@ "glfw": [ "F5" ], + "gtk": [ + "F5" + ], "windows": [ "F5" ] @@ -2466,6 +2880,9 @@ "glfw": [ 294 ], + "gtk": [ + 65474 + ], "windows": [ 116 ] @@ -2482,6 +2899,9 @@ "glfw": [ "F6" ], + "gtk": [ + "F6" + ], "windows": [ "F6" ] @@ -2503,6 +2923,9 @@ "glfw": [ 295 ], + "gtk": [ + 65475 + ], "windows": [ 117 ] @@ -2519,6 +2942,9 @@ "glfw": [ "F7" ], + "gtk": [ + "F7" + ], "windows": [ "F7" ] @@ -2540,6 +2966,9 @@ "glfw": [ 296 ], + "gtk": [ + 65476 + ], "windows": [ 118 ] @@ -2556,6 +2985,9 @@ "glfw": [ "F8" ], + "gtk": [ + "F8" + ], "windows": [ "F8" ] @@ -2577,6 +3009,9 @@ "glfw": [ 297 ], + "gtk": [ + 65477 + ], "windows": [ 119 ] @@ -2593,6 +3028,9 @@ "glfw": [ "F9" ], + "gtk": [ + "F9" + ], "windows": [ "F9" ] @@ -2614,6 +3052,9 @@ "glfw": [ 298 ], + "gtk": [ + 65478 + ], "windows": [ 120 ] @@ -2630,6 +3071,9 @@ "glfw": [ "F10" ], + "gtk": [ + "F10" + ], "windows": [ "F10" ] @@ -2651,6 +3095,9 @@ "glfw": [ 299 ], + "gtk": [ + 65479 + ], "windows": [ 121 ] @@ -2667,6 +3114,9 @@ "glfw": [ "F11" ], + "gtk": [ + "F11" + ], "windows": [ "F11" ] @@ -2688,6 +3138,9 @@ "glfw": [ 300 ], + "gtk": [ + 65480 + ], "windows": [ 122 ] @@ -2704,6 +3157,9 @@ "glfw": [ "F12" ], + "gtk": [ + "F12" + ], "windows": [ "F12" ] @@ -2725,6 +3181,9 @@ "glfw": [ 301 ], + "gtk": [ + 65481 + ], "windows": [ 123 ] @@ -2741,6 +3200,9 @@ "glfw": [ "PRINT_SCREEN" ], + "gtk": [ + "3270_PrintScreen" + ], "windows": null }, "scanCodes": { @@ -2760,6 +3222,9 @@ "glfw": [ 283 ], + "gtk": [ + 64797 + ], "windows": null } }, @@ -2772,6 +3237,9 @@ "english": "Scroll Lock", "chromium": "scrollLock", "glfw": null, + "gtk": [ + "Scroll_Lock" + ], "windows": null }, "scanCodes": { @@ -2789,6 +3257,9 @@ 116 ], "glfw": null, + "gtk": [ + 65300 + ], "windows": null } }, @@ -2803,6 +3274,9 @@ "glfw": [ "PAUSE" ], + "gtk": [ + "Pause" + ], "windows": [ "PAUSE" ] @@ -2825,6 +3299,9 @@ "glfw": [ 284 ], + "gtk": [ + 65299 + ], "windows": [ 19 ] @@ -2841,6 +3318,10 @@ "glfw": [ "INSERT" ], + "gtk": [ + "Insert", + "KP_Insert" + ], "windows": [ "INSERT" ] @@ -2862,6 +3343,10 @@ "glfw": [ 260 ], + "gtk": [ + 65379, + 65438 + ], "windows": [ 45 ] @@ -2878,6 +3363,10 @@ "glfw": [ "HOME" ], + "gtk": [ + "Home", + "KP_Home" + ], "windows": [ "HOME" ] @@ -2899,6 +3388,10 @@ "glfw": [ 268 ], + "gtk": [ + 65360, + 65429 + ], "windows": [ 36 ] @@ -2915,6 +3408,10 @@ "glfw": [ "PAGE_UP" ], + "gtk": [ + "Page_Up", + "KP_Page_Up" + ], "windows": null }, "scanCodes": { @@ -2935,6 +3432,10 @@ "glfw": [ 266 ], + "gtk": [ + 65365, + 65434 + ], "windows": null } }, @@ -2949,6 +3450,10 @@ "glfw": [ "DELETE" ], + "gtk": [ + "Delete", + "KP_Delete" + ], "windows": [ "DELETE" ] @@ -2970,6 +3475,10 @@ "glfw": [ 261 ], + "gtk": [ + 65535, + 65439 + ], "windows": [ 46 ] @@ -2986,6 +3495,10 @@ "glfw": [ "END" ], + "gtk": [ + "End", + "KP_End" + ], "windows": [ "END" ] @@ -3007,6 +3520,10 @@ "glfw": [ 269 ], + "gtk": [ + 65367, + 65436 + ], "windows": [ 35 ] @@ -3023,6 +3540,10 @@ "glfw": [ "PAGE_DOWN" ], + "gtk": [ + "Page_Down", + "KP_Page_Down" + ], "windows": null }, "scanCodes": { @@ -3043,6 +3564,10 @@ "glfw": [ 267 ], + "gtk": [ + 65366, + 65435 + ], "windows": null } }, @@ -3057,6 +3582,10 @@ "glfw": [ "RIGHT" ], + "gtk": [ + "Right", + "KP_Right" + ], "windows": [ "RIGHT" ] @@ -3078,6 +3607,10 @@ "glfw": [ 262 ], + "gtk": [ + 65363, + 65432 + ], "windows": [ 39 ] @@ -3094,6 +3627,10 @@ "glfw": [ "LEFT" ], + "gtk": [ + "Left", + "KP_Left" + ], "windows": [ "LEFT" ] @@ -3115,6 +3652,10 @@ "glfw": [ 263 ], + "gtk": [ + 65361, + 65430 + ], "windows": [ 37 ] @@ -3131,6 +3672,10 @@ "glfw": [ "DOWN" ], + "gtk": [ + "Down", + "KP_Down" + ], "windows": [ "DOWN" ] @@ -3152,6 +3697,10 @@ "glfw": [ 264 ], + "gtk": [ + 65364, + 65433 + ], "windows": [ 40 ] @@ -3168,6 +3717,10 @@ "glfw": [ "UP" ], + "gtk": [ + "Up", + "KP_Up" + ], "windows": [ "UP" ] @@ -3189,6 +3742,10 @@ "glfw": [ 265 ], + "gtk": [ + 65362, + 65431 + ], "windows": [ 38 ] @@ -3205,6 +3762,9 @@ "glfw": [ "NUM_LOCK" ], + "gtk": [ + "Num_Lock" + ], "windows": null }, "scanCodes": { @@ -3224,6 +3784,9 @@ "glfw": [ 282 ], + "gtk": [ + 65407 + ], "windows": null } }, @@ -3238,6 +3801,9 @@ "glfw": [ "KP_DIVIDE" ], + "gtk": [ + "KP_Divide" + ], "windows": [ "DIVIDE" ] @@ -3259,6 +3825,9 @@ "glfw": [ 331 ], + "gtk": [ + 65455 + ], "windows": [ 111 ] @@ -3275,6 +3844,9 @@ "glfw": [ "KP_MULTIPLY" ], + "gtk": [ + "KP_Multiply" + ], "windows": [ "MULTIPLY" ] @@ -3296,6 +3868,9 @@ "glfw": [ 332 ], + "gtk": [ + 65450 + ], "windows": [ 106 ] @@ -3312,6 +3887,9 @@ "glfw": [ "NUMPAD_SUBTRACT" ], + "gtk": [ + "KP_Subtract" + ], "windows": [ "SUBTRACT" ] @@ -3331,6 +3909,9 @@ 156 ], "glfw": null, + "gtk": [ + 65453 + ], "windows": [ 109 ] @@ -3347,6 +3928,9 @@ "glfw": [ "KP_ADD" ], + "gtk": [ + "KP_Add" + ], "windows": [ "ADD" ] @@ -3368,6 +3952,9 @@ "glfw": [ 334 ], + "gtk": [ + 65451 + ], "windows": [ 107 ] @@ -3384,6 +3971,9 @@ "glfw": [ "KP_ENTER" ], + "gtk": [ + "KP_Enter" + ], "windows": null }, "scanCodes": { @@ -3403,6 +3993,9 @@ "glfw": [ 335 ], + "gtk": [ + 65421 + ], "windows": null } }, @@ -3417,6 +4010,9 @@ "glfw": [ "KP_1" ], + "gtk": [ + "KP_1" + ], "windows": [ "NUMPAD1" ] @@ -3438,6 +4034,9 @@ "glfw": [ 321 ], + "gtk": [ + 65457 + ], "windows": [ 97 ] @@ -3454,6 +4053,9 @@ "glfw": [ "KP_2" ], + "gtk": [ + "KP_2" + ], "windows": [ "NUMPAD2" ] @@ -3475,6 +4077,9 @@ "glfw": [ 322 ], + "gtk": [ + 65458 + ], "windows": [ 98 ] @@ -3491,6 +4096,9 @@ "glfw": [ "KP_3" ], + "gtk": [ + "KP_3" + ], "windows": [ "NUMPAD3" ] @@ -3512,6 +4120,9 @@ "glfw": [ 323 ], + "gtk": [ + 65459 + ], "windows": [ 99 ] @@ -3528,6 +4139,9 @@ "glfw": [ "KP_4" ], + "gtk": [ + "KP_4" + ], "windows": [ "NUMPAD4" ] @@ -3549,6 +4163,9 @@ "glfw": [ 324 ], + "gtk": [ + 65460 + ], "windows": [ 100 ] @@ -3565,6 +4182,9 @@ "glfw": [ "KP_5" ], + "gtk": [ + "KP_5" + ], "windows": [ "NUMPAD5" ] @@ -3586,6 +4206,9 @@ "glfw": [ 325 ], + "gtk": [ + 65461 + ], "windows": [ 101 ] @@ -3602,6 +4225,9 @@ "glfw": [ "KP_6" ], + "gtk": [ + "KP_6" + ], "windows": [ "NUMPAD6" ] @@ -3623,6 +4249,9 @@ "glfw": [ 326 ], + "gtk": [ + 65462 + ], "windows": [ 102 ] @@ -3639,6 +4268,9 @@ "glfw": [ "KP_7" ], + "gtk": [ + "KP_7" + ], "windows": [ "NUMPAD7" ] @@ -3660,6 +4292,9 @@ "glfw": [ 327 ], + "gtk": [ + 65463 + ], "windows": [ 103 ] @@ -3676,6 +4311,9 @@ "glfw": [ "KP_8" ], + "gtk": [ + "KP_8" + ], "windows": [ "NUMPAD8" ] @@ -3697,6 +4335,9 @@ "glfw": [ 328 ], + "gtk": [ + 65464 + ], "windows": [ 104 ] @@ -3713,6 +4354,9 @@ "glfw": [ "KP_9" ], + "gtk": [ + "KP_9" + ], "windows": [ "NUMPAD9" ] @@ -3734,6 +4378,9 @@ "glfw": [ 329 ], + "gtk": [ + 65465 + ], "windows": [ 105 ] @@ -3750,6 +4397,9 @@ "glfw": [ "KP_0" ], + "gtk": [ + "KP_0" + ], "windows": [ "NUMPAD0" ] @@ -3771,6 +4421,9 @@ "glfw": [ 320 ], + "gtk": [ + 65456 + ], "windows": [ 96 ] @@ -3787,6 +4440,9 @@ "glfw": [ "KP_DECIMAL" ], + "gtk": [ + "KP_Decimal" + ], "windows": [ "DECIMAL" ] @@ -3808,6 +4464,9 @@ "glfw": [ 330 ], + "gtk": [ + 65454 + ], "windows": [ 110 ] @@ -3820,6 +4479,7 @@ "english": "Intl Backslash", "chromium": "intlBackslash", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -3833,6 +4493,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -3847,6 +4508,9 @@ "glfw": [ "MENU" ], + "gtk": [ + "Menu" + ], "windows": null }, "scanCodes": { @@ -3867,6 +4531,9 @@ "glfw": [ 348 ], + "gtk": [ + 65383 + ], "windows": null } }, @@ -3879,6 +4546,9 @@ "english": "Power", "chromium": "power", "glfw": null, + "gtk": [ + "PowerOff" + ], "windows": null }, "scanCodes": { @@ -3897,6 +4567,9 @@ 26 ], "glfw": null, + "gtk": [ + 269025066 + ], "windows": null } }, @@ -3911,6 +4584,9 @@ "glfw": [ "KP_EQUAL" ], + "gtk": [ + "KP_Equal" + ], "windows": [ "OEM_NEC_EQUAL" ] @@ -3932,6 +4608,9 @@ "glfw": [ 336 ], + "gtk": [ + 65469 + ], "windows": [ 146 ] @@ -3948,6 +4627,9 @@ "glfw": [ "F13" ], + "gtk": [ + "F13" + ], "windows": [ "F13" ] @@ -3967,6 +4649,9 @@ "glfw": [ 302 ], + "gtk": [ + 65482 + ], "windows": [ 124 ] @@ -3983,6 +4668,9 @@ "glfw": [ "F14" ], + "gtk": [ + "F14" + ], "windows": [ "F14" ] @@ -4002,6 +4690,9 @@ "glfw": [ 303 ], + "gtk": [ + 65483 + ], "windows": [ 125 ] @@ -4018,6 +4709,9 @@ "glfw": [ "F15" ], + "gtk": [ + "F15" + ], "windows": [ "F15" ] @@ -4037,6 +4731,9 @@ "glfw": [ 304 ], + "gtk": [ + 65484 + ], "windows": [ 126 ] @@ -4053,6 +4750,9 @@ "glfw": [ "F16" ], + "gtk": [ + "F16" + ], "windows": [ "F16" ] @@ -4072,6 +4772,9 @@ "glfw": [ 305 ], + "gtk": [ + 65485 + ], "windows": [ 127 ] @@ -4088,6 +4791,9 @@ "glfw": [ "F17" ], + "gtk": [ + "F17" + ], "windows": [ "F17" ] @@ -4107,6 +4813,9 @@ "glfw": [ 306 ], + "gtk": [ + 65486 + ], "windows": [ 128 ] @@ -4123,6 +4832,9 @@ "glfw": [ "F18" ], + "gtk": [ + "F18" + ], "windows": [ "F18" ] @@ -4142,6 +4854,9 @@ "glfw": [ 307 ], + "gtk": [ + 65487 + ], "windows": [ 129 ] @@ -4158,6 +4873,9 @@ "glfw": [ "F19" ], + "gtk": [ + "F19" + ], "windows": [ "F19" ] @@ -4177,6 +4895,9 @@ "glfw": [ 308 ], + "gtk": [ + 65488 + ], "windows": [ 130 ] @@ -4193,6 +4914,9 @@ "glfw": [ "F20" ], + "gtk": [ + "F20" + ], "windows": [ "F20" ] @@ -4212,6 +4936,9 @@ "glfw": [ 309 ], + "gtk": [ + 65489 + ], "windows": [ 131 ] @@ -4228,6 +4955,9 @@ "glfw": [ "F21" ], + "gtk": [ + "F21" + ], "windows": [ "F21" ] @@ -4247,6 +4977,9 @@ "glfw": [ 310 ], + "gtk": [ + 65490 + ], "windows": [ 132 ] @@ -4263,6 +4996,9 @@ "glfw": [ "F22" ], + "gtk": [ + "F22" + ], "windows": [ "F22" ] @@ -4282,6 +5018,9 @@ "glfw": [ 311 ], + "gtk": [ + 65491 + ], "windows": [ 133 ] @@ -4298,6 +5037,9 @@ "glfw": [ "F23" ], + "gtk": [ + "F23" + ], "windows": [ "F23" ] @@ -4317,6 +5059,9 @@ "glfw": [ 312 ], + "gtk": [ + 65492 + ], "windows": [ 134 ] @@ -4331,6 +5076,9 @@ "english": "F24", "chromium": "f24", "glfw": null, + "gtk": [ + "F24" + ], "windows": [ "F24" ] @@ -4348,6 +5096,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65493 + ], "windows": [ 135 ] @@ -4362,6 +5113,9 @@ "english": "Open", "chromium": "open", "glfw": null, + "gtk": [ + "Open" + ], "windows": null }, "scanCodes": { @@ -4377,6 +5131,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025131 + ], "windows": null } }, @@ -4389,6 +5146,9 @@ "english": "Help", "chromium": "help", "glfw": null, + "gtk": [ + "Help" + ], "windows": [ "HELP" ] @@ -4408,6 +5168,9 @@ 259 ], "glfw": null, + "gtk": [ + 65386 + ], "windows": [ 47 ] @@ -4422,6 +5185,9 @@ "english": "Select", "chromium": "select", "glfw": null, + "gtk": [ + "Select" + ], "windows": [ "SELECT" ] @@ -4441,6 +5207,9 @@ 23 ], "glfw": null, + "gtk": [ + 65376 + ], "windows": [ 41 ] @@ -4455,6 +5224,7 @@ "english": "Again", "chromium": "again", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4470,6 +5240,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4482,6 +5253,9 @@ "english": "Undo", "chromium": "undo", "glfw": null, + "gtk": [ + "Undo" + ], "windows": null }, "scanCodes": { @@ -4497,6 +5271,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65381 + ], "windows": null } }, @@ -4509,6 +5286,7 @@ "english": "Cut", "chromium": "cut", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4526,6 +5304,7 @@ 277 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -4538,6 +5317,10 @@ "english": "Copy", "chromium": "copy", "glfw": null, + "gtk": [ + "Copy", + "3270_Copy" + ], "windows": null }, "scanCodes": { @@ -4555,6 +5338,10 @@ 278 ], "glfw": null, + "gtk": [ + 269025111, + 64789 + ], "windows": null } }, @@ -4567,6 +5354,9 @@ "english": "Paste", "chromium": "paste", "glfw": null, + "gtk": [ + "Paste" + ], "windows": null }, "scanCodes": { @@ -4584,6 +5374,9 @@ 279 ], "glfw": null, + "gtk": [ + 269025133 + ], "windows": null } }, @@ -4596,6 +5389,9 @@ "english": "Find", "chromium": "find", "glfw": null, + "gtk": [ + "Find" + ], "windows": null }, "scanCodes": { @@ -4611,6 +5407,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65384 + ], "windows": null } }, @@ -4623,6 +5422,9 @@ "english": "Audio Volume Mute", "chromium": "volumeMute", "glfw": null, + "gtk": [ + "AudioMute" + ], "windows": null }, "scanCodes": { @@ -4640,6 +5442,9 @@ 164 ], "glfw": null, + "gtk": [ + 269025042 + ], "windows": null } }, @@ -4652,6 +5457,9 @@ "english": "Audio Volume Up", "chromium": "volumeUp", "glfw": null, + "gtk": [ + "AudioRaiseVolume" + ], "windows": null }, "scanCodes": { @@ -4669,6 +5477,9 @@ 24 ], "glfw": null, + "gtk": [ + 269025043 + ], "windows": null } }, @@ -4681,6 +5492,9 @@ "english": "Audio Volume Down", "chromium": "volumeDown", "glfw": null, + "gtk": [ + "AudioLowerVolume" + ], "windows": null }, "scanCodes": { @@ -4698,6 +5512,9 @@ 25 ], "glfw": null, + "gtk": [ + 269025041 + ], "windows": null } }, @@ -4710,6 +5527,7 @@ "english": "Numpad Comma", "chromium": "numpadComma", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4728,6 +5546,7 @@ 159 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -4738,6 +5557,7 @@ "english": "Intl Ro", "chromium": "intlRo", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4751,6 +5571,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4761,6 +5582,9 @@ "english": "Kana Mode", "chromium": "kanaMode", "glfw": null, + "gtk": [ + "kana_switch" + ], "windows": null }, "scanCodes": { @@ -4774,6 +5598,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65406 + ], "windows": null } }, @@ -4784,6 +5611,9 @@ "english": "Intl Yen", "chromium": "intlYen", "glfw": null, + "gtk": [ + "yen" + ], "windows": null }, "scanCodes": { @@ -4797,6 +5627,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 165 + ], "windows": null } }, @@ -4809,6 +5642,7 @@ "english": "Convert", "chromium": "convert", "glfw": null, + "gtk": null, "windows": [ "CONVERT" ] @@ -4828,6 +5662,7 @@ 214 ], "glfw": null, + "gtk": null, "windows": [ 28 ] @@ -4842,6 +5677,7 @@ "english": "Non Convert", "chromium": "nonConvert", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4859,6 +5695,7 @@ 213 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -4869,6 +5706,7 @@ "english": "Lang 1", "chromium": "lang1", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4882,6 +5720,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4892,6 +5731,7 @@ "english": "Lang 2", "chromium": "lang2", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4905,6 +5745,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4917,6 +5758,7 @@ "english": "Lang 3", "chromium": "lang3", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4932,6 +5774,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4944,6 +5787,7 @@ "english": "Lang 4", "chromium": "lang4", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4959,6 +5803,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4969,6 +5814,7 @@ "english": "Lang 5", "chromium": "lang5", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -4982,6 +5828,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -4992,6 +5839,7 @@ "english": "Abort", "chromium": "abort", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5005,6 +5853,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5017,6 +5866,7 @@ "english": "Props", "chromium": "props", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5032,6 +5882,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5044,6 +5895,7 @@ "english": "Numpad Paren Left", "chromium": "numpadParenLeft", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5061,6 +5913,7 @@ 162 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5073,6 +5926,7 @@ "english": "Numpad Paren Right", "chromium": "numpadParenRight", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5090,6 +5944,7 @@ 163 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5100,6 +5955,7 @@ "english": "Numpad Backspace", "chromium": "numpadBackspace", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5113,6 +5969,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5123,6 +5980,7 @@ "english": "Numpad Memory Store", "chromium": "numpadMemoryStore", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5136,6 +5994,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5146,6 +6005,7 @@ "english": "Numpad Memory Recall", "chromium": "numpadMemoryRecall", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5159,6 +6019,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5169,6 +6030,7 @@ "english": "Numpad Memory Clear", "chromium": "numpadMemoryClear", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5182,6 +6044,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5192,6 +6055,7 @@ "english": "Numpad Memory Add", "chromium": "numpadMemoryAdd", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5205,6 +6069,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5215,6 +6080,7 @@ "english": "Numpad Memory Subtract", "chromium": "numpadMemorySubtract", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5228,6 +6094,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5238,6 +6105,7 @@ "english": "Numpad Sign Change", "chromium": "numpadSignChange", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5251,6 +6119,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5261,6 +6130,7 @@ "english": "Numpad Clear", "chromium": "numpadClear", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5274,6 +6144,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5284,6 +6155,7 @@ "english": "Numpad Clear Entry", "chromium": "numpadClearEntry", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5297,6 +6169,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5311,6 +6184,9 @@ "glfw": [ "LEFT_CONTROL" ], + "gtk": [ + "Control_L" + ], "windows": [ "LCONTROL" ] @@ -5332,6 +6208,9 @@ "glfw": [ 341 ], + "gtk": [ + 65507 + ], "windows": [ 162 ] @@ -5348,6 +6227,9 @@ "glfw": [ "LEFT_SHIFT" ], + "gtk": [ + "Shift_L" + ], "windows": [ "LSHIFT" ] @@ -5369,6 +6251,9 @@ "glfw": [ 340 ], + "gtk": [ + 65505 + ], "windows": [ 160 ] @@ -5385,6 +6270,9 @@ "glfw": [ "LEFT_ALT" ], + "gtk": [ + "Alt_L" + ], "windows": [ "LMENU" ] @@ -5406,6 +6294,9 @@ "glfw": [ 342 ], + "gtk": [ + 65513 + ], "windows": [ 164 ] @@ -5422,6 +6313,9 @@ "glfw": [ "LEFT_SUPER" ], + "gtk": [ + "Meta_L" + ], "windows": [ "LWIN" ] @@ -5443,6 +6337,9 @@ "glfw": [ 343 ], + "gtk": [ + 65511 + ], "windows": [ 91 ] @@ -5459,6 +6356,9 @@ "glfw": [ "RIGHT_CONTROL" ], + "gtk": [ + "Control_R" + ], "windows": [ "RCONTROL" ] @@ -5480,6 +6380,9 @@ "glfw": [ 345 ], + "gtk": [ + 65508 + ], "windows": [ 163 ] @@ -5496,6 +6399,9 @@ "glfw": [ "RIGHT_SHIFT" ], + "gtk": [ + "Shift_R" + ], "windows": [ "RSHIFT" ] @@ -5517,6 +6423,9 @@ "glfw": [ 344 ], + "gtk": [ + 65506 + ], "windows": [ 161 ] @@ -5533,6 +6442,9 @@ "glfw": [ "RIGHT_ALT" ], + "gtk": [ + "Alt_R" + ], "windows": [ "RMENU" ] @@ -5554,6 +6466,9 @@ "glfw": [ 346 ], + "gtk": [ + 65514 + ], "windows": [ 165 ] @@ -5570,6 +6485,9 @@ "glfw": [ "RIGHT_SUPER" ], + "gtk": [ + "Meta_R" + ], "windows": [ "RWIN" ] @@ -5591,6 +6509,9 @@ "glfw": [ 347 ], + "gtk": [ + 65512 + ], "windows": [ 92 ] @@ -5605,6 +6526,7 @@ "english": "Info", "chromium": "info", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5622,6 +6544,7 @@ 165 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5634,6 +6557,7 @@ "english": "Closed Caption Toggle", "chromium": "closedCaptionToggle", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5649,6 +6573,7 @@ 175 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5661,6 +6586,9 @@ "english": "Brightness Up", "chromium": "brightnessUp", "glfw": null, + "gtk": [ + "MonBrightnessUp" + ], "windows": null }, "scanCodes": { @@ -5678,6 +6606,9 @@ 221 ], "glfw": null, + "gtk": [ + 269025026 + ], "windows": null } }, @@ -5690,6 +6621,9 @@ "english": "Brightness Down", "chromium": "brightnessDown", "glfw": null, + "gtk": [ + "MonBrightnessDown" + ], "windows": null }, "scanCodes": { @@ -5707,6 +6641,9 @@ 220 ], "glfw": null, + "gtk": [ + 269025027 + ], "windows": null } }, @@ -5717,6 +6654,7 @@ "english": "Brightness Toggle", "chromium": "brightnessToggle", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5730,6 +6668,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5740,6 +6679,7 @@ "english": "Brightness Minimum", "chromium": "brightnessMinimum", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5753,6 +6693,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5763,6 +6704,7 @@ "english": "Brightness Maximum", "chromium": "brightnessMaximum", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5776,6 +6718,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5786,6 +6729,7 @@ "english": "Brightness Auto", "chromium": "brightnessAuto", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5799,6 +6743,65 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, + "windows": null + } + }, + "kbdIllumUp": { + "names": { + "domkey": null, + "android": null, + "english": "Kbd Illum Up", + "chromium": "kbdIllumUp", + "glfw": null, + "gtk": [ + "KbdBrightnessUp" + ], + "windows": null + }, + "scanCodes": { + "android": null, + "usb": 786553, + "linux": 230, + "xkb": 238, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": null, + "glfw": null, + "gtk": [ + 269025029 + ], + "windows": null + } + }, + "kbdIllumDown": { + "names": { + "domkey": null, + "android": null, + "english": "Kbd Illum Down", + "chromium": "kbdIllumDown", + "glfw": null, + "gtk": [ + "KbdBrightnessDown" + ], + "windows": null + }, + "scanCodes": { + "android": null, + "usb": 786554, + "linux": 229, + "xkb": 237, + "windows": null, + "macos": null + }, + "keyCodes": { + "android": null, + "glfw": null, + "gtk": [ + 269025030 + ], "windows": null } }, @@ -5811,6 +6814,7 @@ "english": "Media Last", "chromium": "mediaLast", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5826,6 +6830,7 @@ 229 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5836,6 +6841,9 @@ "english": "Launch Phone", "chromium": "launchPhone", "glfw": null, + "gtk": [ + "Phone" + ], "windows": null }, "scanCodes": { @@ -5849,6 +6857,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025134 + ], "windows": null } }, @@ -5859,6 +6870,7 @@ "english": "Program Guide", "chromium": "programGuide", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5872,6 +6884,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5884,6 +6897,7 @@ "english": "Exit", "chromium": "exit", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5899,6 +6913,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -5911,6 +6926,7 @@ "english": "Channel Up", "chromium": "channelUp", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5928,6 +6944,7 @@ 166 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5940,6 +6957,7 @@ "english": "Channel Down", "chromium": "channelDown", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -5957,6 +6975,7 @@ 167 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -5969,6 +6988,10 @@ "english": "Media Play", "chromium": "mediaPlay", "glfw": null, + "gtk": [ + "AudioPlay", + "3270_Play" + ], "windows": null }, "scanCodes": { @@ -5987,6 +7010,10 @@ 126 ], "glfw": null, + "gtk": [ + 269025044, + 64790 + ], "windows": null } }, @@ -5999,6 +7026,9 @@ "english": "Media Pause", "chromium": "mediaPause", "glfw": null, + "gtk": [ + "AudioPause" + ], "windows": null }, "scanCodes": { @@ -6016,6 +7046,9 @@ 127 ], "glfw": null, + "gtk": [ + 269025073 + ], "windows": null } }, @@ -6028,6 +7061,9 @@ "english": "Media Record", "chromium": "mediaRecord", "glfw": null, + "gtk": [ + "AudioRecord" + ], "windows": null }, "scanCodes": { @@ -6045,6 +7081,9 @@ 130 ], "glfw": null, + "gtk": [ + 269025052 + ], "windows": null } }, @@ -6057,6 +7096,9 @@ "english": "Media Fast Forward", "chromium": "mediaFastForward", "glfw": null, + "gtk": [ + "AudioForward" + ], "windows": null }, "scanCodes": { @@ -6074,6 +7116,9 @@ 90 ], "glfw": null, + "gtk": [ + 269025175 + ], "windows": null } }, @@ -6086,6 +7131,9 @@ "english": "Media Rewind", "chromium": "mediaRewind", "glfw": null, + "gtk": [ + "AudioRewind" + ], "windows": null }, "scanCodes": { @@ -6103,6 +7151,9 @@ 89 ], "glfw": null, + "gtk": [ + 269025086 + ], "windows": null } }, @@ -6115,6 +7166,9 @@ "english": "Media Track Next", "chromium": "mediaTrackNext", "glfw": null, + "gtk": [ + "AudioNext" + ], "windows": null }, "scanCodes": { @@ -6132,6 +7186,9 @@ 87 ], "glfw": null, + "gtk": [ + 269025047 + ], "windows": null } }, @@ -6144,6 +7201,9 @@ "english": "Media Track Previous", "chromium": "mediaTrackPrevious", "glfw": null, + "gtk": [ + "AudioPrev" + ], "windows": null }, "scanCodes": { @@ -6161,6 +7221,9 @@ 88 ], "glfw": null, + "gtk": [ + 269025046 + ], "windows": null } }, @@ -6173,6 +7236,9 @@ "english": "Media Stop", "chromium": "mediaStop", "glfw": null, + "gtk": [ + "AudioStop" + ], "windows": [ "MEDIA_STOP" ] @@ -6193,6 +7259,9 @@ 86 ], "glfw": null, + "gtk": [ + 269025045 + ], "windows": [ 178 ] @@ -6207,6 +7276,9 @@ "english": "Eject", "chromium": "eject", "glfw": null, + "gtk": [ + "Eject" + ], "windows": null }, "scanCodes": { @@ -6225,6 +7297,9 @@ 129 ], "glfw": null, + "gtk": [ + 269025068 + ], "windows": null } }, @@ -6237,6 +7312,7 @@ "english": "Media Play Pause", "chromium": "mediaPlayPause", "glfw": null, + "gtk": null, "windows": [ "MEDIA_PLAY_PAUSE" ] @@ -6256,6 +7332,7 @@ 85 ], "glfw": null, + "gtk": null, "windows": [ 179 ] @@ -6268,6 +7345,7 @@ "english": "Speech Input Toggle", "chromium": "speechInputToggle", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6281,6 +7359,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6293,6 +7372,7 @@ "english": "Bass Boost", "chromium": "bassBoost", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6308,6 +7388,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6318,6 +7399,7 @@ "english": "Media Select", "chromium": "mediaSelect", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6331,6 +7413,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6341,6 +7424,7 @@ "english": "Launch Word Processor", "chromium": "launchWordProcessor", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6354,6 +7438,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6364,6 +7449,7 @@ "english": "Launch Spreadsheet", "chromium": "launchSpreadsheet", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6377,6 +7463,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6389,6 +7476,9 @@ "english": "Launch Mail", "chromium": "launchMail", "glfw": null, + "gtk": [ + "Mail" + ], "windows": [ "LAUNCH_MAIL" ] @@ -6409,6 +7499,9 @@ 65 ], "glfw": null, + "gtk": [ + 269025049 + ], "windows": [ 180 ] @@ -6423,6 +7516,7 @@ "english": "Launch Contacts", "chromium": "launchContacts", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6440,6 +7534,7 @@ 207 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -6452,6 +7547,9 @@ "english": "Launch Calendar", "chromium": "launchCalendar", "glfw": null, + "gtk": [ + "Calendar" + ], "windows": null }, "scanCodes": { @@ -6469,6 +7567,9 @@ 208 ], "glfw": null, + "gtk": [ + 269025056 + ], "windows": null } }, @@ -6479,6 +7580,7 @@ "english": "Launch App2", "chromium": "launchApp2", "glfw": null, + "gtk": null, "windows": [ "LAUNCH_APP2" ] @@ -6494,6 +7596,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": [ 183 ] @@ -6506,6 +7609,7 @@ "english": "Launch App1", "chromium": "launchApp1", "glfw": null, + "gtk": null, "windows": [ "LAUNCH_APP1" ] @@ -6521,6 +7625,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": [ 182 ] @@ -6533,6 +7638,9 @@ "english": "Launch Internet Browser", "chromium": "launchInternetBrowser", "glfw": null, + "gtk": [ + "WWW" + ], "windows": null }, "scanCodes": { @@ -6546,6 +7654,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025070 + ], "windows": null } }, @@ -6556,6 +7667,9 @@ "english": "Log Off", "chromium": "logOff", "glfw": null, + "gtk": [ + "LogOff" + ], "windows": null }, "scanCodes": { @@ -6569,6 +7683,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025121 + ], "windows": null } }, @@ -6579,6 +7696,7 @@ "english": "Lock Screen", "chromium": "lockScreen", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6592,6 +7710,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6602,6 +7721,7 @@ "english": "Launch Control Panel", "chromium": "launchControlPanel", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6615,6 +7735,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6625,6 +7746,7 @@ "english": "Select Task", "chromium": "selectTask", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6638,6 +7760,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6648,6 +7771,9 @@ "english": "Launch Documents", "chromium": "launchDocuments", "glfw": null, + "gtk": [ + "Document" + ], "windows": null }, "scanCodes": { @@ -6661,6 +7787,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6671,6 +7798,9 @@ "english": "Spell Check", "chromium": "spellCheck", "glfw": null, + "gtk": [ + "Spell" + ], "windows": null }, "scanCodes": { @@ -6684,6 +7814,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025148 + ], "windows": null } }, @@ -6694,6 +7827,7 @@ "english": "Launch Keyboard Layout", "chromium": "launchKeyboardLayout", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6707,6 +7841,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -6717,6 +7852,9 @@ "english": "Launch Screen Saver", "chromium": "launchScreenSaver", "glfw": null, + "gtk": [ + "ScreenSaver" + ], "windows": null }, "scanCodes": { @@ -6730,6 +7868,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025069 + ], "windows": null } }, @@ -6742,6 +7883,7 @@ "english": "Launch Assistant", "chromium": "launchAssistant", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -6757,6 +7899,7 @@ 219 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -6767,6 +7910,9 @@ "english": "Launch Audio Browser", "chromium": "launchAudioBrowser", "glfw": null, + "gtk": [ + "Music" + ], "windows": null }, "scanCodes": { @@ -6780,6 +7926,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025170 + ], "windows": null } }, @@ -6792,6 +7941,9 @@ "english": "New Key", "chromium": "new", "glfw": null, + "gtk": [ + "New" + ], "windows": null }, "scanCodes": { @@ -6807,6 +7959,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025128 + ], "windows": null } }, @@ -6820,6 +7975,9 @@ "english": "Close", "chromium": "close", "glfw": null, + "gtk": [ + "Close" + ], "windows": null }, "scanCodes": { @@ -6838,6 +7996,9 @@ 128 ], "glfw": null, + "gtk": [ + 269025110 + ], "windows": null } }, @@ -6848,6 +8009,9 @@ "english": "Save", "chromium": "save", "glfw": null, + "gtk": [ + "Save" + ], "windows": null }, "scanCodes": { @@ -6861,6 +8025,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025143 + ], "windows": null } }, @@ -6873,6 +8040,9 @@ "english": "Print", "chromium": "print", "glfw": null, + "gtk": [ + "Print" + ], "windows": [ "PRINT" ] @@ -6890,6 +8060,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65377 + ], "windows": [ 42 ] @@ -6904,6 +8077,9 @@ "english": "Browser Search", "chromium": "browserSearch", "glfw": null, + "gtk": [ + "Search" + ], "windows": [ "BROWSER_SEARCH" ] @@ -6923,6 +8099,9 @@ 84 ], "glfw": null, + "gtk": [ + 269025051 + ], "windows": [ 170 ] @@ -6935,6 +8114,9 @@ "english": "Browser Home", "chromium": "browserHome", "glfw": null, + "gtk": [ + "HomePage" + ], "windows": [ "BROWSER_HOME" ] @@ -6950,6 +8132,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025048 + ], "windows": [ 172 ] @@ -6962,6 +8147,9 @@ "english": "Browser Back", "chromium": "browserBack", "glfw": null, + "gtk": [ + "Back" + ], "windows": [ "BROWSER_BACK" ] @@ -6977,6 +8165,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025062 + ], "windows": [ 166 ] @@ -6991,6 +8182,9 @@ "english": "Browser Forward", "chromium": "browserForward", "glfw": null, + "gtk": [ + "Forward" + ], "windows": [ "BROWSER_FORWARD" ] @@ -7010,6 +8204,9 @@ 125 ], "glfw": null, + "gtk": [ + 269025063 + ], "windows": [ 167 ] @@ -7022,6 +8219,9 @@ "english": "Browser Stop", "chromium": "browserStop", "glfw": null, + "gtk": [ + "Stop" + ], "windows": [ "BROWSER_STOP" ] @@ -7037,6 +8237,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025064 + ], "windows": [ 169 ] @@ -7049,6 +8252,9 @@ "english": "Browser Refresh", "chromium": "browserRefresh", "glfw": null, + "gtk": [ + "Refresh" + ], "windows": [ "BROWSER_REFRESH" ] @@ -7064,6 +8270,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025065 + ], "windows": [ 168 ] @@ -7078,6 +8287,9 @@ "english": "Browser Favorites", "chromium": "browserFavorites", "glfw": null, + "gtk": [ + "Favorites" + ], "windows": [ "BROWSER_FAVORITES" ] @@ -7097,6 +8309,9 @@ 174 ], "glfw": null, + "gtk": [ + 269025072 + ], "windows": [ 171 ] @@ -7111,6 +8326,9 @@ "english": "Zoom In", "chromium": "zoomIn", "glfw": null, + "gtk": [ + "ZoomIn" + ], "windows": null }, "scanCodes": { @@ -7126,6 +8344,9 @@ 168 ], "glfw": null, + "gtk": [ + 269025163 + ], "windows": null } }, @@ -7138,6 +8359,9 @@ "english": "Zoom Out", "chromium": "zoomOut", "glfw": null, + "gtk": [ + "ZoomOut" + ], "windows": null }, "scanCodes": { @@ -7153,6 +8377,9 @@ 169 ], "glfw": null, + "gtk": [ + 269025164 + ], "windows": null } }, @@ -7165,6 +8392,7 @@ "english": "Zoom Toggle", "chromium": "zoomToggle", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7180,6 +8408,7 @@ 255 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7192,6 +8421,9 @@ "english": "Redo", "chromium": "redo", "glfw": null, + "gtk": [ + "Redo" + ], "windows": null }, "scanCodes": { @@ -7207,6 +8439,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 65382 + ], "windows": null } }, @@ -7217,6 +8452,9 @@ "english": "Mail Reply", "chromium": "mailReply", "glfw": null, + "gtk": [ + "Reply" + ], "windows": null }, "scanCodes": { @@ -7230,6 +8468,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025138 + ], "windows": null } }, @@ -7240,6 +8481,9 @@ "english": "Mail Forward", "chromium": "mailForward", "glfw": null, + "gtk": [ + "MailForward" + ], "windows": null }, "scanCodes": { @@ -7253,6 +8497,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025168 + ], "windows": null } }, @@ -7263,6 +8510,9 @@ "english": "Mail Send", "chromium": "mailSend", "glfw": null, + "gtk": [ + "Send" + ], "windows": null }, "scanCodes": { @@ -7276,6 +8526,9 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": [ + 269025147 + ], "windows": null } }, @@ -7286,6 +8539,7 @@ "english": "Keyboard Layout Select", "chromium": "keyboardLayoutSelect", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7299,6 +8553,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -7309,6 +8564,7 @@ "english": "Show All Windows", "chromium": "showAllWindows", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7322,6 +8578,7 @@ "keyCodes": { "android": null, "glfw": null, + "gtk": null, "windows": null } }, @@ -7334,6 +8591,7 @@ "english": "Game Button 1", "chromium": "button1", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7352,6 +8610,7 @@ 188 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7364,6 +8623,7 @@ "english": "Game Button 2", "chromium": "button2", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7382,6 +8642,7 @@ 189 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7394,6 +8655,7 @@ "english": "Game Button 3", "chromium": "button3", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7412,6 +8674,7 @@ 190 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7424,6 +8687,7 @@ "english": "Game Button 4", "chromium": "button4", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7442,6 +8706,7 @@ 191 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7454,6 +8719,7 @@ "english": "Game Button 5", "chromium": "button5", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7472,6 +8738,7 @@ 192 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7484,6 +8751,7 @@ "english": "Game Button 6", "chromium": "button6", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7502,6 +8770,7 @@ 193 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7514,6 +8783,7 @@ "english": "Game Button 7", "chromium": "button7", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7532,6 +8802,7 @@ 194 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7544,6 +8815,7 @@ "english": "Game Button 8", "chromium": "button8", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7562,6 +8834,7 @@ 195 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7574,6 +8847,7 @@ "english": "Game Button 9", "chromium": "button9", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7592,6 +8866,7 @@ 196 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7604,6 +8879,7 @@ "english": "Game Button 10", "chromium": "button10", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7622,6 +8898,7 @@ 197 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7634,6 +8911,7 @@ "english": "Game Button 11", "chromium": "button11", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7652,6 +8930,7 @@ 198 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7664,6 +8943,7 @@ "english": "Game Button 12", "chromium": "button12", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7682,6 +8962,7 @@ 199 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7694,6 +8975,7 @@ "english": "Game Button 13", "chromium": "button13", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7712,6 +8994,7 @@ 200 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7724,6 +9007,7 @@ "english": "Game Button 14", "chromium": "button14", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7742,6 +9026,7 @@ 201 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7754,6 +9039,7 @@ "english": "Game Button 15", "chromium": "button15", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7772,6 +9058,7 @@ 202 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7784,6 +9071,7 @@ "english": "Game Button 16", "chromium": "button16", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7802,6 +9090,7 @@ 203 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7814,6 +9103,7 @@ "english": "Game Button A", "chromium": "buttonA", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7831,6 +9121,7 @@ 96 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7843,6 +9134,7 @@ "english": "Game Button B", "chromium": "buttonB", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7860,6 +9152,7 @@ 97 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7872,6 +9165,7 @@ "english": "Game Button C", "chromium": "buttonC", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7889,6 +9183,7 @@ 98 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7901,6 +9196,7 @@ "english": "Game Button Left 1", "chromium": "buttonL1", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7918,6 +9214,7 @@ 102 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7930,6 +9227,7 @@ "english": "Game Button Left 2", "chromium": "buttonL2", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7947,6 +9245,7 @@ 104 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7959,6 +9258,7 @@ "english": "Game Button Mode", "chromium": "buttonMode", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -7976,6 +9276,7 @@ 110 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -7988,6 +9289,7 @@ "english": "Game Button Right 1", "chromium": "buttonR1", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8005,6 +9307,7 @@ 103 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8017,6 +9320,7 @@ "english": "Game Button Right 2", "chromium": "buttonR2", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8034,6 +9338,7 @@ 105 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8046,6 +9351,7 @@ "english": "Game Button Select", "chromium": "buttonSelect", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8063,6 +9369,7 @@ 109 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8075,6 +9382,7 @@ "english": "Game Button Start", "chromium": "buttonStart", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8092,6 +9400,7 @@ 108 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8104,6 +9413,7 @@ "english": "Game Button Thumb Left", "chromium": "buttonThumbl", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8121,6 +9431,7 @@ 106 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8133,6 +9444,7 @@ "english": "Game Button Thumb Right", "chromium": "buttonThumbr", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8150,6 +9462,7 @@ 107 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8162,6 +9475,7 @@ "english": "Game Button X", "chromium": "buttonX", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8179,6 +9493,7 @@ 99 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8191,6 +9506,7 @@ "english": "Game Button Y", "chromium": "buttonY", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8208,6 +9524,7 @@ 100 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8220,6 +9537,7 @@ "english": "Game Button Z", "chromium": "buttonZ", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8237,6 +9555,7 @@ 101 ], "glfw": null, + "gtk": null, "windows": null } }, @@ -8249,6 +9568,7 @@ "english": "Fn", "chromium": "fn", "glfw": null, + "gtk": null, "windows": null }, "scanCodes": { @@ -8266,6 +9586,7 @@ 119 ], "glfw": null, + "gtk": null, "windows": null } } diff --git a/dev/tools/gen_keycodes/data/key_name_to_gtk_name.json b/dev/tools/gen_keycodes/data/key_name_to_gtk_name.json new file mode 100644 index 0000000000..13337edc16 --- /dev/null +++ b/dev/tools/gen_keycodes/data/key_name_to_gtk_name.json @@ -0,0 +1,179 @@ +{ + "altLeft": ["Alt_L"], + "altRight": ["Alt_R"], + "arrowDown": ["Down", "KP_Down"], + "arrowLeft": ["Left", "KP_Left"], + "arrowRight": ["Right", "KP_Right"], + "arrowUp": ["Up", "KP_Up"], + "audioVolumeDown": ["AudioLowerVolume"], + "audioVolumeMute": ["AudioMute"], + "audioVolumeUp": ["AudioRaiseVolume"], + "backquote": ["quoteleft"], + "backslash": ["backslash"], + "backspace": ["BackSpace"], + "bracketLeft": ["bracketleft"], + "bracketRight": ["bracketright"], + "brightnessDown": ["MonBrightnessDown"], + "brightnessUp": ["MonBrightnessUp"], + "browserBack": ["Back"], + "browserFavorites": ["Favorites"], + "browserFavourites": ["Favourites"], + "browserForward": ["Forward"], + "browserHome": ["HomePage"], + "browserRefresh": ["Refresh"], + "browserSearch": ["Search"], + "browserStop": ["Stop"], + "capsLock": ["Caps_Lock"], + "close": ["Close"], + "comma": ["comma"], + "contextMenu": ["Menu"], + "controlLeft": ["Control_L"], + "controlRight": ["Control_R"], + "copy": ["Copy", "3270_Copy"], + "delete": ["Delete", "KP_Delete"], + "digit0": ["0"], + "digit1": ["1"], + "digit2": ["2"], + "digit3": ["3"], + "digit4": ["4"], + "digit5": ["5"], + "digit6": ["6"], + "digit7": ["7"], + "digit8": ["8"], + "digit9": ["9"], + "eject": ["Eject"], + "end": ["End", "KP_End"], + "enter": ["Return", "Enter"], + "equal": ["equal"], + "escape": ["Escape"], + "f1": ["F1", "KP_F1"], + "f2": ["F2", "KP_F2"], + "f3": ["F3", "KP_F3"], + "f4": ["F4", "KP_F4"], + "f5": ["F5"], + "f6": ["F6"], + "f7": ["F7"], + "f8": ["F8"], + "f9": ["F9"], + "f10": ["F10"], + "f11": ["F11"], + "f12": ["F12"], + "f13": ["F13"], + "f14": ["F14"], + "f15": ["F15"], + "f16": ["F16"], + "f17": ["F17"], + "f18": ["F18"], + "f19": ["F19"], + "f20": ["F20"], + "f21": ["F21"], + "f22": ["F22"], + "f23": ["F23"], + "f24": ["F24"], + "f25": ["F25"], + "find": ["Find"], + "help": ["Help"], + "home": ["Home", "KP_Home"], + "hyper": ["Hyper_L", "Hyper_R"], + "insert": ["Insert", "KP_Insert"], + "intlYen": ["yen"], + "kanaMode": ["kana_switch"], + "kbdIllumDown": ["KbdBrightnessDown"], + "kbdIllumUp": ["KbdBrightnessUp"], + "keyA": ["A"], + "keyB": ["B"], + "keyC": ["C"], + "keyD": ["D"], + "keyE": ["E"], + "keyF": ["F"], + "keyG": ["G"], + "keyH": ["H"], + "keyI": ["I"], + "keyJ": ["J"], + "keyK": ["K"], + "keyL": ["L"], + "keyM": ["M"], + "keyN": ["N"], + "keyO": ["O"], + "keyP": ["P"], + "keyQ": ["Q"], + "keyR": ["R"], + "keyS": ["S"], + "keyT": ["T"], + "keyU": ["U"], + "keyV": ["V"], + "keyW": ["W"], + "keyX": ["X"], + "keyY": ["Y"], + "keyZ": ["Z"], + "launchAudioBrowser": ["Music"], + "launchCalendar": ["Calendar"], + "launchDocuments": ["Document"], + "launchInternetBrowser": ["WWW"], + "launchMail": ["Mail"], + "launchPhone": ["Phone"], + "launchScreenSaver": ["ScreenSaver"], + "logOff": ["LogOff"], + "mailForward": ["MailForward"], + "mailReply": ["Reply"], + "mailSend": ["Send"], + "mediaFastForward": ["AudioForward"], + "mediaPause": ["AudioPause"], + "mediaPlay": ["AudioPlay", "3270_Play"], + "mediaRecord": ["AudioRecord"], + "mediaRewind": ["AudioRewind"], + "mediaStop": ["AudioStop"], + "mediaTrackNext": ["AudioNext"], + "mediaTrackPrevious": ["AudioPrev"], + "metaLeft": ["Meta_L"], + "metaRight": ["Meta_R"], + "minus": ["minus"], + "newKey": ["New"], + "numLock": ["Num_Lock"], + "numpad0": ["KP_0"], + "numpad1": ["KP_1"], + "numpad2": ["KP_2"], + "numpad3": ["KP_3"], + "numpad4": ["KP_4"], + "numpad5": ["KP_5"], + "numpad6": ["KP_6"], + "numpad7": ["KP_7"], + "numpad8": ["KP_8"], + "numpad9": ["KP_9"], + "numpadAdd": ["KP_Add"], + "numpadDecimal": ["KP_Decimal"], + "numpadDivide": ["KP_Divide"], + "numpadEnter": ["KP_Enter"], + "numpadEqual": ["KP_Equal"], + "numpadMultiply": ["KP_Multiply"], + "numpadSubtract": ["KP_Subtract"], + "open": ["Open"], + "pageDown": ["Page_Down", "KP_Page_Down"], + "pageUp": ["Page_Up", "KP_Page_Up"], + "paste": ["Paste"], + "pause": ["Pause"], + "period": ["period"], + "power": ["PowerOff"], + "print": ["Print"], + "printScreen": ["3270_PrintScreen"], + "quote": ["apostrophe"], + "redo": ["Redo"], + "resume": ["Resume"], + "save": ["Save"], + "scrollLock": ["Scroll_Lock"], + "select": ["Select"], + "semicolon": ["semicolon"], + "shiftLeft": ["Shift_L"], + "shiftRight": ["Shift_R"], + "slash": ["slash"], + "sleep": ["Sleep"], + "space": ["space", "KP_Space"], + "spellCheck": ["Spell"], + "superKey": ["Super_L", "Super_R"], + "suspend": ["Suspend"], + "tab": ["Tab", "KP_Tab"], + "undo": ["Undo"], + "wakeUp": ["WakeUp"], + "zoomIn": ["ZoomIn"], + "zoomOut": ["ZoomOut"] +} diff --git a/dev/tools/gen_keycodes/data/keyboard_map_gtk_cc.tmpl b/dev/tools/gen_keycodes/data/keyboard_map_gtk_cc.tmpl new file mode 100644 index 0000000000..9645a22090 --- /dev/null +++ b/dev/tools/gen_keycodes/data/keyboard_map_gtk_cc.tmpl @@ -0,0 +1,24 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +// DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT +// This file is generated by flutter/flutter@dev/tools/gen_keycodes/bin/gen_keycodes.dart and +// should not be edited directly. +// +// Edit the template dev/tools/gen_keycodes/data/keyboard_maps_gtk_cxx.tmpl instead. +// See dev/tools/gen_keycodes/README.md for more information. + +/// Maps GTK-specific key codes to the matching [LogicalKeyboardKey]. +const std::map g_gtk_to_logical_key = { +@@@GTK_KEY_CODE_MAP@@@ +}; + +/// A map of GTK key codes which have printable representations, but appear +/// on the number pad. Used to provide different key objects for keys like +/// KEY_EQUALS and NUMPAD_EQUALS. +const std::map g_gtk_numpad_map = { +@@@GTK_NUMPAD_MAP@@@ +}; diff --git a/dev/tools/gen_keycodes/data/keyboard_maps.tmpl b/dev/tools/gen_keycodes/data/keyboard_maps.tmpl index 30658790dc..498f636fb7 100644 --- a/dev/tools/gen_keycodes/data/keyboard_maps.tmpl +++ b/dev/tools/gen_keycodes/data/keyboard_maps.tmpl @@ -71,6 +71,18 @@ const Map kGlfwNumpadMap = { @@@GLFW_NUMPAD_MAP@@@ }; +/// Maps GTK-specific key codes to the matching [LogicalKeyboardKey]. +const Map kGtkToLogicalKey = { +@@@GTK_KEY_CODE_MAP@@@ +}; + +/// A map of GTK key codes which have printable representations, but appear +/// on the number pad. Used to provide different key objects for keys like +/// KEY_EQUALS and NUMPAD_EQUALS. +const Map kGtkNumpadMap = { +@@@GTK_NUMPAD_MAP@@@ +}; + /// Maps XKB specific key code values representing [PhysicalKeyboardKey]. const Map kLinuxToPhysicalKey = { @@@XKB_SCAN_CODE_MAP@@@ diff --git a/dev/tools/gen_keycodes/lib/dart_code_gen.dart b/dev/tools/gen_keycodes/lib/dart_code_gen.dart index 983fc56dfe..c27ddc79d5 100644 --- a/dev/tools/gen_keycodes/lib/dart_code_gen.dart +++ b/dev/tools/gen_keycodes/lib/dart_code_gen.dart @@ -175,6 +175,32 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK return glfwKeyCodeMap.toString().trimRight(); } + /// This generates the map of GTK number pad key codes to logical keys. + String get gtkNumpadMap { + final StringBuffer gtkNumpadMap = StringBuffer(); + for (final Key entry in numpadKeyData) { + if (entry.gtkKeyCodes != null) { + for (final int code in entry.gtkKeyCodes.cast()) { + gtkNumpadMap.writeln(' $code: LogicalKeyboardKey.${entry.constantName},'); + } + } + } + return gtkNumpadMap.toString().trimRight(); + } + + /// This generates the map of GTK key codes to logical keys. + String get gtkKeyCodeMap { + final StringBuffer gtkKeyCodeMap = StringBuffer(); + for (final Key entry in keyData.data) { + if (entry.gtkKeyCodes != null) { + for (final int code in entry.gtkKeyCodes.cast()) { + gtkKeyCodeMap.writeln(' $code: LogicalKeyboardKey.${entry.constantName},'); + } + } + } + return gtkKeyCodeMap.toString().trimRight(); + } + /// This generates the map of XKB USB HID codes to physical keys. String get xkbScanCodeMap { final StringBuffer xkbScanCodeMap = StringBuffer(); @@ -414,6 +440,8 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK 'MACOS_FUNCTION_KEY_MAP': macOsFunctionKeyMap, 'GLFW_KEY_CODE_MAP': glfwKeyCodeMap, 'GLFW_NUMPAD_MAP': glfwNumpadMap, + 'GTK_KEY_CODE_MAP': gtkKeyCodeMap, + 'GTK_NUMPAD_MAP': gtkNumpadMap, 'XKB_SCAN_CODE_MAP': xkbScanCodeMap, 'WEB_LOGICAL_KEY_MAP': webLogicalKeyMap, 'WEB_PHYSICAL_KEY_MAP': webPhysicalKeyMap, diff --git a/dev/tools/gen_keycodes/lib/key_data.dart b/dev/tools/gen_keycodes/lib/key_data.dart index b41c2c1a8b..76348c3181 100644 --- a/dev/tools/gen_keycodes/lib/key_data.dart +++ b/dev/tools/gen_keycodes/lib/key_data.dart @@ -28,6 +28,8 @@ class KeyData { String androidNameMap, String glfwKeyCodeHeader, String glfwNameMap, + String gtkKeyCodeHeader, + String gtkNameMap, String windowsKeyCodeHeader, String windowsNameMap, ) : assert(chromiumHidCodes != null), @@ -36,11 +38,14 @@ class KeyData { assert(androidNameMap != null), assert(glfwKeyCodeHeader != null), assert(glfwNameMap != null), + assert(gtkKeyCodeHeader != null), + assert(gtkNameMap != null), assert(windowsKeyCodeHeader != null), assert(windowsNameMap != null) { _nameToAndroidScanCodes = _readAndroidScanCodes(androidKeyboardLayout); _nameToAndroidKeyCode = _readAndroidKeyCodes(androidKeyCodeHeader); _nameToGlfwKeyCode = _readGlfwKeyCodes(glfwKeyCodeHeader); + _nameToGtkKeyCode = _readGtkKeyCodes(gtkKeyCodeHeader); _nameToWindowsKeyCode = _readWindowsKeyCodes(windowsKeyCodeHeader); // Cast Android dom map final Map> dynamicAndroidNames = (json.decode(androidNameMap) as Map).cast>(); @@ -52,6 +57,11 @@ class KeyData { _nameToGlfwName = dynamicGlfwNames.map>((String key, List value) { return MapEntry>(key, value.cast()); }); + // Cast GTK dom map + final Map> dynamicGtkNames = (json.decode(gtkNameMap) as Map).cast>(); + _nameToGtkName = dynamicGtkNames.map>((String key, List value) { + return MapEntry>(key, value.cast()); + }); // Cast Windows dom map final Map> dynamicWindowsNames = (json.decode(windowsNameMap) as Map).cast>(); _nameToWindowsName = dynamicWindowsNames.map>((String key, List value) { @@ -97,6 +107,17 @@ class KeyData { } } + // GTK key names + entry.gtkKeyNames = _nameToGtkName[entry.constantName]?.cast(); + if (entry.gtkKeyNames != null && entry.gtkKeyNames.isNotEmpty) { + for (final String gtkKeyName in entry.gtkKeyNames) { + if (_nameToGtkKeyCode[gtkKeyName] != null) { + entry.gtkKeyCodes ??= []; + entry.gtkKeyCodes.add(_nameToGtkKeyCode[gtkKeyName]); + } + } + } + // Windows key names entry.windowsKeyNames = _nameToWindowsName[entry.constantName]?.cast(); if (entry.windowsKeyNames != null && entry.windowsKeyNames.isNotEmpty) { @@ -133,6 +154,13 @@ class KeyData { /// JSON. Map> _nameToGlfwName; + /// The mapping from the Flutter name (e.g. "eject") to the GTK name (e.g. + /// "GDK_KEY_Eject"). + /// + /// Only populated if data is parsed from the source files, not if parsed from + /// JSON. + Map> _nameToGtkName; + /// The mapping from the Android name (e.g. "MEDIA_EJECT") to the integer scan /// code (physical location) of the key. /// @@ -154,6 +182,13 @@ class KeyData { /// JSON. Map _nameToGlfwKeyCode; + /// The mapping from GTK name (e.g. "GTK_KEY_comma") to the integer key code + /// (logical meaning) of the key. + /// + /// Only populated if data is parsed from the source files, not if parsed from + /// JSON. + Map _nameToGtkKeyCode; + /// The mapping from Widows name (e.g. "RETURN") to the integer key code /// (logical meaning) of the key. /// @@ -244,6 +279,20 @@ class KeyData { return result; } + /// Parses entries from GTK's gdkkeysyms.h key code data file. + /// + /// Lines in this file look like this (without the ///): + /// /** Space key. */ + /// #define GDK_KEY_space 0x020 + Map _readGtkKeyCodes(String headerFile) { + final RegExp definedCodes = RegExp(r'#define GDK_KEY_([a-zA-Z0-9_]+)\s*0x([0-9a-f]+),?'); + final Map replaced = {}; + for (final Match match in definedCodes.allMatches(headerFile)) { + replaced[match.group(1)] = int.parse(match.group(2), radix: 16); + } + return replaced; + } + Map _readWindowsKeyCodes(String headerFile) { final RegExp definedCodes = RegExp(r'define VK_([A-Z0-9_]+)\s*([A-Z0-9_x]+),?'); final Map replaced = {}; @@ -332,6 +381,8 @@ class Key { this.androidKeyCodes, this.glfwKeyNames, this.glfwKeyCodes, + this.gtkKeyNames, + this.gtkKeyCodes, }) : assert(usbHidCode != null), assert(chromiumName != null), _constantName = enumName; @@ -354,6 +405,8 @@ class Key { macOsScanCode: map['scanCodes']['macos'] as int, glfwKeyNames: (map['names']['glfw'] as List)?.cast(), glfwKeyCodes: (map['keyCodes']['glfw'] as List)?.cast(), + gtkKeyNames: (map['names']['gtk'] as List)?.cast(), + gtkKeyCodes: (map['keyCodes']['gtk'] as List)?.cast(), ); } @@ -402,6 +455,15 @@ class Key { /// value. List glfwKeyCodes; + /// The list of names that GTK gives to this key (symbol names minus the + /// prefix). + List gtkKeyNames; + + /// The list of GTK key codes matching this key, created by looking up the + /// Linux name in the GTK data, and substituting the GTK key code + /// value. + List gtkKeyCodes; + /// Creates a JSON map from the key data. Map toJson() { return { @@ -411,6 +473,7 @@ class Key { 'english': commentName, 'chromium': chromiumName, 'glfw': glfwKeyNames, + 'gtk': gtkKeyNames, 'windows': windowsKeyNames, }, 'scanCodes': { @@ -424,6 +487,7 @@ class Key { 'keyCodes': >{ 'android': androidKeyCodes, 'glfw': glfwKeyCodes, + 'gtk': gtkKeyCodes, 'windows': windowsKeyCodes, }, }; diff --git a/packages/flutter/lib/src/services/keyboard_maps.dart b/packages/flutter/lib/src/services/keyboard_maps.dart index aceb97a55b..8eaaf17a63 100644 --- a/packages/flutter/lib/src/services/keyboard_maps.dart +++ b/packages/flutter/lib/src/services/keyboard_maps.dart @@ -1312,6 +1312,223 @@ const Map kGlfwNumpadMap = { 336: LogicalKeyboardKey.numpadEqual, }; +/// Maps GTK-specific key codes to the matching [LogicalKeyboardKey]. +const Map kGtkToLogicalKey = { + 65517: LogicalKeyboardKey.hyper, + 65518: LogicalKeyboardKey.hyper, + 65515: LogicalKeyboardKey.superKey, + 65516: LogicalKeyboardKey.superKey, + 269025191: LogicalKeyboardKey.suspend, + 269025071: LogicalKeyboardKey.sleep, + 269025067: LogicalKeyboardKey.wakeUp, + 65: LogicalKeyboardKey.keyA, + 66: LogicalKeyboardKey.keyB, + 67: LogicalKeyboardKey.keyC, + 68: LogicalKeyboardKey.keyD, + 69: LogicalKeyboardKey.keyE, + 70: LogicalKeyboardKey.keyF, + 71: LogicalKeyboardKey.keyG, + 72: LogicalKeyboardKey.keyH, + 73: LogicalKeyboardKey.keyI, + 74: LogicalKeyboardKey.keyJ, + 75: LogicalKeyboardKey.keyK, + 76: LogicalKeyboardKey.keyL, + 77: LogicalKeyboardKey.keyM, + 78: LogicalKeyboardKey.keyN, + 79: LogicalKeyboardKey.keyO, + 80: LogicalKeyboardKey.keyP, + 81: LogicalKeyboardKey.keyQ, + 82: LogicalKeyboardKey.keyR, + 83: LogicalKeyboardKey.keyS, + 84: LogicalKeyboardKey.keyT, + 85: LogicalKeyboardKey.keyU, + 86: LogicalKeyboardKey.keyV, + 87: LogicalKeyboardKey.keyW, + 88: LogicalKeyboardKey.keyX, + 89: LogicalKeyboardKey.keyY, + 90: LogicalKeyboardKey.keyZ, + 49: LogicalKeyboardKey.digit1, + 50: LogicalKeyboardKey.digit2, + 51: LogicalKeyboardKey.digit3, + 52: LogicalKeyboardKey.digit4, + 53: LogicalKeyboardKey.digit5, + 54: LogicalKeyboardKey.digit6, + 55: LogicalKeyboardKey.digit7, + 56: LogicalKeyboardKey.digit8, + 57: LogicalKeyboardKey.digit9, + 48: LogicalKeyboardKey.digit0, + 65293: LogicalKeyboardKey.enter, + 65307: LogicalKeyboardKey.escape, + 65288: LogicalKeyboardKey.backspace, + 65289: LogicalKeyboardKey.tab, + 65417: LogicalKeyboardKey.tab, + 32: LogicalKeyboardKey.space, + 65408: LogicalKeyboardKey.space, + 45: LogicalKeyboardKey.minus, + 61: LogicalKeyboardKey.equal, + 91: LogicalKeyboardKey.bracketLeft, + 93: LogicalKeyboardKey.bracketRight, + 92: LogicalKeyboardKey.backslash, + 59: LogicalKeyboardKey.semicolon, + 39: LogicalKeyboardKey.quote, + 96: LogicalKeyboardKey.backquote, + 44: LogicalKeyboardKey.comma, + 46: LogicalKeyboardKey.period, + 47: LogicalKeyboardKey.slash, + 65509: LogicalKeyboardKey.capsLock, + 65470: LogicalKeyboardKey.f1, + 65425: LogicalKeyboardKey.f1, + 65471: LogicalKeyboardKey.f2, + 65426: LogicalKeyboardKey.f2, + 65472: LogicalKeyboardKey.f3, + 65427: LogicalKeyboardKey.f3, + 65473: LogicalKeyboardKey.f4, + 65428: LogicalKeyboardKey.f4, + 65474: LogicalKeyboardKey.f5, + 65475: LogicalKeyboardKey.f6, + 65476: LogicalKeyboardKey.f7, + 65477: LogicalKeyboardKey.f8, + 65478: LogicalKeyboardKey.f9, + 65479: LogicalKeyboardKey.f10, + 65480: LogicalKeyboardKey.f11, + 65481: LogicalKeyboardKey.f12, + 64797: LogicalKeyboardKey.printScreen, + 65300: LogicalKeyboardKey.scrollLock, + 65299: LogicalKeyboardKey.pause, + 65379: LogicalKeyboardKey.insert, + 65438: LogicalKeyboardKey.insert, + 65360: LogicalKeyboardKey.home, + 65429: LogicalKeyboardKey.home, + 65365: LogicalKeyboardKey.pageUp, + 65434: LogicalKeyboardKey.pageUp, + 65535: LogicalKeyboardKey.delete, + 65439: LogicalKeyboardKey.delete, + 65367: LogicalKeyboardKey.end, + 65436: LogicalKeyboardKey.end, + 65366: LogicalKeyboardKey.pageDown, + 65435: LogicalKeyboardKey.pageDown, + 65363: LogicalKeyboardKey.arrowRight, + 65432: LogicalKeyboardKey.arrowRight, + 65361: LogicalKeyboardKey.arrowLeft, + 65430: LogicalKeyboardKey.arrowLeft, + 65364: LogicalKeyboardKey.arrowDown, + 65433: LogicalKeyboardKey.arrowDown, + 65362: LogicalKeyboardKey.arrowUp, + 65431: LogicalKeyboardKey.arrowUp, + 65407: LogicalKeyboardKey.numLock, + 65455: LogicalKeyboardKey.numpadDivide, + 65450: LogicalKeyboardKey.numpadMultiply, + 65453: LogicalKeyboardKey.numpadSubtract, + 65451: LogicalKeyboardKey.numpadAdd, + 65421: LogicalKeyboardKey.numpadEnter, + 65457: LogicalKeyboardKey.numpad1, + 65458: LogicalKeyboardKey.numpad2, + 65459: LogicalKeyboardKey.numpad3, + 65460: LogicalKeyboardKey.numpad4, + 65461: LogicalKeyboardKey.numpad5, + 65462: LogicalKeyboardKey.numpad6, + 65463: LogicalKeyboardKey.numpad7, + 65464: LogicalKeyboardKey.numpad8, + 65465: LogicalKeyboardKey.numpad9, + 65456: LogicalKeyboardKey.numpad0, + 65454: LogicalKeyboardKey.numpadDecimal, + 65383: LogicalKeyboardKey.contextMenu, + 269025066: LogicalKeyboardKey.power, + 65469: LogicalKeyboardKey.numpadEqual, + 65482: LogicalKeyboardKey.f13, + 65483: LogicalKeyboardKey.f14, + 65484: LogicalKeyboardKey.f15, + 65485: LogicalKeyboardKey.f16, + 65486: LogicalKeyboardKey.f17, + 65487: LogicalKeyboardKey.f18, + 65488: LogicalKeyboardKey.f19, + 65489: LogicalKeyboardKey.f20, + 65490: LogicalKeyboardKey.f21, + 65491: LogicalKeyboardKey.f22, + 65492: LogicalKeyboardKey.f23, + 65493: LogicalKeyboardKey.f24, + 269025131: LogicalKeyboardKey.open, + 65386: LogicalKeyboardKey.help, + 65376: LogicalKeyboardKey.select, + 65381: LogicalKeyboardKey.undo, + 269025111: LogicalKeyboardKey.copy, + 64789: LogicalKeyboardKey.copy, + 269025133: LogicalKeyboardKey.paste, + 65384: LogicalKeyboardKey.find, + 269025042: LogicalKeyboardKey.audioVolumeMute, + 269025043: LogicalKeyboardKey.audioVolumeUp, + 269025041: LogicalKeyboardKey.audioVolumeDown, + 65406: LogicalKeyboardKey.kanaMode, + 165: LogicalKeyboardKey.intlYen, + 65507: LogicalKeyboardKey.controlLeft, + 65505: LogicalKeyboardKey.shiftLeft, + 65513: LogicalKeyboardKey.altLeft, + 65511: LogicalKeyboardKey.metaLeft, + 65508: LogicalKeyboardKey.controlRight, + 65506: LogicalKeyboardKey.shiftRight, + 65514: LogicalKeyboardKey.altRight, + 65512: LogicalKeyboardKey.metaRight, + 269025026: LogicalKeyboardKey.brightnessUp, + 269025027: LogicalKeyboardKey.brightnessDown, + 269025134: LogicalKeyboardKey.launchPhone, + 269025044: LogicalKeyboardKey.mediaPlay, + 64790: LogicalKeyboardKey.mediaPlay, + 269025073: LogicalKeyboardKey.mediaPause, + 269025052: LogicalKeyboardKey.mediaRecord, + 269025175: LogicalKeyboardKey.mediaFastForward, + 269025086: LogicalKeyboardKey.mediaRewind, + 269025047: LogicalKeyboardKey.mediaTrackNext, + 269025046: LogicalKeyboardKey.mediaTrackPrevious, + 269025045: LogicalKeyboardKey.mediaStop, + 269025068: LogicalKeyboardKey.eject, + 269025049: LogicalKeyboardKey.launchMail, + 269025056: LogicalKeyboardKey.launchCalendar, + 269025070: LogicalKeyboardKey.launchInternetBrowser, + 269025121: LogicalKeyboardKey.logOff, + 269025148: LogicalKeyboardKey.spellCheck, + 269025069: LogicalKeyboardKey.launchScreenSaver, + 269025170: LogicalKeyboardKey.launchAudioBrowser, + 269025128: LogicalKeyboardKey.newKey, + 269025110: LogicalKeyboardKey.close, + 269025143: LogicalKeyboardKey.save, + 65377: LogicalKeyboardKey.print, + 269025051: LogicalKeyboardKey.browserSearch, + 269025048: LogicalKeyboardKey.browserHome, + 269025062: LogicalKeyboardKey.browserBack, + 269025063: LogicalKeyboardKey.browserForward, + 269025064: LogicalKeyboardKey.browserStop, + 269025065: LogicalKeyboardKey.browserRefresh, + 269025072: LogicalKeyboardKey.browserFavorites, + 269025163: LogicalKeyboardKey.zoomIn, + 269025164: LogicalKeyboardKey.zoomOut, + 65382: LogicalKeyboardKey.redo, + 269025138: LogicalKeyboardKey.mailReply, + 269025168: LogicalKeyboardKey.mailForward, + 269025147: LogicalKeyboardKey.mailSend, +}; + +/// A map of GTK key codes which have printable representations, but appear +/// on the number pad. Used to provide different key objects for keys like +/// KEY_EQUALS and NUMPAD_EQUALS. +const Map kGtkNumpadMap = { + 65455: LogicalKeyboardKey.numpadDivide, + 65450: LogicalKeyboardKey.numpadMultiply, + 65453: LogicalKeyboardKey.numpadSubtract, + 65451: LogicalKeyboardKey.numpadAdd, + 65457: LogicalKeyboardKey.numpad1, + 65458: LogicalKeyboardKey.numpad2, + 65459: LogicalKeyboardKey.numpad3, + 65460: LogicalKeyboardKey.numpad4, + 65461: LogicalKeyboardKey.numpad5, + 65462: LogicalKeyboardKey.numpad6, + 65463: LogicalKeyboardKey.numpad7, + 65464: LogicalKeyboardKey.numpad8, + 65465: LogicalKeyboardKey.numpad9, + 65456: LogicalKeyboardKey.numpad0, + 65454: LogicalKeyboardKey.numpadDecimal, + 65469: LogicalKeyboardKey.numpadEqual, +}; + /// Maps XKB specific key code values representing [PhysicalKeyboardKey]. const Map kLinuxToPhysicalKey = { 0x00000281: PhysicalKeyboardKey.privacyScreenToggle, diff --git a/packages/flutter/lib/src/services/raw_keyboard_linux.dart b/packages/flutter/lib/src/services/raw_keyboard_linux.dart index 25e9193f17..7b58b76a6a 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_linux.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_linux.dart @@ -19,7 +19,7 @@ import 'raw_keyboard.dart'; /// /// * [RawKeyboard], which uses this interface to expose key data. class RawKeyEventDataLinux extends RawKeyEventData { - /// Creates a key event data structure specific for macOS. + /// Creates a key event data structure specific for Linux. /// /// The [toolkit], [scanCode], [unicodeScalarValues], [keyCode], and [modifiers], /// arguments must not be null. @@ -145,6 +145,8 @@ abstract class KeyHelper { factory KeyHelper(String toolkit) { if (toolkit == 'glfw') { return GLFWKeyHelper(); + } else if (toolkit == 'gtk') { + return GtkKeyHelper(); } else { throw FlutterError('Window toolkit not recognized: $toolkit'); } @@ -314,3 +316,149 @@ class GLFWKeyHelper with KeyHelper { return kGlfwToLogicalKey[keyCode]; } } + +/// Helper class that uses GTK-specific key mappings. +class GtkKeyHelper with KeyHelper { + /// This mask is used to check the [modifiers] field to test whether one of the + /// SHIFT modifier keys is pressed. + /// + /// {@template flutter.services.gtkKeyHelper.modifiers} + /// Use this value if you need to decode the [modifiers] field yourself, but + /// it's much easier to use [isModifierPressed] if you just want to know if a + /// modifier is pressed. This is especially true on GTK, since its modifiers + /// don't include the effects of the current key event. + /// {@endtemplate} + static const int modifierShift = 1 << 0; + + /// This mask is used to check the [modifiers] field to test whether the CAPS + /// LOCK modifier key is on. + /// {@macro flutter.services.gtkKeyHelper.modifiers} + static const int modifierCapsLock = 1 << 1; + + /// This mask is used to check the [modifiers] field to test whether one of the + /// CTRL modifier keys is pressed. + /// {@macro flutter.services.gtkKeyHelper.modifiers} + static const int modifierControl = 1 << 2; + + /// This mask is used to check the [modifiers] field to test whether the first + /// modifier key is pressed (usually mapped to alt). + /// {@macro flutter.services.gtkKeyHelper.modifiers} + static const int modifierMod1 = 1 << 3; + + /// This mask is used to check the [modifiers] field to test whether the second + /// modifier key is pressed (assumed to be mapped to num lock). + /// {@macro flutter.services.gtkKeyHelper.modifiers} + static const int modifierMod2 = 1 << 4; + + /// This mask is used to check the [modifiers] field to test whether one of the + /// Meta(SUPER) modifier keys is pressed. + /// {@macro flutter.services.gtkKeyHelper.modifiers} + static const int modifierMeta = 1 << 28; + + int _mergeModifiers({int modifiers, int keyCode, bool isDown}) { + // GTK Key codes for modifier keys. + const int shiftLeftKeyCode = 0xffe1; + const int shiftRightKeyCode = 0xffe2; + const int controlLeftKeyCode = 0xffe3; + const int controlRightKeyCode = 0xffe4; + const int capsLockKeyCode = 0xffe5; + const int shiftLockKeyCode = 0xffe6; + const int metaLeftKeyCode = 0xffe7; + const int metaRightKeyCode = 0xffe8; + const int altLeftKeyCode = 0xffe9; + const int altRightKeyCode = 0xffea; + const int numLockKeyCode = 0xff7f; + + // On GTK, the "modifiers" bitfield is the state as it is BEFORE this event + // happened, not AFTER, like every other platform. Consequently, if this is + // a key down, then we need to add the correct modifier bits, and if it's a + // key up, we need to remove them. + + int modifierChange = 0; + switch (keyCode) { + case shiftLeftKeyCode: + case shiftRightKeyCode: + modifierChange = modifierShift; + break; + case controlLeftKeyCode: + case controlRightKeyCode: + modifierChange = modifierControl; + break; + case altLeftKeyCode: + case altRightKeyCode: + modifierChange = modifierMod1; + break; + case metaLeftKeyCode: + case metaRightKeyCode: + modifierChange = modifierMeta; + break; + case capsLockKeyCode: + case shiftLockKeyCode: + modifierChange = modifierCapsLock; + break; + case numLockKeyCode: + modifierChange = modifierMod2; + break; + default: + break; + } + + return isDown ? modifiers | modifierChange : modifiers & ~modifierChange; + } + + @override + bool isModifierPressed(ModifierKey key, int modifiers, {KeyboardSide side = KeyboardSide.any, int keyCode, bool isDown}) { + modifiers = _mergeModifiers(modifiers: modifiers, keyCode: keyCode, isDown: isDown); + switch (key) { + case ModifierKey.controlModifier: + return modifiers & modifierControl != 0; + case ModifierKey.shiftModifier: + return modifiers & modifierShift != 0; + case ModifierKey.altModifier: + return modifiers & modifierMod1 != 0; + case ModifierKey.metaModifier: + return modifiers & modifierMeta != 0; + case ModifierKey.capsLockModifier: + return modifiers & modifierCapsLock != 0; + case ModifierKey.numLockModifier: + return modifiers & modifierMod2 != 0; + case ModifierKey.functionModifier: + case ModifierKey.symbolModifier: + case ModifierKey.scrollLockModifier: + // These are not used in GTK keyboards. + return false; + } + return false; + } + + @override + KeyboardSide getModifierSide(ModifierKey key) { + switch (key) { + case ModifierKey.controlModifier: + case ModifierKey.shiftModifier: + case ModifierKey.altModifier: + case ModifierKey.metaModifier: + // Neither GTK or X11 provide a distinction between left and right modifiers, so defaults to KeyboardSide.any. + // https://code.woboq.org/qt5/include/X11/X.h.html#_M/ShiftMask + return KeyboardSide.any; + case ModifierKey.capsLockModifier: + case ModifierKey.numLockModifier: + case ModifierKey.functionModifier: + case ModifierKey.symbolModifier: + case ModifierKey.scrollLockModifier: + return KeyboardSide.all; + } + assert(false, 'Not handling $key type properly.'); + return null; + } + + @override + LogicalKeyboardKey numpadKey(int keyCode) { + return kGtkNumpadMap[keyCode]; + } + + @override + LogicalKeyboardKey logicalKey(int keyCode) { + return kGtkToLogicalKey[keyCode]; + } +} diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 8e0595e5c4..e7e5c09558 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -1101,6 +1101,189 @@ void main() { }); }, skip: isBrowser); + group('RawKeyEventDataLinux-GTK', () { + const Map modifierTests = { + GtkKeyHelper.modifierMod1: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.any), + GtkKeyHelper.modifierShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.any), + GtkKeyHelper.modifierControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.any), + GtkKeyHelper.modifierMeta: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.any), + GtkKeyHelper.modifierMod2: _ModifierCheck(ModifierKey.numLockModifier, KeyboardSide.all), + GtkKeyHelper.modifierCapsLock: _ModifierCheck(ModifierKey.capsLockModifier, KeyboardSide.all), + }; + + // How modifiers are interpreted depends upon the keyCode for GTK. + int keyCodeForModifier(int modifier, {bool isLeft}) { + switch (modifier) { + case GtkKeyHelper.modifierMod1: + return isLeft ? 65513 : 65513; + case GtkKeyHelper.modifierShift: + return isLeft ? 65505 : 65506; + case GtkKeyHelper.modifierControl: + return isLeft ? 65507 : 65508; + case GtkKeyHelper.modifierMeta: + return isLeft ? 65511 : 65512; + case GtkKeyHelper.modifierMod2: + return 65407; + case GtkKeyHelper.modifierCapsLock: + return 65509; + default: + return 65; // keyA + } + } + + test('modifier keys are recognized individually', () { + for (final int modifier in modifierTests.keys) { + for (final bool isDown in [true, false]) { + for (final bool isLeft in [true, false]) { + final RawKeyEvent event = RawKeyEvent.fromMessage({ + 'type': isDown ? 'keydown' : 'keyup', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': keyCodeForModifier(modifier, isLeft: isLeft), + 'scanCode': 0x00000026, + 'unicodeScalarValues': 97, + // GTK modifiers don't include the current key event. + 'modifiers': isDown ? 0 : modifier, + }); + final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux; + for (final ModifierKey key in ModifierKey.values) { + if (modifierTests[modifier].key == key) { + expect( + data.isModifierPressed(key, side: modifierTests[modifier].side), + isDown ? isTrue : isFalse, + reason: "${isLeft ? 'left' : 'right'} $key ${isDown ? 'should' : 'should not'} be pressed with metaState $modifier, when key is ${isDown ? 'down' : 'up'}, but isn't.", + ); + expect(data.getModifierSide(key), equals(modifierTests[modifier].side)); + } else { + expect( + data.isModifierPressed(key, side: modifierTests[modifier].side), + isFalse, + reason: "${isLeft ? 'left' : 'right'} $key should not be pressed with metaState $modifier, wwhen key is ${isDown ? 'down' : 'up'}, but is.", + ); + } + } + } + } + } + }); + test('modifier keys are recognized when combined', () { + for (final int modifier in modifierTests.keys) { + if (modifier == GtkKeyHelper.modifierControl) { + // No need to combine CTRL key with itself. + continue; + } + final RawKeyEvent event = RawKeyEvent.fromMessage({ + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65, + 'scanCode': 0x00000026, + 'unicodeScalarValues': 97, + 'modifiers': modifier | GtkKeyHelper.modifierControl, + }); + final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux; + for (final ModifierKey key in ModifierKey.values) { + if (modifierTests[modifier].key == key || key == ModifierKey.controlModifier) { + expect( + data.isModifierPressed(key, side: modifierTests[modifier].side), + isTrue, + reason: '$key should be pressed with metaState $modifier ' + "and additional key ${GtkKeyHelper.modifierControl}, but isn't.", + ); + if (key != ModifierKey.controlModifier) { + expect(data.getModifierSide(key), equals(modifierTests[modifier].side)); + } else { + expect(data.getModifierSide(key), equals(KeyboardSide.any)); + } + } else { + expect( + data.isModifierPressed(key, side: modifierTests[modifier].side), + isFalse, + reason: '$key should not be pressed with metaState $modifier ' + 'and additional key ${GtkKeyHelper.modifierControl}.', + ); + } + } + } + }); + test('Printable keyboard keys are correctly translated', () { + final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65, + 'scanCode': 0x00000026, + 'unicodeScalarValues': 113, + 'modifiers': 0x0, + }); + final RawKeyEventDataLinux data = keyAEvent.data as RawKeyEventDataLinux; + expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA)); + expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ)); + expect(data.keyLabel, equals('q')); + }); + test('Code points with two Unicode scalar values are allowed', () { + final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65, + 'scanCode': 0x00000026, + 'unicodeScalarValues': 0x10FFFF, + 'modifiers': 0x0, + }); + final RawKeyEventDataLinux data = keyAEvent.data as RawKeyEventDataLinux; + expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA)); + expect(data.logicalKey.keyId, equals(0x10FFFF)); + expect(data.keyLabel, equals('􏿿')); + }); + + test('Code points with more than three Unicode scalar values are not allowed', () { + // |keyCode| and |scanCode| are arbitrary values. This test should fail due to an invalid |unicodeScalarValues|. + void _createFailingKey() { + RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65, + 'scanCode': 0x00000026, + 'unicodeScalarValues': 0x1F00000000, + 'modifiers': 0x0, + }); + } + + expect(() => _createFailingKey(), throwsAssertionError); + }); + test('Control keyboard keys are correctly translated', () { + final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65307, + 'scanCode': 0x00000009, + 'unicodeScalarValues': 0, + 'modifiers': 0x0, + }); + final RawKeyEventDataLinux data = escapeKeyEvent.data as RawKeyEventDataLinux; + expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); + expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); + expect(data.keyLabel, isNull); + }); + test('Modifier keyboard keys are correctly translated', () { + final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { + 'type': 'keydown', + 'keymap': 'linux', + 'toolkit': 'gtk', + 'keyCode': 65505, + 'scanCode': 0x00000032, + 'unicodeScalarValues': 0, + }); + final RawKeyEventDataLinux data = shiftLeftKeyEvent.data as RawKeyEventDataLinux; + expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); + expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); + expect(data.keyLabel, isNull); + }); + }, skip: isBrowser); + group('RawKeyEventDataWeb', () { const Map modifierTests = { RawKeyEventDataWeb.modifierAlt: ModifierKey.altModifier,