Unverified Commit 24d39997 authored by puelo's avatar puelo Committed by GitHub

Generate RawKeyEvents for iOS 13.4+ (#65193)

* Added RawKeyEvent support for iOS

* Removed unused remnant

* added some missing keys

* Removed trailing whitespaces

* commit for build

* Added mapping names

* Made iOS keycodes generatable and collectable

* Fixed naming and formatting issues

* fixed raw_keyboard_test
parent f8772661
......@@ -11,6 +11,7 @@ import 'package:path/path.dart' as path;
import 'package:gen_keycodes/android_code_gen.dart';
import 'package:gen_keycodes/base_code_gen.dart';
import 'package:gen_keycodes/ios_code_gen.dart';
import 'package:gen_keycodes/macos_code_gen.dart';
import 'package:gen_keycodes/fuchsia_code_gen.dart';
import 'package:gen_keycodes/glfw_code_gen.dart';
......@@ -252,7 +253,7 @@ Future<void> main(List<String> rawArguments) async {
print('Writing ${'key maps'.padRight(15)}${mapsFile.absolute}');
await mapsFile.writeAsString(KeyboardMapsCodeGenerator(data).generate());
for (final String platform in <String>['android', 'darwin', 'glfw', 'fuchsia', 'linux', 'windows', 'web']) {
for (final String platform in <String>['android', 'macos', 'ios', 'glfw', 'fuchsia', 'linux', 'windows', 'web']) {
PlatformCodeGenerator codeGenerator;
switch (platform) {
case 'glfw':
......@@ -264,9 +265,12 @@ Future<void> main(List<String> rawArguments) async {
case 'android':
codeGenerator = AndroidCodeGenerator(data);
break;
case 'darwin':
case 'macos':
codeGenerator = MacOsCodeGenerator(data);
break;
case 'ios':
codeGenerator = IosCodeGenerator(data);
break;
case 'windows':
codeGenerator = WindowsCodeGenerator(data);
break;
......
......@@ -17,7 +17,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -47,7 +48,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -78,7 +80,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -106,7 +109,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -137,7 +141,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -166,7 +171,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -191,7 +197,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -216,7 +223,8 @@
"linux": 633,
"xkb": 641,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -249,7 +257,8 @@
"linux": 142,
"xkb": 150,
"windows": 57439,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -286,7 +295,8 @@
"linux": 143,
"xkb": 151,
"windows": 57443,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -315,7 +325,8 @@
"linux": 227,
"xkb": 235,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -340,7 +351,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 0
},
"keyCodes": {
"android": null,
......@@ -365,7 +377,8 @@
"linux": null,
"xkb": null,
"windows": 255,
"macos": null
"macos": null,
"ios": 1
},
"keyCodes": {
"android": null,
......@@ -390,7 +403,8 @@
"linux": null,
"xkb": null,
"windows": 252,
"macos": null
"macos": null,
"ios": 2
},
"keyCodes": {
"android": null,
......@@ -415,7 +429,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 3
},
"keyCodes": {
"android": null,
......@@ -450,7 +465,8 @@
"linux": 30,
"xkb": 38,
"windows": 30,
"macos": 0
"macos": 0,
"ios": 4
},
"keyCodes": {
"android": [
......@@ -493,7 +509,8 @@
"linux": 48,
"xkb": 56,
"windows": 48,
"macos": 11
"macos": 11,
"ios": 5
},
"keyCodes": {
"android": [
......@@ -536,7 +553,8 @@
"linux": 46,
"xkb": 54,
"windows": 46,
"macos": 8
"macos": 8,
"ios": 6
},
"keyCodes": {
"android": [
......@@ -579,7 +597,8 @@
"linux": 32,
"xkb": 40,
"windows": 32,
"macos": 2
"macos": 2,
"ios": 7
},
"keyCodes": {
"android": [
......@@ -622,7 +641,8 @@
"linux": 18,
"xkb": 26,
"windows": 18,
"macos": 14
"macos": 14,
"ios": 8
},
"keyCodes": {
"android": [
......@@ -665,7 +685,8 @@
"linux": 33,
"xkb": 41,
"windows": 33,
"macos": 3
"macos": 3,
"ios": 9
},
"keyCodes": {
"android": [
......@@ -708,7 +729,8 @@
"linux": 34,
"xkb": 42,
"windows": 34,
"macos": 5
"macos": 5,
"ios": 10
},
"keyCodes": {
"android": [
......@@ -751,7 +773,8 @@
"linux": 35,
"xkb": 43,
"windows": 35,
"macos": 4
"macos": 4,
"ios": 11
},
"keyCodes": {
"android": [
......@@ -794,7 +817,8 @@
"linux": 23,
"xkb": 31,
"windows": 23,
"macos": 34
"macos": 34,
"ios": 12
},
"keyCodes": {
"android": [
......@@ -837,7 +861,8 @@
"linux": 36,
"xkb": 44,
"windows": 36,
"macos": 38
"macos": 38,
"ios": 13
},
"keyCodes": {
"android": [
......@@ -880,7 +905,8 @@
"linux": 37,
"xkb": 45,
"windows": 37,
"macos": 40
"macos": 40,
"ios": 14
},
"keyCodes": {
"android": [
......@@ -923,7 +949,8 @@
"linux": 38,
"xkb": 46,
"windows": 38,
"macos": 37
"macos": 37,
"ios": 15
},
"keyCodes": {
"android": [
......@@ -966,7 +993,8 @@
"linux": 50,
"xkb": 58,
"windows": 50,
"macos": 46
"macos": 46,
"ios": 16
},
"keyCodes": {
"android": [
......@@ -1009,7 +1037,8 @@
"linux": 49,
"xkb": 57,
"windows": 49,
"macos": 45
"macos": 45,
"ios": 17
},
"keyCodes": {
"android": [
......@@ -1052,7 +1081,8 @@
"linux": 24,
"xkb": 32,
"windows": 24,
"macos": 31
"macos": 31,
"ios": 18
},
"keyCodes": {
"android": [
......@@ -1095,7 +1125,8 @@
"linux": 25,
"xkb": 33,
"windows": 25,
"macos": 35
"macos": 35,
"ios": 19
},
"keyCodes": {
"android": [
......@@ -1138,7 +1169,8 @@
"linux": 16,
"xkb": 24,
"windows": 16,
"macos": 12
"macos": 12,
"ios": 20
},
"keyCodes": {
"android": [
......@@ -1181,7 +1213,8 @@
"linux": 19,
"xkb": 27,
"windows": 19,
"macos": 15
"macos": 15,
"ios": 21
},
"keyCodes": {
"android": [
......@@ -1224,7 +1257,8 @@
"linux": 31,
"xkb": 39,
"windows": 31,
"macos": 1
"macos": 1,
"ios": 22
},
"keyCodes": {
"android": [
......@@ -1267,7 +1301,8 @@
"linux": 20,
"xkb": 28,
"windows": 20,
"macos": 17
"macos": 17,
"ios": 23
},
"keyCodes": {
"android": [
......@@ -1310,7 +1345,8 @@
"linux": 22,
"xkb": 30,
"windows": 22,
"macos": 32
"macos": 32,
"ios": 24
},
"keyCodes": {
"android": [
......@@ -1353,7 +1389,8 @@
"linux": 47,
"xkb": 55,
"windows": 47,
"macos": 9
"macos": 9,
"ios": 25
},
"keyCodes": {
"android": [
......@@ -1396,7 +1433,8 @@
"linux": 17,
"xkb": 25,
"windows": 17,
"macos": 13
"macos": 13,
"ios": 26
},
"keyCodes": {
"android": [
......@@ -1439,7 +1477,8 @@
"linux": 45,
"xkb": 53,
"windows": 45,
"macos": 7
"macos": 7,
"ios": 27
},
"keyCodes": {
"android": [
......@@ -1482,7 +1521,8 @@
"linux": 21,
"xkb": 29,
"windows": 21,
"macos": 16
"macos": 16,
"ios": 28
},
"keyCodes": {
"android": [
......@@ -1525,7 +1565,8 @@
"linux": 44,
"xkb": 52,
"windows": 44,
"macos": 6
"macos": 6,
"ios": 29
},
"keyCodes": {
"android": [
......@@ -1566,7 +1607,8 @@
"linux": 2,
"xkb": 10,
"windows": 2,
"macos": 18
"macos": 18,
"ios": 30
},
"keyCodes": {
"android": [
......@@ -1605,7 +1647,8 @@
"linux": 3,
"xkb": 11,
"windows": 3,
"macos": 19
"macos": 19,
"ios": 31
},
"keyCodes": {
"android": [
......@@ -1644,7 +1687,8 @@
"linux": 4,
"xkb": 12,
"windows": 4,
"macos": 20
"macos": 20,
"ios": 32
},
"keyCodes": {
"android": [
......@@ -1683,7 +1727,8 @@
"linux": 5,
"xkb": 13,
"windows": 5,
"macos": 21
"macos": 21,
"ios": 33
},
"keyCodes": {
"android": [
......@@ -1722,7 +1767,8 @@
"linux": 6,
"xkb": 14,
"windows": 6,
"macos": 23
"macos": 23,
"ios": 34
},
"keyCodes": {
"android": [
......@@ -1761,7 +1807,8 @@
"linux": 7,
"xkb": 15,
"windows": 7,
"macos": 22
"macos": 22,
"ios": 35
},
"keyCodes": {
"android": [
......@@ -1800,7 +1847,8 @@
"linux": 8,
"xkb": 16,
"windows": 8,
"macos": 26
"macos": 26,
"ios": 36
},
"keyCodes": {
"android": [
......@@ -1839,7 +1887,8 @@
"linux": 9,
"xkb": 17,
"windows": 9,
"macos": 28
"macos": 28,
"ios": 37
},
"keyCodes": {
"android": [
......@@ -1878,7 +1927,8 @@
"linux": 10,
"xkb": 18,
"windows": 10,
"macos": 25
"macos": 25,
"ios": 38
},
"keyCodes": {
"android": [
......@@ -1917,7 +1967,8 @@
"linux": 11,
"xkb": 19,
"windows": 11,
"macos": 29
"macos": 29,
"ios": 39
},
"keyCodes": {
"android": [
......@@ -1960,7 +2011,8 @@
"linux": 28,
"xkb": 36,
"windows": 28,
"macos": 36
"macos": 36,
"ios": 40
},
"keyCodes": {
"android": [
......@@ -2004,7 +2056,8 @@
"linux": 1,
"xkb": 9,
"windows": 1,
"macos": 53
"macos": 53,
"ios": 41
},
"keyCodes": {
"android": [
......@@ -2047,7 +2100,8 @@
"linux": 14,
"xkb": 22,
"windows": 14,
"macos": 51
"macos": 51,
"ios": 42
},
"keyCodes": {
"android": [
......@@ -2092,7 +2146,8 @@
"linux": 15,
"xkb": 23,
"windows": 15,
"macos": 48
"macos": 48,
"ios": 43
},
"keyCodes": {
"android": [
......@@ -2138,7 +2193,8 @@
"linux": 57,
"xkb": 65,
"windows": 57,
"macos": 49
"macos": 49,
"ios": 44
},
"keyCodes": {
"android": [
......@@ -2182,7 +2238,8 @@
"linux": 12,
"xkb": 20,
"windows": 12,
"macos": 27
"macos": 27,
"ios": 45
},
"keyCodes": {
"android": [
......@@ -2225,7 +2282,8 @@
"linux": 13,
"xkb": 21,
"windows": 13,
"macos": 24
"macos": 24,
"ios": 46
},
"keyCodes": {
"android": [
......@@ -2268,7 +2326,8 @@
"linux": 26,
"xkb": 34,
"windows": 26,
"macos": 33
"macos": 33,
"ios": 47
},
"keyCodes": {
"android": [
......@@ -2311,7 +2370,8 @@
"linux": 27,
"xkb": 35,
"windows": 27,
"macos": 30
"macos": 30,
"ios": 48
},
"keyCodes": {
"android": [
......@@ -2355,7 +2415,8 @@
"linux": 43,
"xkb": 51,
"windows": 43,
"macos": 42
"macos": 42,
"ios": 49
},
"keyCodes": {
"android": [
......@@ -2398,7 +2459,8 @@
"linux": 39,
"xkb": 47,
"windows": 39,
"macos": 41
"macos": 41,
"ios": 51
},
"keyCodes": {
"android": [
......@@ -2441,7 +2503,8 @@
"linux": 40,
"xkb": 48,
"windows": 40,
"macos": 39
"macos": 39,
"ios": 52
},
"keyCodes": {
"android": [
......@@ -2484,7 +2547,8 @@
"linux": 41,
"xkb": 49,
"windows": 41,
"macos": 50
"macos": 50,
"ios": 53
},
"keyCodes": {
"android": [
......@@ -2527,7 +2591,8 @@
"linux": 51,
"xkb": 59,
"windows": 51,
"macos": 43
"macos": 43,
"ios": 54
},
"keyCodes": {
"android": [
......@@ -2570,7 +2635,8 @@
"linux": 52,
"xkb": 60,
"windows": 52,
"macos": 47
"macos": 47,
"ios": 55
},
"keyCodes": {
"android": [
......@@ -2613,7 +2679,8 @@
"linux": 53,
"xkb": 61,
"windows": 53,
"macos": 44
"macos": 44,
"ios": 56
},
"keyCodes": {
"android": [
......@@ -2656,7 +2723,8 @@
"linux": 58,
"xkb": 66,
"windows": 58,
"macos": 57
"macos": 57,
"ios": 57
},
"keyCodes": {
"android": [
......@@ -2700,7 +2768,8 @@
"linux": 59,
"xkb": 67,
"windows": 59,
"macos": 122
"macos": 122,
"ios": 58
},
"keyCodes": {
"android": [
......@@ -2745,7 +2814,8 @@
"linux": 60,
"xkb": 68,
"windows": 60,
"macos": 120
"macos": 120,
"ios": 59
},
"keyCodes": {
"android": [
......@@ -2790,7 +2860,8 @@
"linux": 61,
"xkb": 69,
"windows": 61,
"macos": 99
"macos": 99,
"ios": 60
},
"keyCodes": {
"android": [
......@@ -2835,7 +2906,8 @@
"linux": 62,
"xkb": 70,
"windows": 62,
"macos": 118
"macos": 118,
"ios": 61
},
"keyCodes": {
"android": [
......@@ -2879,7 +2951,8 @@
"linux": 63,
"xkb": 71,
"windows": 63,
"macos": 96
"macos": 96,
"ios": 62
},
"keyCodes": {
"android": [
......@@ -2922,7 +2995,8 @@
"linux": 64,
"xkb": 72,
"windows": 64,
"macos": 97
"macos": 97,
"ios": 63
},
"keyCodes": {
"android": [
......@@ -2965,7 +3039,8 @@
"linux": 65,
"xkb": 73,
"windows": 65,
"macos": 98
"macos": 98,
"ios": 64
},
"keyCodes": {
"android": [
......@@ -3008,7 +3083,8 @@
"linux": 66,
"xkb": 74,
"windows": 66,
"macos": 100
"macos": 100,
"ios": 65
},
"keyCodes": {
"android": [
......@@ -3051,7 +3127,8 @@
"linux": 67,
"xkb": 75,
"windows": 67,
"macos": 101
"macos": 101,
"ios": 66
},
"keyCodes": {
"android": [
......@@ -3094,7 +3171,8 @@
"linux": 68,
"xkb": 76,
"windows": 68,
"macos": 109
"macos": 109,
"ios": 67
},
"keyCodes": {
"android": [
......@@ -3137,7 +3215,8 @@
"linux": 87,
"xkb": 95,
"windows": 87,
"macos": 103
"macos": 103,
"ios": 68
},
"keyCodes": {
"android": [
......@@ -3180,7 +3259,8 @@
"linux": 88,
"xkb": 96,
"windows": 88,
"macos": 111
"macos": 111,
"ios": 69
},
"keyCodes": {
"android": [
......@@ -3221,7 +3301,8 @@
"linux": 99,
"xkb": 107,
"windows": 57399,
"macos": null
"macos": null,
"ios": 70
},
"keyCodes": {
"android": [
......@@ -3258,7 +3339,8 @@
"linux": 70,
"xkb": 78,
"windows": 70,
"macos": null
"macos": null,
"ios": 71
},
"keyCodes": {
"android": [
......@@ -3298,7 +3380,8 @@
"linux": 119,
"xkb": 127,
"windows": 69,
"macos": null
"macos": null,
"ios": 72
},
"keyCodes": {
"android": [
......@@ -3342,7 +3425,8 @@
"linux": 110,
"xkb": 118,
"windows": 57426,
"macos": 114
"macos": 114,
"ios": 73
},
"keyCodes": {
"android": [
......@@ -3387,7 +3471,8 @@
"linux": 102,
"xkb": 110,
"windows": 57415,
"macos": 115
"macos": 115,
"ios": 74
},
"keyCodes": {
"android": [
......@@ -3431,7 +3516,8 @@
"linux": 104,
"xkb": 112,
"windows": 57417,
"macos": 116
"macos": 116,
"ios": 75
},
"keyCodes": {
"android": [
......@@ -3474,7 +3560,8 @@
"linux": 111,
"xkb": 119,
"windows": 57427,
"macos": 117
"macos": 117,
"ios": 76
},
"keyCodes": {
"android": [
......@@ -3519,7 +3606,8 @@
"linux": 107,
"xkb": 115,
"windows": 57423,
"macos": 119
"macos": 119,
"ios": 77
},
"keyCodes": {
"android": [
......@@ -3563,7 +3651,8 @@
"linux": 109,
"xkb": 117,
"windows": 57425,
"macos": 121
"macos": 121,
"ios": 78
},
"keyCodes": {
"android": [
......@@ -3606,7 +3695,8 @@
"linux": 106,
"xkb": 114,
"windows": 57421,
"macos": 124
"macos": 124,
"ios": 79
},
"keyCodes": {
"android": [
......@@ -3651,7 +3741,8 @@
"linux": 105,
"xkb": 113,
"windows": 57419,
"macos": 123
"macos": 123,
"ios": 80
},
"keyCodes": {
"android": [
......@@ -3696,7 +3787,8 @@
"linux": 108,
"xkb": 116,
"windows": 57424,
"macos": 125
"macos": 125,
"ios": 81
},
"keyCodes": {
"android": [
......@@ -3741,7 +3833,8 @@
"linux": 103,
"xkb": 111,
"windows": 57416,
"macos": 126
"macos": 126,
"ios": 82
},
"keyCodes": {
"android": [
......@@ -3783,7 +3876,8 @@
"linux": 69,
"xkb": 77,
"windows": 57413,
"macos": 71
"macos": 71,
"ios": 83
},
"keyCodes": {
"android": [
......@@ -3824,7 +3918,8 @@
"linux": 98,
"xkb": 106,
"windows": 57397,
"macos": 75
"macos": 75,
"ios": 84
},
"keyCodes": {
"android": [
......@@ -3867,7 +3962,8 @@
"linux": 55,
"xkb": 63,
"windows": 55,
"macos": 67
"macos": 67,
"ios": 85
},
"keyCodes": {
"android": [
......@@ -3910,7 +4006,8 @@
"linux": 74,
"xkb": 82,
"windows": 74,
"macos": 78
"macos": 78,
"ios": 86
},
"keyCodes": {
"android": [
......@@ -3951,7 +4048,8 @@
"linux": 78,
"xkb": 86,
"windows": 78,
"macos": 69
"macos": 69,
"ios": 87
},
"keyCodes": {
"android": [
......@@ -3992,7 +4090,8 @@
"linux": 96,
"xkb": 104,
"windows": 57372,
"macos": 76
"macos": 76,
"ios": 88
},
"keyCodes": {
"android": [
......@@ -4033,7 +4132,8 @@
"linux": 79,
"xkb": 87,
"windows": 79,
"macos": 83
"macos": 83,
"ios": 89
},
"keyCodes": {
"android": [
......@@ -4076,7 +4176,8 @@
"linux": 80,
"xkb": 88,
"windows": 80,
"macos": 84
"macos": 84,
"ios": 90
},
"keyCodes": {
"android": [
......@@ -4119,7 +4220,8 @@
"linux": 81,
"xkb": 89,
"windows": 81,
"macos": 85
"macos": 85,
"ios": 91
},
"keyCodes": {
"android": [
......@@ -4162,7 +4264,8 @@
"linux": 75,
"xkb": 83,
"windows": 75,
"macos": 86
"macos": 86,
"ios": 92
},
"keyCodes": {
"android": [
......@@ -4205,7 +4308,8 @@
"linux": 76,
"xkb": 84,
"windows": 76,
"macos": 87
"macos": 87,
"ios": 93
},
"keyCodes": {
"android": [
......@@ -4248,7 +4352,8 @@
"linux": 77,
"xkb": 85,
"windows": 77,
"macos": 88
"macos": 88,
"ios": 94
},
"keyCodes": {
"android": [
......@@ -4291,7 +4396,8 @@
"linux": 71,
"xkb": 79,
"windows": 71,
"macos": 89
"macos": 89,
"ios": 95
},
"keyCodes": {
"android": [
......@@ -4334,7 +4440,8 @@
"linux": 72,
"xkb": 80,
"windows": 72,
"macos": 91
"macos": 91,
"ios": 96
},
"keyCodes": {
"android": [
......@@ -4377,7 +4484,8 @@
"linux": 73,
"xkb": 81,
"windows": 73,
"macos": 92
"macos": 92,
"ios": 97
},
"keyCodes": {
"android": [
......@@ -4420,7 +4528,8 @@
"linux": 82,
"xkb": 90,
"windows": 82,
"macos": 82
"macos": 82,
"ios": 98
},
"keyCodes": {
"android": [
......@@ -4463,7 +4572,8 @@
"linux": 83,
"xkb": 91,
"windows": 83,
"macos": 65
"macos": 65,
"ios": 99
},
"keyCodes": {
"android": [
......@@ -4496,7 +4606,8 @@
"linux": 86,
"xkb": 94,
"windows": 86,
"macos": 10
"macos": 10,
"ios": 100
},
"keyCodes": {
"android": null,
......@@ -4530,7 +4641,8 @@
"linux": 127,
"xkb": 135,
"windows": 57437,
"macos": 110
"macos": 110,
"ios": 101
},
"keyCodes": {
"android": [
......@@ -4568,7 +4680,8 @@
"linux": 116,
"xkb": 124,
"windows": 57438,
"macos": null
"macos": null,
"ios": 102
},
"keyCodes": {
"android": [
......@@ -4607,7 +4720,8 @@
"linux": 117,
"xkb": 125,
"windows": 89,
"macos": 81
"macos": 81,
"ios": 103
},
"keyCodes": {
"android": [
......@@ -4650,7 +4764,8 @@
"linux": 183,
"xkb": 191,
"windows": 100,
"macos": 105
"macos": 105,
"ios": 104
},
"keyCodes": {
"android": null,
......@@ -4691,7 +4806,8 @@
"linux": 184,
"xkb": 192,
"windows": 101,
"macos": 107
"macos": 107,
"ios": 105
},
"keyCodes": {
"android": null,
......@@ -4732,7 +4848,8 @@
"linux": 185,
"xkb": 193,
"windows": 102,
"macos": 113
"macos": 113,
"ios": 106
},
"keyCodes": {
"android": null,
......@@ -4773,7 +4890,8 @@
"linux": 186,
"xkb": 194,
"windows": 103,
"macos": 106
"macos": 106,
"ios": 107
},
"keyCodes": {
"android": null,
......@@ -4814,7 +4932,8 @@
"linux": 187,
"xkb": 195,
"windows": 104,
"macos": 64
"macos": 64,
"ios": 108
},
"keyCodes": {
"android": null,
......@@ -4855,7 +4974,8 @@
"linux": 188,
"xkb": 196,
"windows": 105,
"macos": 79
"macos": 79,
"ios": 109
},
"keyCodes": {
"android": null,
......@@ -4896,7 +5016,8 @@
"linux": 189,
"xkb": 197,
"windows": 106,
"macos": 80
"macos": 80,
"ios": 110
},
"keyCodes": {
"android": null,
......@@ -4937,7 +5058,8 @@
"linux": 190,
"xkb": 198,
"windows": 107,
"macos": 90
"macos": 90,
"ios": 111
},
"keyCodes": {
"android": null,
......@@ -4978,7 +5100,8 @@
"linux": 191,
"xkb": 199,
"windows": 108,
"macos": null
"macos": null,
"ios": 112
},
"keyCodes": {
"android": null,
......@@ -5019,7 +5142,8 @@
"linux": 192,
"xkb": 200,
"windows": 109,
"macos": null
"macos": null,
"ios": 113
},
"keyCodes": {
"android": null,
......@@ -5060,7 +5184,8 @@
"linux": 193,
"xkb": 201,
"windows": 110,
"macos": null
"macos": null,
"ios": 114
},
"keyCodes": {
"android": null,
......@@ -5099,7 +5224,8 @@
"linux": 194,
"xkb": 202,
"windows": 118,
"macos": null
"macos": null,
"ios": 115
},
"keyCodes": {
"android": null,
......@@ -5134,7 +5260,8 @@
"linux": 134,
"xkb": 142,
"windows": null,
"macos": null
"macos": null,
"ios": 116
},
"keyCodes": {
"android": null,
......@@ -5169,7 +5296,8 @@
"linux": 138,
"xkb": 146,
"windows": 57403,
"macos": null
"macos": null,
"ios": 117
},
"keyCodes": {
"android": [
......@@ -5208,7 +5336,8 @@
"linux": 132,
"xkb": 140,
"windows": null,
"macos": null
"macos": null,
"ios": 119
},
"keyCodes": {
"android": [
......@@ -5243,7 +5372,8 @@
"linux": 129,
"xkb": 137,
"windows": null,
"macos": null
"macos": null,
"ios": 121
},
"keyCodes": {
"android": null,
......@@ -5274,7 +5404,8 @@
"linux": 131,
"xkb": 139,
"windows": 57352,
"macos": null
"macos": null,
"ios": 122
},
"keyCodes": {
"android": null,
......@@ -5305,7 +5436,8 @@
"linux": 137,
"xkb": 145,
"windows": 57367,
"macos": null
"macos": null,
"ios": 123
},
"keyCodes": {
"android": [
......@@ -5339,7 +5471,8 @@
"linux": 133,
"xkb": 141,
"windows": 57368,
"macos": null
"macos": null,
"ios": 124
},
"keyCodes": {
"android": [
......@@ -5375,7 +5508,8 @@
"linux": 135,
"xkb": 143,
"windows": 57354,
"macos": null
"macos": null,
"ios": 125
},
"keyCodes": {
"android": [
......@@ -5410,7 +5544,8 @@
"linux": 136,
"xkb": 144,
"windows": null,
"macos": null
"macos": null,
"ios": 126
},
"keyCodes": {
"android": null,
......@@ -5443,7 +5578,8 @@
"linux": 113,
"xkb": 121,
"windows": 57376,
"macos": 74
"macos": 74,
"ios": 127
},
"keyCodes": {
"android": [
......@@ -5478,7 +5614,8 @@
"linux": 115,
"xkb": 123,
"windows": 57392,
"macos": 72
"macos": 72,
"ios": 128
},
"keyCodes": {
"android": [
......@@ -5513,7 +5650,8 @@
"linux": 114,
"xkb": 122,
"windows": 57390,
"macos": 73
"macos": 73,
"ios": 129
},
"keyCodes": {
"android": [
......@@ -5547,7 +5685,8 @@
"linux": 121,
"xkb": 129,
"windows": 126,
"macos": 95
"macos": 95,
"ios": 133
},
"keyCodes": {
"android": [
......@@ -5574,7 +5713,8 @@
"linux": 89,
"xkb": 97,
"windows": 115,
"macos": 94
"macos": 94,
"ios": 135
},
"keyCodes": {
"android": null,
......@@ -5601,7 +5741,8 @@
"linux": 93,
"xkb": 101,
"windows": 112,
"macos": null
"macos": null,
"ios": 136
},
"keyCodes": {
"android": null,
......@@ -5630,7 +5771,8 @@
"linux": 124,
"xkb": 132,
"windows": 125,
"macos": 93
"macos": 93,
"ios": 137
},
"keyCodes": {
"android": null,
......@@ -5663,7 +5805,8 @@
"linux": 92,
"xkb": 100,
"windows": 121,
"macos": null
"macos": null,
"ios": 138
},
"keyCodes": {
"android": [
......@@ -5696,7 +5839,8 @@
"linux": 94,
"xkb": 102,
"windows": 123,
"macos": null
"macos": null,
"ios": 139
},
"keyCodes": {
"android": [
......@@ -5723,7 +5867,8 @@
"linux": 122,
"xkb": 130,
"windows": 114,
"macos": 104
"macos": 104,
"ios": 144
},
"keyCodes": {
"android": null,
......@@ -5748,7 +5893,8 @@
"linux": 123,
"xkb": 131,
"windows": 113,
"macos": 102
"macos": 102,
"ios": 145
},
"keyCodes": {
"android": null,
......@@ -5777,7 +5923,8 @@
"linux": 90,
"xkb": 98,
"windows": 120,
"macos": null
"macos": null,
"ios": 146
},
"keyCodes": {
"android": null,
......@@ -5806,7 +5953,8 @@
"linux": 91,
"xkb": 99,
"windows": 119,
"macos": null
"macos": null,
"ios": 147
},
"keyCodes": {
"android": null,
......@@ -5831,7 +5979,8 @@
"linux": 85,
"xkb": 93,
"windows": null,
"macos": null
"macos": null,
"ios": 148
},
"keyCodes": {
"android": null,
......@@ -5856,7 +6005,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 155
},
"keyCodes": {
"android": null,
......@@ -5885,7 +6035,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 163
},
"keyCodes": {
"android": null,
......@@ -5914,7 +6065,8 @@
"linux": 179,
"xkb": 187,
"windows": null,
"macos": null
"macos": null,
"ios": 182
},
"keyCodes": {
"android": [
......@@ -5945,7 +6097,8 @@
"linux": 180,
"xkb": 188,
"windows": null,
"macos": null
"macos": null,
"ios": 183
},
"keyCodes": {
"android": [
......@@ -5972,7 +6125,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 187
},
"keyCodes": {
"android": null,
......@@ -5997,7 +6151,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 208
},
"keyCodes": {
"android": null,
......@@ -6022,7 +6177,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 209
},
"keyCodes": {
"android": null,
......@@ -6047,7 +6203,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 210
},
"keyCodes": {
"android": null,
......@@ -6072,7 +6229,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 211
},
"keyCodes": {
"android": null,
......@@ -6097,7 +6255,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 212
},
"keyCodes": {
"android": null,
......@@ -6122,7 +6281,8 @@
"linux": 118,
"xkb": 126,
"windows": null,
"macos": null
"macos": null,
"ios": 215
},
"keyCodes": {
"android": null,
......@@ -6147,7 +6307,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 216
},
"keyCodes": {
"android": null,
......@@ -6172,7 +6333,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": 217
},
"keyCodes": {
"android": null,
......@@ -6207,7 +6369,8 @@
"linux": 29,
"xkb": 37,
"windows": 29,
"macos": 59
"macos": 59,
"ios": 224
},
"keyCodes": {
"android": [
......@@ -6250,7 +6413,8 @@
"linux": 42,
"xkb": 50,
"windows": 42,
"macos": 56
"macos": 56,
"ios": 225
},
"keyCodes": {
"android": [
......@@ -6293,7 +6457,8 @@
"linux": 56,
"xkb": 64,
"windows": 56,
"macos": 58
"macos": 58,
"ios": 226
},
"keyCodes": {
"android": [
......@@ -6336,7 +6501,8 @@
"linux": 125,
"xkb": 133,
"windows": 57435,
"macos": 55
"macos": 55,
"ios": 227
},
"keyCodes": {
"android": [
......@@ -6379,7 +6545,8 @@
"linux": 97,
"xkb": 105,
"windows": 57373,
"macos": 62
"macos": 62,
"ios": 228
},
"keyCodes": {
"android": [
......@@ -6422,7 +6589,8 @@
"linux": 54,
"xkb": 62,
"windows": 54,
"macos": 60
"macos": 60,
"ios": 229
},
"keyCodes": {
"android": [
......@@ -6465,7 +6633,8 @@
"linux": 100,
"xkb": 108,
"windows": 57400,
"macos": 61
"macos": 61,
"ios": 230
},
"keyCodes": {
"android": [
......@@ -6508,7 +6677,8 @@
"linux": 126,
"xkb": 134,
"windows": 57436,
"macos": 54
"macos": 54,
"ios": 231
},
"keyCodes": {
"android": [
......@@ -6545,7 +6715,8 @@
"linux": 358,
"xkb": 366,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6576,7 +6747,8 @@
"linux": 370,
"xkb": 378,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6609,7 +6781,8 @@
"linux": 225,
"xkb": 233,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6644,7 +6817,8 @@
"linux": 224,
"xkb": 232,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6673,7 +6847,8 @@
"linux": 431,
"xkb": 439,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6698,7 +6873,8 @@
"linux": 592,
"xkb": 600,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6723,7 +6899,8 @@
"linux": 593,
"xkb": 601,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6748,7 +6925,8 @@
"linux": 244,
"xkb": 252,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6775,7 +6953,8 @@
"linux": 230,
"xkb": 238,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6804,7 +6983,8 @@
"linux": 229,
"xkb": 237,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6835,7 +7015,8 @@
"linux": 405,
"xkb": 413,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6864,7 +7045,8 @@
"linux": 169,
"xkb": 177,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6891,7 +7073,8 @@
"linux": 362,
"xkb": 370,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6920,7 +7103,8 @@
"linux": 174,
"xkb": 182,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -6949,7 +7133,8 @@
"linux": 410,
"xkb": 418,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -6980,7 +7165,8 @@
"linux": 411,
"xkb": 419,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7015,7 +7201,8 @@
"linux": 207,
"xkb": 215,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7051,7 +7238,8 @@
"linux": 201,
"xkb": 209,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7086,7 +7274,8 @@
"linux": 167,
"xkb": 175,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7121,7 +7310,8 @@
"linux": 208,
"xkb": 216,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7156,7 +7346,8 @@
"linux": 168,
"xkb": 176,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7191,7 +7382,8 @@
"linux": 163,
"xkb": 171,
"windows": 57369,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7226,7 +7418,8 @@
"linux": 165,
"xkb": 173,
"windows": 57360,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7264,7 +7457,8 @@
"linux": 166,
"xkb": 174,
"windows": 57380,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7302,7 +7496,8 @@
"linux": 161,
"xkb": 169,
"windows": 57388,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7337,7 +7532,8 @@
"linux": 164,
"xkb": 172,
"windows": 57378,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7366,7 +7562,8 @@
"linux": 582,
"xkb": 590,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7395,7 +7592,8 @@
"linux": 209,
"xkb": 217,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7420,7 +7618,8 @@
"linux": 171,
"xkb": 179,
"windows": 57453,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7445,7 +7644,8 @@
"linux": 421,
"xkb": 429,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7470,7 +7670,8 @@
"linux": 423,
"xkb": 431,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7504,7 +7705,8 @@
"linux": 155,
"xkb": 163,
"windows": 57452,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7539,7 +7741,8 @@
"linux": 429,
"xkb": 437,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7572,7 +7775,8 @@
"linux": 397,
"xkb": 405,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7603,7 +7807,8 @@
"linux": 140,
"xkb": 148,
"windows": 57377,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7632,7 +7837,8 @@
"linux": 144,
"xkb": 152,
"windows": 57451,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7661,7 +7867,8 @@
"linux": 150,
"xkb": 158,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7690,7 +7897,8 @@
"linux": 433,
"xkb": 441,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7717,7 +7925,8 @@
"linux": 152,
"xkb": 160,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7742,7 +7951,8 @@
"linux": 579,
"xkb": 587,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7767,7 +7977,8 @@
"linux": 580,
"xkb": 588,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7794,7 +8005,8 @@
"linux": 235,
"xkb": 243,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7821,7 +8033,8 @@
"linux": 432,
"xkb": 440,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7848,7 +8061,8 @@
"linux": 374,
"xkb": 382,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7875,7 +8089,8 @@
"linux": 581,
"xkb": 589,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7906,7 +8121,8 @@
"linux": 583,
"xkb": 591,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -7935,7 +8151,8 @@
"linux": 392,
"xkb": 400,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -7968,7 +8185,8 @@
"linux": 181,
"xkb": 189,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8003,7 +8221,8 @@
"linux": 206,
"xkb": 214,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8034,7 +8253,8 @@
"linux": 234,
"xkb": 242,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8069,7 +8289,8 @@
"linux": 210,
"xkb": 218,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8106,7 +8327,8 @@
"linux": 217,
"xkb": 225,
"windows": 57445,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8141,7 +8363,8 @@
"linux": 172,
"xkb": 180,
"windows": 57394,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8174,7 +8397,8 @@
"linux": 158,
"xkb": 166,
"windows": 57450,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8211,7 +8435,8 @@
"linux": 159,
"xkb": 167,
"windows": 57449,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8246,7 +8471,8 @@
"linux": 128,
"xkb": 136,
"windows": 57448,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8279,7 +8505,8 @@
"linux": 173,
"xkb": 181,
"windows": 57447,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8316,7 +8543,8 @@
"linux": 156,
"xkb": 164,
"windows": 57446,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8351,7 +8579,8 @@
"linux": 418,
"xkb": 426,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8384,7 +8613,8 @@
"linux": 419,
"xkb": 427,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8415,7 +8645,8 @@
"linux": 372,
"xkb": 380,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8448,7 +8679,8 @@
"linux": 182,
"xkb": 190,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8477,7 +8709,8 @@
"linux": 232,
"xkb": 240,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8506,7 +8739,8 @@
"linux": 233,
"xkb": 241,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8535,7 +8769,8 @@
"linux": 231,
"xkb": 239,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8562,7 +8797,8 @@
"linux": 584,
"xkb": 592,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8587,7 +8823,8 @@
"linux": 120,
"xkb": 128,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": null,
......@@ -8617,7 +8854,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8649,7 +8887,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8681,7 +8920,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8713,7 +8953,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8745,7 +8986,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8777,7 +9019,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8809,7 +9052,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8841,7 +9085,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8873,7 +9118,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8905,7 +9151,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8937,7 +9184,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -8969,7 +9217,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9001,7 +9250,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9033,7 +9283,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9065,7 +9316,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9097,7 +9349,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9128,7 +9381,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9159,7 +9413,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9190,7 +9445,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9221,7 +9477,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9252,7 +9509,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9283,7 +9541,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9314,7 +9573,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9345,7 +9605,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9376,7 +9637,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9407,7 +9669,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9438,7 +9701,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9469,7 +9733,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9500,7 +9765,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9531,7 +9797,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9562,7 +9829,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": null
"macos": null,
"ios": null
},
"keyCodes": {
"android": [
......@@ -9593,7 +9861,8 @@
"linux": null,
"xkb": null,
"windows": null,
"macos": 63
"macos": 63,
"ios": null
},
"keyCodes": {
"android": [
......
// 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 <map>
// 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_map_ios_cc.tmpl instead.
// See dev/tools/gen_keycodes/README.md for more information.
// Maps macOS-specific key code values representing [PhysicalKeyboardKey].
//
// iOS doesn't provide a scan code, but a virtual keycode to represent a physical key.
const std::map<int, int> g_ios_to_physical_key = {
@@@IOS_SCAN_CODE_MAP@@@
};
// A map of iOS 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<int, int> g_ios_numpad_map = {
@@@IOS_NUMPAD_MAP@@@
};
......@@ -8,7 +8,7 @@
// 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_map_darwin_cc.tmpl instead.
// Edit the template dev/tools/gen_keycodes/data/keyboard_map_macos_cc.tmpl instead.
// See dev/tools/gen_keycodes/README.md for more information.
// Maps macOS-specific key code values representing [PhysicalKeyboardKey].
......
......@@ -59,6 +59,20 @@ const Map<int, LogicalKeyboardKey> kMacOsFunctionKeyMap = <int, LogicalKeyboardK
@@@MACOS_FUNCTION_KEY_MAP@@@
};
/// Maps iOS-specific key code values representing [PhysicalKeyboardKey].
///
/// iOS doesn't provide a scan code, but a virtual keycode to represent a physical key.
const Map<int, PhysicalKeyboardKey> kIosToPhysicalKey = <int, PhysicalKeyboardKey>{
@@@IOS_SCAN_CODE_MAP@@@
};
/// A map of iOS 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<int, LogicalKeyboardKey> kIosNumPadMap = <int, LogicalKeyboardKey>{
@@@IOS_NUMPAD_MAP@@@
};
/// Maps GLFW-specific key codes to the matching [LogicalKeyboardKey].
const Map<int, LogicalKeyboardKey> kGlfwToLogicalKey = <int, LogicalKeyboardKey>{
@@@GLFW_KEY_CODE_MAP@@@
......
// 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.
import 'package:path/path.dart' as path;
import 'base_code_gen.dart';
import 'key_data.dart';
import 'utils.dart';
/// Generates the key mapping of iOS, based on the information in the key
/// data structure given to it.
class IosCodeGenerator extends PlatformCodeGenerator {
IosCodeGenerator(KeyData keyData) : super(keyData);
/// This generates the map of iOS key codes to physical keys.
String get _iosScanCodeMap {
final StringBuffer iosScanCodeMap = StringBuffer();
for (final Key entry in keyData.data) {
if (entry.iosScanCode != null) {
iosScanCodeMap.writeln(' { ${toHex(entry.iosScanCode)}, ${toHex(entry.usbHidCode)} }, // ${entry.constantName}');
}
}
return iosScanCodeMap.toString().trimRight();
}
/// This generates the map of iOS number pad key codes to logical keys.
String get _iosNumpadMap {
final StringBuffer iosNumPadMap = StringBuffer();
for (final Key entry in numpadKeyData) {
if (entry.iosScanCode != null) {
iosNumPadMap.writeln(' { ${toHex(entry.iosScanCode)}, ${toHex(entry.flutterId, digits: 10)} }, // ${entry.constantName}');
}
}
return iosNumPadMap.toString().trimRight();
}
@override
String get templatePath => path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'keyboard_map_ios_cc.tmpl');
@override
String outputPath(String platform) => path.joinAll(<String>[flutterRoot.path, '..', 'engine', 'src', 'flutter', 'shell', 'platform', 'darwin', platform, 'keycodes', 'keyboard_map_$platform.h']);
@override
Map<String, String> mappings() {
// There is no iOS keycode map since iOS uses keycode to represent a physical key.
// The LogicalKeyboardKey is generated by raw_keyboard_macos.dart from the unmodified characters
// from NSEvent.
return <String, String>{
'IOS_SCAN_CODE_MAP': _iosScanCodeMap,
'IOS_NUMPAD_MAP': _iosNumpadMap
};
}
}
......@@ -325,16 +325,18 @@ class KeyData {
input = input.replaceAll(commentRegExp, '');
input.replaceAllMapped(usbMapRegExp, (Match match) {
if (match != null) {
final int usbHidCode = getHex(match.group(1));
final int macScanCode = getHex(match.group(5));
final int linuxScanCode = getHex(match.group(2));
final int xKbScanCode = getHex(match.group(3));
final int windowsScanCode = getHex(match.group(4));
final Key newEntry = Key(
usbHidCode: getHex(match.group(1)),
usbHidCode: usbHidCode,
linuxScanCode: linuxScanCode == 0 ? null : linuxScanCode,
xKbScanCode: xKbScanCode == 0 ? null : xKbScanCode,
windowsScanCode: windowsScanCode == 0 ? null : windowsScanCode,
macOsScanCode: macScanCode == 0xffff ? null : macScanCode,
iosScanCode: (usbHidCode & 0x070000) == 0x070000 ? (usbHidCode ^ 0x070000) : null,
name: match.group(6) == 'NULL' ? null : match.group(6),
// The input data has a typo...
chromiumName: shoutingToLowerCamel(match.group(7)).replaceAll('Minimium', 'Minimum'),
......@@ -375,6 +377,7 @@ class Key {
this.windowsKeyNames,
this.windowsKeyCodes,
this.macOsScanCode,
this.iosScanCode,
@required this.chromiumName,
this.androidKeyNames,
this.androidScanCodes,
......@@ -403,6 +406,7 @@ class Key {
windowsKeyCodes: (map['keyCodes']['windows'] as List<dynamic>)?.cast<int>(),
windowsKeyNames: (map['names']['windows'] as List<dynamic>)?.cast<String>(),
macOsScanCode: map['scanCodes']['macos'] as int,
iosScanCode: map['scanCodes']['ios'] as int,
glfwKeyNames: (map['names']['glfw'] as List<dynamic>)?.cast<String>(),
glfwKeyCodes: (map['keyCodes']['glfw'] as List<dynamic>)?.cast<int>(),
gtkKeyNames: (map['names']['gtk'] as List<dynamic>)?.cast<String>(),
......@@ -428,6 +432,8 @@ class Key {
List<String> windowsKeyNames;
/// The macOS scan code of the key from Chromium's header file.
int macOsScanCode;
/// The iOS scan code of the key from UIKey's documentation (USB Hid table)
int iosScanCode;
/// The name of the key, mostly derived from the DomKey name in Chromium,
/// but where there was no DomKey representation, derived from the Chromium
/// symbol name.
......@@ -483,6 +489,7 @@ class Key {
'xkb': xKbScanCode,
'windows': windowsScanCode,
'macos': macOsScanCode,
'ios': iosScanCode,
},
'keyCodes': <String, List<int>>{
'android': androidKeyCodes,
......@@ -550,7 +557,8 @@ class Key {
return """'$constantName': (name: "$name", usbHidCode: ${toHex(usbHidCode)}, """
'linuxScanCode: ${toHex(linuxScanCode)}, xKbScanCode: ${toHex(xKbScanCode)}, '
'windowsKeyCode: ${toHex(windowsScanCode)}, macOsScanCode: ${toHex(macOsScanCode)}, '
'windowsScanCode: ${toHex(windowsScanCode)}, chromiumSymbolName: $chromiumName';
'windowsScanCode: ${toHex(windowsScanCode)}, chromiumSymbolName: $chromiumName '
'iOSScanCode: ${toHex(iosScanCode)})';
}
/// Returns the static map of printable representations.
......
......@@ -198,6 +198,28 @@ class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
return macOsFunctionKeyMap.toString().trimRight();
}
/// This generates the map of iOS key codes to physical keys.
String get iosScanCodeMap {
final StringBuffer iosScanCodeMap = StringBuffer();
for (final Key entry in keyData.data) {
if (entry.iosScanCode != null) {
iosScanCodeMap.writeln(' ${toHex(entry.iosScanCode)}: PhysicalKeyboardKey.${entry.constantName},');
}
}
return iosScanCodeMap.toString().trimRight();
}
/// This generates the map of iOS number pad key codes to logical keys.
String get iosNumpadMap {
final StringBuffer iosNumPadMap = StringBuffer();
for (final Key entry in numpadKeyData) {
if (entry.iosScanCode != null) {
iosNumPadMap.writeln(' ${toHex(entry.iosScanCode)}: LogicalKeyboardKey.${entry.constantName},');
}
}
return iosNumPadMap.toString().trimRight();
}
/// This generates the map of Fuchsia key codes to logical keys.
String get fuchsiaKeyCodeMap {
final StringBuffer fuchsiaKeyCodeMap = StringBuffer();
......@@ -267,6 +289,8 @@ class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
'MACOS_SCAN_CODE_MAP': macOsScanCodeMap,
'MACOS_NUMPAD_MAP': macOsNumpadMap,
'MACOS_FUNCTION_KEY_MAP': macOsFunctionKeyMap,
'IOS_SCAN_CODE_MAP': iosScanCodeMap,
'IOS_NUMPAD_MAP': iosNumpadMap,
'GLFW_KEY_CODE_MAP': glfwKeyCodeMap,
'GLFW_NUMPAD_MAP': glfwNumpadMap,
'GTK_KEY_CODE_MAP': gtkKeyCodeMap,
......
......@@ -47,7 +47,10 @@ class MacOsCodeGenerator extends PlatformCodeGenerator {
}
@override
String get templatePath => path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'keyboard_map_darwin_cc.tmpl');
String get templatePath => path.join(flutterRoot.path, 'dev', 'tools', 'gen_keycodes', 'data', 'keyboard_map_macos_cc.tmpl');
@override
String outputPath(String platform) => path.joinAll(<String>[flutterRoot.path, '..', 'engine', 'src', 'flutter', 'shell', 'platform', 'darwin', platform, 'keycodes', 'keyboard_map_$platform.h']);
@override
Map<String, String> mappings() {
......
......@@ -27,6 +27,7 @@ export 'src/services/platform_views.dart';
export 'src/services/raw_keyboard.dart';
export 'src/services/raw_keyboard_android.dart';
export 'src/services/raw_keyboard_fuchsia.dart';
export 'src/services/raw_keyboard_ios.dart';
export 'src/services/raw_keyboard_linux.dart';
export 'src/services/raw_keyboard_macos.dart';
export 'src/services/raw_keyboard_web.dart';
......
......@@ -1178,6 +1178,196 @@ const Map<int, LogicalKeyboardKey> kMacOsFunctionKeyMap = <int, LogicalKeyboardK
0x0000005a: LogicalKeyboardKey.f20,
};
/// Maps iOS-specific key code values representing [PhysicalKeyboardKey].
///
/// iOS doesn't provide a scan code, but a virtual keycode to represent a physical key.
const Map<int, PhysicalKeyboardKey> kIosToPhysicalKey = <int, PhysicalKeyboardKey>{
0x00000000: PhysicalKeyboardKey.usbReserved,
0x00000001: PhysicalKeyboardKey.usbErrorRollOver,
0x00000002: PhysicalKeyboardKey.usbPostFail,
0x00000003: PhysicalKeyboardKey.usbErrorUndefined,
0x00000004: PhysicalKeyboardKey.keyA,
0x00000005: PhysicalKeyboardKey.keyB,
0x00000006: PhysicalKeyboardKey.keyC,
0x00000007: PhysicalKeyboardKey.keyD,
0x00000008: PhysicalKeyboardKey.keyE,
0x00000009: PhysicalKeyboardKey.keyF,
0x0000000a: PhysicalKeyboardKey.keyG,
0x0000000b: PhysicalKeyboardKey.keyH,
0x0000000c: PhysicalKeyboardKey.keyI,
0x0000000d: PhysicalKeyboardKey.keyJ,
0x0000000e: PhysicalKeyboardKey.keyK,
0x0000000f: PhysicalKeyboardKey.keyL,
0x00000010: PhysicalKeyboardKey.keyM,
0x00000011: PhysicalKeyboardKey.keyN,
0x00000012: PhysicalKeyboardKey.keyO,
0x00000013: PhysicalKeyboardKey.keyP,
0x00000014: PhysicalKeyboardKey.keyQ,
0x00000015: PhysicalKeyboardKey.keyR,
0x00000016: PhysicalKeyboardKey.keyS,
0x00000017: PhysicalKeyboardKey.keyT,
0x00000018: PhysicalKeyboardKey.keyU,
0x00000019: PhysicalKeyboardKey.keyV,
0x0000001a: PhysicalKeyboardKey.keyW,
0x0000001b: PhysicalKeyboardKey.keyX,
0x0000001c: PhysicalKeyboardKey.keyY,
0x0000001d: PhysicalKeyboardKey.keyZ,
0x0000001e: PhysicalKeyboardKey.digit1,
0x0000001f: PhysicalKeyboardKey.digit2,
0x00000020: PhysicalKeyboardKey.digit3,
0x00000021: PhysicalKeyboardKey.digit4,
0x00000022: PhysicalKeyboardKey.digit5,
0x00000023: PhysicalKeyboardKey.digit6,
0x00000024: PhysicalKeyboardKey.digit7,
0x00000025: PhysicalKeyboardKey.digit8,
0x00000026: PhysicalKeyboardKey.digit9,
0x00000027: PhysicalKeyboardKey.digit0,
0x00000028: PhysicalKeyboardKey.enter,
0x00000029: PhysicalKeyboardKey.escape,
0x0000002a: PhysicalKeyboardKey.backspace,
0x0000002b: PhysicalKeyboardKey.tab,
0x0000002c: PhysicalKeyboardKey.space,
0x0000002d: PhysicalKeyboardKey.minus,
0x0000002e: PhysicalKeyboardKey.equal,
0x0000002f: PhysicalKeyboardKey.bracketLeft,
0x00000030: PhysicalKeyboardKey.bracketRight,
0x00000031: PhysicalKeyboardKey.backslash,
0x00000033: PhysicalKeyboardKey.semicolon,
0x00000034: PhysicalKeyboardKey.quote,
0x00000035: PhysicalKeyboardKey.backquote,
0x00000036: PhysicalKeyboardKey.comma,
0x00000037: PhysicalKeyboardKey.period,
0x00000038: PhysicalKeyboardKey.slash,
0x00000039: PhysicalKeyboardKey.capsLock,
0x0000003a: PhysicalKeyboardKey.f1,
0x0000003b: PhysicalKeyboardKey.f2,
0x0000003c: PhysicalKeyboardKey.f3,
0x0000003d: PhysicalKeyboardKey.f4,
0x0000003e: PhysicalKeyboardKey.f5,
0x0000003f: PhysicalKeyboardKey.f6,
0x00000040: PhysicalKeyboardKey.f7,
0x00000041: PhysicalKeyboardKey.f8,
0x00000042: PhysicalKeyboardKey.f9,
0x00000043: PhysicalKeyboardKey.f10,
0x00000044: PhysicalKeyboardKey.f11,
0x00000045: PhysicalKeyboardKey.f12,
0x00000046: PhysicalKeyboardKey.printScreen,
0x00000047: PhysicalKeyboardKey.scrollLock,
0x00000048: PhysicalKeyboardKey.pause,
0x00000049: PhysicalKeyboardKey.insert,
0x0000004a: PhysicalKeyboardKey.home,
0x0000004b: PhysicalKeyboardKey.pageUp,
0x0000004c: PhysicalKeyboardKey.delete,
0x0000004d: PhysicalKeyboardKey.end,
0x0000004e: PhysicalKeyboardKey.pageDown,
0x0000004f: PhysicalKeyboardKey.arrowRight,
0x00000050: PhysicalKeyboardKey.arrowLeft,
0x00000051: PhysicalKeyboardKey.arrowDown,
0x00000052: PhysicalKeyboardKey.arrowUp,
0x00000053: PhysicalKeyboardKey.numLock,
0x00000054: PhysicalKeyboardKey.numpadDivide,
0x00000055: PhysicalKeyboardKey.numpadMultiply,
0x00000056: PhysicalKeyboardKey.numpadSubtract,
0x00000057: PhysicalKeyboardKey.numpadAdd,
0x00000058: PhysicalKeyboardKey.numpadEnter,
0x00000059: PhysicalKeyboardKey.numpad1,
0x0000005a: PhysicalKeyboardKey.numpad2,
0x0000005b: PhysicalKeyboardKey.numpad3,
0x0000005c: PhysicalKeyboardKey.numpad4,
0x0000005d: PhysicalKeyboardKey.numpad5,
0x0000005e: PhysicalKeyboardKey.numpad6,
0x0000005f: PhysicalKeyboardKey.numpad7,
0x00000060: PhysicalKeyboardKey.numpad8,
0x00000061: PhysicalKeyboardKey.numpad9,
0x00000062: PhysicalKeyboardKey.numpad0,
0x00000063: PhysicalKeyboardKey.numpadDecimal,
0x00000064: PhysicalKeyboardKey.intlBackslash,
0x00000065: PhysicalKeyboardKey.contextMenu,
0x00000066: PhysicalKeyboardKey.power,
0x00000067: PhysicalKeyboardKey.numpadEqual,
0x00000068: PhysicalKeyboardKey.f13,
0x00000069: PhysicalKeyboardKey.f14,
0x0000006a: PhysicalKeyboardKey.f15,
0x0000006b: PhysicalKeyboardKey.f16,
0x0000006c: PhysicalKeyboardKey.f17,
0x0000006d: PhysicalKeyboardKey.f18,
0x0000006e: PhysicalKeyboardKey.f19,
0x0000006f: PhysicalKeyboardKey.f20,
0x00000070: PhysicalKeyboardKey.f21,
0x00000071: PhysicalKeyboardKey.f22,
0x00000072: PhysicalKeyboardKey.f23,
0x00000073: PhysicalKeyboardKey.f24,
0x00000074: PhysicalKeyboardKey.open,
0x00000075: PhysicalKeyboardKey.help,
0x00000077: PhysicalKeyboardKey.select,
0x00000079: PhysicalKeyboardKey.again,
0x0000007a: PhysicalKeyboardKey.undo,
0x0000007b: PhysicalKeyboardKey.cut,
0x0000007c: PhysicalKeyboardKey.copy,
0x0000007d: PhysicalKeyboardKey.paste,
0x0000007e: PhysicalKeyboardKey.find,
0x0000007f: PhysicalKeyboardKey.audioVolumeMute,
0x00000080: PhysicalKeyboardKey.audioVolumeUp,
0x00000081: PhysicalKeyboardKey.audioVolumeDown,
0x00000085: PhysicalKeyboardKey.numpadComma,
0x00000087: PhysicalKeyboardKey.intlRo,
0x00000088: PhysicalKeyboardKey.kanaMode,
0x00000089: PhysicalKeyboardKey.intlYen,
0x0000008a: PhysicalKeyboardKey.convert,
0x0000008b: PhysicalKeyboardKey.nonConvert,
0x00000090: PhysicalKeyboardKey.lang1,
0x00000091: PhysicalKeyboardKey.lang2,
0x00000092: PhysicalKeyboardKey.lang3,
0x00000093: PhysicalKeyboardKey.lang4,
0x00000094: PhysicalKeyboardKey.lang5,
0x0000009b: PhysicalKeyboardKey.abort,
0x000000a3: PhysicalKeyboardKey.props,
0x000000b6: PhysicalKeyboardKey.numpadParenLeft,
0x000000b7: PhysicalKeyboardKey.numpadParenRight,
0x000000bb: PhysicalKeyboardKey.numpadBackspace,
0x000000d0: PhysicalKeyboardKey.numpadMemoryStore,
0x000000d1: PhysicalKeyboardKey.numpadMemoryRecall,
0x000000d2: PhysicalKeyboardKey.numpadMemoryClear,
0x000000d3: PhysicalKeyboardKey.numpadMemoryAdd,
0x000000d4: PhysicalKeyboardKey.numpadMemorySubtract,
0x000000d7: PhysicalKeyboardKey.numpadSignChange,
0x000000d8: PhysicalKeyboardKey.numpadClear,
0x000000d9: PhysicalKeyboardKey.numpadClearEntry,
0x000000e0: PhysicalKeyboardKey.controlLeft,
0x000000e1: PhysicalKeyboardKey.shiftLeft,
0x000000e2: PhysicalKeyboardKey.altLeft,
0x000000e3: PhysicalKeyboardKey.metaLeft,
0x000000e4: PhysicalKeyboardKey.controlRight,
0x000000e5: PhysicalKeyboardKey.shiftRight,
0x000000e6: PhysicalKeyboardKey.altRight,
0x000000e7: PhysicalKeyboardKey.metaRight,
};
/// A map of iOS 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<int, LogicalKeyboardKey> kIosNumPadMap = <int, LogicalKeyboardKey>{
0x00000054: LogicalKeyboardKey.numpadDivide,
0x00000055: LogicalKeyboardKey.numpadMultiply,
0x00000056: LogicalKeyboardKey.numpadSubtract,
0x00000057: LogicalKeyboardKey.numpadAdd,
0x00000059: LogicalKeyboardKey.numpad1,
0x0000005a: LogicalKeyboardKey.numpad2,
0x0000005b: LogicalKeyboardKey.numpad3,
0x0000005c: LogicalKeyboardKey.numpad4,
0x0000005d: LogicalKeyboardKey.numpad5,
0x0000005e: LogicalKeyboardKey.numpad6,
0x0000005f: LogicalKeyboardKey.numpad7,
0x00000060: LogicalKeyboardKey.numpad8,
0x00000061: LogicalKeyboardKey.numpad9,
0x00000062: LogicalKeyboardKey.numpad0,
0x00000063: LogicalKeyboardKey.numpadDecimal,
0x00000067: LogicalKeyboardKey.numpadEqual,
0x00000085: LogicalKeyboardKey.numpadComma,
0x000000b6: LogicalKeyboardKey.numpadParenLeft,
0x000000b7: LogicalKeyboardKey.numpadParenRight,
};
/// Maps GLFW-specific key codes to the matching [LogicalKeyboardKey].
const Map<int, LogicalKeyboardKey> kGlfwToLogicalKey = <int, LogicalKeyboardKey>{
65: LogicalKeyboardKey.keyA,
......
......@@ -10,6 +10,7 @@ import 'package:flutter/foundation.dart';
import 'keyboard_key.dart';
import 'raw_keyboard_android.dart';
import 'raw_keyboard_fuchsia.dart';
import 'raw_keyboard_ios.dart';
import 'raw_keyboard_linux.dart';
import 'raw_keyboard_macos.dart';
import 'raw_keyboard_web.dart';
......@@ -306,6 +307,13 @@ abstract class RawKeyEvent with Diagnosticable {
modifiers: message['modifiers'] as int? ?? 0);
character = message['characters'] as String?;
break;
case 'ios':
data = RawKeyEventDataIos(
characters: message['characters'] as String? ?? '',
charactersIgnoringModifiers: message['charactersIgnoringModifiers'] as String? ?? '',
keyCode: message['keyCode'] as int? ?? 0,
modifiers: message['modifiers'] as int? ?? 0);
break;
case 'linux':
final int unicodeScalarValues = message['unicodeScalarValues'] as int? ?? 0;
data = RawKeyEventDataLinux(
......@@ -340,9 +348,10 @@ abstract class RawKeyEvent with Diagnosticable {
}
break;
default:
// Raw key events are not yet implemented on iOS or other platforms,
// but this exception isn't hit, because the engine never sends these
// messages.
/// This exception would only be hit on platforms that haven't yet
/// implemented raw key events, but will only be triggered if the
/// engine for those platforms sends raw key event messages in the
/// first place.
throw FlutterError('Unknown keymap for key events: $keymap');
}
......
// 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.
import 'package:flutter/foundation.dart';
import 'keyboard_key.dart';
import 'keyboard_maps.dart';
import 'raw_keyboard.dart';
/// Maps iOS specific string values of nonvisible keys to logical keys
///
/// See: https://developer.apple.com/documentation/uikit/uikeycommand/input_strings_for_special_keys?language=objc
const Map<String, LogicalKeyboardKey> _kIosToLogicalMap = <String, LogicalKeyboardKey>{
'UIKeyInputEscape': LogicalKeyboardKey.escape,
'UIKeyInputF1': LogicalKeyboardKey.f1,
'UIKeyInputF2': LogicalKeyboardKey.f2,
'UIKeyInputF3': LogicalKeyboardKey.f3,
'UIKeyInputF4': LogicalKeyboardKey.f4,
'UIKeyInputF5': LogicalKeyboardKey.f5,
'UIKeyInputF6': LogicalKeyboardKey.f6,
'UIKeyInputF7': LogicalKeyboardKey.f7,
'UIKeyInputF8': LogicalKeyboardKey.f8,
'UIKeyInputF9': LogicalKeyboardKey.f9,
'UIKeyInputF10': LogicalKeyboardKey.f10,
'UIKeyInputF11': LogicalKeyboardKey.f11,
'UIKeyInputF12': LogicalKeyboardKey.f12,
'UIKeyInputUpArrow': LogicalKeyboardKey.arrowUp,
'UIKeyInputDownArrow': LogicalKeyboardKey.arrowDown,
'UIKeyInputLeftArrow': LogicalKeyboardKey.arrowLeft,
'UIKeyInputRightArrow': LogicalKeyboardKey.arrowRight,
'UIKeyInputHome': LogicalKeyboardKey.home,
'UIKeyInputEnd': LogicalKeyboardKey.enter,
'UIKeyInputPageUp': LogicalKeyboardKey.pageUp,
'UIKeyInputPageDown': LogicalKeyboardKey.pageDown
};
/// Platform-specific key event data for iOS.
///
/// This object contains information about key events obtained from iOS'
/// `UIKey` interface.
///
/// See also:
///
/// * [RawKeyboard], which uses this interface to expose key data.
class RawKeyEventDataIos extends RawKeyEventData {
/// Creates a key event data structure specific for iOS.
///
/// The [characters], [charactersIgnoringModifiers], and [modifiers], arguments
/// must not be null.
const RawKeyEventDataIos({
this.characters = '',
this.charactersIgnoringModifiers = '',
this.keyCode = 0,
this.modifiers = 0,
}) : assert(characters != null),
assert(charactersIgnoringModifiers != null),
assert(keyCode != null),
assert(modifiers != null);
/// The Unicode characters associated with a key-up or key-down event.
///
/// See also:
///
/// * [Apple's UIKey documentation](https://developer.apple.com/documentation/uikit/uikey/3526130-characters?language=objc)
final String characters;
/// The characters generated by a key event as if no modifier key (except for
/// Shift) applies.
///
/// See also:
///
/// * [Apple's UIKey documentation](https://developer.apple.com/documentation/uikit/uikey/3526131-charactersignoringmodifiers?language=objc)
final String charactersIgnoringModifiers;
/// The virtual key code for the keyboard key associated with a key event.
///
/// See also:
///
/// * [Apple's UIKey documentation](https://developer.apple.com/documentation/uikit/uikey/3526132-keycode?language=objc)
final int keyCode;
/// A mask of the current modifiers using the values in Modifier Flags.
///
/// See also:
///
/// * [Apple's UIKey documentation](https://developer.apple.com/documentation/uikit/uikey/3526133-modifierflags?language=objc)
final int modifiers;
@override
String get keyLabel => charactersIgnoringModifiers;
@override
PhysicalKeyboardKey get physicalKey => kIosToPhysicalKey[keyCode] ?? PhysicalKeyboardKey.none;
@override
LogicalKeyboardKey get logicalKey {
// Look to see if the keyCode is a printable number pad key, so that a
// difference between regular keys (e.g. "=") and the number pad version
// (e.g. the "=" on the number pad) can be determined.
final LogicalKeyboardKey? numPadKey = kIosNumPadMap[keyCode];
if (numPadKey != null) {
return numPadKey;
}
// Look to see if the [keyLabel] is one we know about and have a mapping for.
final LogicalKeyboardKey? newKey = _kIosToLogicalMap[keyLabel];
if (newKey != null) {
return newKey;
}
// If this key is printable, generate the LogicalKeyboardKey from its
// Unicode value. Control keys such as ESC, CRTL, and SHIFT are not
// printable. HOME, DEL, arrow keys, and function keys are considered
// modifier function keys, which generate invalid Unicode scalar values.
if (keyLabel.isNotEmpty &&
!LogicalKeyboardKey.isControlCharacter(keyLabel)) {
// Given that charactersIgnoringModifiers can contain a String of
// arbitrary length, limit to a maximum of two Unicode scalar values. It
// is unlikely that a keyboard would produce a code point bigger than 32
// bits, but it is still worth defending against this case.
assert(charactersIgnoringModifiers.length <= 2);
int codeUnit = charactersIgnoringModifiers.codeUnitAt(0);
if (charactersIgnoringModifiers.length == 2) {
final int secondCode = charactersIgnoringModifiers.codeUnitAt(1);
codeUnit = (codeUnit << 16) | secondCode;
}
final int keyId = LogicalKeyboardKey.unicodePlane | (codeUnit & LogicalKeyboardKey.valueMask);
return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey(
keyId,
keyLabel: keyLabel,
debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}',
);
}
// Control keys like "backspace" and movement keys like arrow keys don't
// have a printable representation, but are present on the physical
// keyboard. Since there is no logical keycode map for iOS (iOS uses the
// keycode to reference physical keys), a LogicalKeyboardKey is created with
// the physical key's HID usage and debugName. This avoids duplicating the
// physical key map.
if (physicalKey != PhysicalKeyboardKey.none) {
final int keyId = physicalKey.usbHidUsage | LogicalKeyboardKey.hidPlane;
return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey(
keyId,
keyLabel: physicalKey.debugName ?? '',
debugName: physicalKey.debugName,
);
}
// This is a non-printable key that is unrecognized, so a new code is minted
// with the autogenerated bit set.
const int iosKeyIdPlane = 0x00400000000;
return LogicalKeyboardKey(
iosKeyIdPlane | keyCode | LogicalKeyboardKey.autogeneratedMask,
debugName: kReleaseMode ? null : 'Unknown iOS key code $keyCode',
);
}
bool _isLeftRightModifierPressed(KeyboardSide side, int anyMask, int leftMask, int rightMask) {
if (modifiers & anyMask == 0) {
return false;
}
// If only the "anyMask" bit is set, then we respond true for requests of
// whether either left or right is pressed. Handles the case where iOS
// supplies just the "either" modifier flag, but not the left/right flag.
// (e.g. modifierShift but not modifierLeftShift).
final bool anyOnly = modifiers & (leftMask | rightMask | anyMask) == anyMask;
switch (side) {
case KeyboardSide.any:
return true;
case KeyboardSide.all:
return modifiers & leftMask != 0 && modifiers & rightMask != 0 || anyOnly;
case KeyboardSide.left:
return modifiers & leftMask != 0 || anyOnly;
case KeyboardSide.right:
return modifiers & rightMask != 0 || anyOnly;
}
}
@override
bool isModifierPressed(ModifierKey key, {KeyboardSide side = KeyboardSide.any}) {
final int independentModifier = modifiers & deviceIndependentMask;
bool result;
switch (key) {
case ModifierKey.controlModifier:
result = _isLeftRightModifierPressed(side, independentModifier & modifierControl, modifierLeftControl, modifierRightControl);
break;
case ModifierKey.shiftModifier:
result = _isLeftRightModifierPressed(side, independentModifier & modifierShift, modifierLeftShift, modifierRightShift);
break;
case ModifierKey.altModifier:
result = _isLeftRightModifierPressed(side, independentModifier & modifierOption, modifierLeftOption, modifierRightOption);
break;
case ModifierKey.metaModifier:
result = _isLeftRightModifierPressed(side, independentModifier & modifierCommand, modifierLeftCommand, modifierRightCommand);
break;
case ModifierKey.capsLockModifier:
result = independentModifier & modifierCapsLock != 0;
break;
// On iOS, the function modifier bit is set for any function key, like F1,
// F2, etc., but the meaning of ModifierKey.modifierFunction in Flutter is
// that of the Fn modifier key, so there's no good way to emulate that on
// iOS.
case ModifierKey.functionModifier:
case ModifierKey.numLockModifier:
case ModifierKey.symbolModifier:
case ModifierKey.scrollLockModifier:
// These modifier masks are not used in iOS keyboards.
result = false;
break;
}
assert(!result || getModifierSide(key) != null, "$runtimeType thinks that a modifier is pressed, but can't figure out what side it's on.");
return result;
}
@override
KeyboardSide? getModifierSide(ModifierKey key) {
KeyboardSide? findSide(int anyMask, int leftMask, int rightMask) {
final int combinedMask = leftMask | rightMask;
final int combined = modifiers & combinedMask;
if (combined == leftMask) {
return KeyboardSide.left;
} else if (combined == rightMask) {
return KeyboardSide.right;
} else if (combined == combinedMask || modifiers & (combinedMask | anyMask) == anyMask) {
// Handles the case where iOS supplies just the "either" modifier
// flag, but not the left/right flag. (e.g. modifierShift but not
// modifierLeftShift), or if left and right flags are provided, but not
// the "either" modifier flag.
return KeyboardSide.all;
}
return null;
}
switch (key) {
case ModifierKey.controlModifier:
return findSide(modifierControl, modifierLeftControl, modifierRightControl);
case ModifierKey.shiftModifier:
return findSide(modifierShift, modifierLeftShift, modifierRightShift);
case ModifierKey.altModifier:
return findSide(modifierOption, modifierLeftOption, modifierRightOption);
case ModifierKey.metaModifier:
return findSide(modifierCommand, modifierLeftCommand, modifierRightCommand);
case ModifierKey.capsLockModifier:
case ModifierKey.numLockModifier:
case ModifierKey.scrollLockModifier:
case ModifierKey.functionModifier:
case ModifierKey.symbolModifier:
return KeyboardSide.all;
}
}
// Modifier key masks. See Apple's UIKey documentation
// https://developer.apple.com/documentation/uikit/uikeymodifierflags?language=objc
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-86/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h.auto.html
/// This mask is used to check the [modifiers] field to test whether the CAPS
/// LOCK modifier key is on.
///
/// {@template flutter.services.rawKeyEventDataIOS.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.
/// {@endtemplate}
static const int modifierCapsLock = 0x10000;
/// This mask is used to check the [modifiers] field to test whether one of the
/// SHIFT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierShift = 0x20000;
/// This mask is used to check the [modifiers] field to test whether the left
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierLeftShift = 0x02;
/// This mask is used to check the [modifiers] field to test whether the right
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierRightShift = 0x04;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CTRL modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierControl = 0x40000;
/// This mask is used to check the [modifiers] field to test whether the left
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierLeftControl = 0x01;
/// This mask is used to check the [modifiers] field to test whether the right
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierRightControl = 0x2000;
/// This mask is used to check the [modifiers] field to test whether one of the
/// ALT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierOption = 0x80000;
/// This mask is used to check the [modifiers] field to test whether the left
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierLeftOption = 0x20;
/// This mask is used to check the [modifiers] field to test whether the right
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierRightOption = 0x40;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierCommand = 0x100000;
/// This mask is used to check the [modifiers] field to test whether the left
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierLeftCommand = 0x08;
/// This mask is used to check the [modifiers] field to test whether the right
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierRightCommand = 0x10;
/// This mask is used to check the [modifiers] field to test whether any key in
/// the numeric keypad is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierNumericPad = 0x200000;
/// This mask is used to check the [modifiers] field to test whether the
/// HELP modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierHelp = 0x400000;
/// This mask is used to check the [modifiers] field to test whether one of the
/// FUNCTION modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataIOS.modifiers}
static const int modifierFunction = 0x800000;
/// Used to retrieve only the device-independent modifier flags, allowing
/// applications to mask off the device-dependent modifier flags, including
/// event coalescing information.
static const int deviceIndependentMask = 0xffff0000;
@override
String toString() {
return '${objectRuntimeType(this, 'RawKeyEventDataIos')}(keyLabel: $keyLabel, keyCode: $keyCode, characters: $characters,'
' unmodifiedCharacters: $charactersIgnoringModifiers, modifiers: $modifiers, '
'modifiers down: $modifiersPressed)';
}
}
......@@ -41,7 +41,7 @@ void main() {
}
});
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
RawKeyboard.instance.clearKeysPressed();
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
......@@ -110,7 +110,7 @@ void main() {
await simulateKeyUpEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
// The Fn key isn't mapped on linux or Windows.
if (platform != 'linux' && platform != 'windows') {
if (platform != 'linux' && platform != 'windows' && platform != 'ios') {
await simulateKeyDownEvent(LogicalKeyboardKey.fn, platform: platform);
expect(
RawKeyboard.instance.keysPressed,
......@@ -146,7 +146,7 @@ void main() {
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021
testWidgets('keysPressed is correct when modifier is released before key', (WidgetTester tester) async {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows', 'ios']) {
RawKeyboard.instance.clearKeysPressed();
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform, physicalKey: PhysicalKeyboardKey.shiftLeft);
......@@ -221,6 +221,31 @@ void main() {
);
});
testWidgets('keysPressed modifiers are synchronized with key events on iOS', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
final Map<String, dynamic> data = KeyEventSimulator.getKeyData(
LogicalKeyboardKey.keyA,
platform: 'ios',
isDown: true,
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
// dispatch the modified data.
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
SystemChannels.keyEvent.codec.encodeMessage(data),
(ByteData? data) {},
);
expect(
RawKeyboard.instance.keysPressed,
equals(
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
),
);
});
testWidgets('keysPressed modifiers are synchronized with key events on Windows', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
......@@ -403,6 +428,44 @@ void main() {
);
});
testWidgets('sided modifiers without a side set return all sides on iOS', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
final Map<String, dynamic> data = KeyEventSimulator.getKeyData(
LogicalKeyboardKey.keyA,
platform: 'ios',
isDown: true,
);
// Set only the generic "shift down" modifier, without setting a side.
data['modifiers'] |=
RawKeyEventDataIos.modifierShift |
RawKeyEventDataIos.modifierOption |
RawKeyEventDataIos.modifierCommand |
RawKeyEventDataIos.modifierControl;
// dispatch the modified data.
await ServicesBinding.instance?.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
SystemChannels.keyEvent.codec.encodeMessage(data),
(ByteData? data) {},
);
expect(
RawKeyboard.instance.keysPressed,
equals(
<LogicalKeyboardKey>{
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
LogicalKeyboardKey.altLeft,
LogicalKeyboardKey.altRight,
LogicalKeyboardKey.controlLeft,
LogicalKeyboardKey.controlRight,
LogicalKeyboardKey.metaLeft,
LogicalKeyboardKey.metaRight,
LogicalKeyboardKey.keyA,
},
),
);
});
testWidgets('sided modifiers without a side set return all sides on Windows', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
......@@ -946,7 +1009,6 @@ void main() {
'type': 'keydown',
'keymap': 'macos',
'keyCode': 0x04,
'plainCodePoint': 0x64,
'characters': 'a',
'charactersIgnoringModifiers': 'a',
'modifiers': modifier | RawKeyEventDataMacOs.modifierCapsLock,
......@@ -1037,6 +1099,152 @@ void main() {
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
});
group('RawKeyEventDataIos', () {
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
RawKeyEventDataIos.modifierOption | RawKeyEventDataIos.modifierLeftOption: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.left),
RawKeyEventDataIos.modifierOption | RawKeyEventDataIos.modifierRightOption: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.right),
RawKeyEventDataIos.modifierShift | RawKeyEventDataIos.modifierLeftShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.left),
RawKeyEventDataIos.modifierShift | RawKeyEventDataIos.modifierRightShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.right),
RawKeyEventDataIos.modifierControl | RawKeyEventDataIos.modifierLeftControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.left),
RawKeyEventDataIos.modifierControl | RawKeyEventDataIos.modifierRightControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.right),
RawKeyEventDataIos.modifierCommand | RawKeyEventDataIos.modifierLeftCommand: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.left),
RawKeyEventDataIos.modifierCommand | RawKeyEventDataIos.modifierRightCommand: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.right),
RawKeyEventDataIos.modifierOption: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.all),
RawKeyEventDataIos.modifierShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.all),
RawKeyEventDataIos.modifierControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.all),
RawKeyEventDataIos.modifierCommand: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.all),
RawKeyEventDataIos.modifierCapsLock: _ModifierCheck(ModifierKey.capsLockModifier, KeyboardSide.all),
};
test('modifier keys are recognized individually', () {
for (final int modifier in modifierTests.keys) {
final RawKeyEvent event = RawKeyEvent.fromMessage(<String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x04,
'characters': 'a',
'charactersIgnoringModifiers': 'a',
'modifiers': modifier,
});
final RawKeyEventDataIos data = event.data as RawKeyEventDataIos;
for (final ModifierKey key in ModifierKey.values) {
if (modifierTests[modifier]!.key == key) {
expect(
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
isTrue,
reason: "$key should be pressed with metaState $modifier, but isn't.",
);
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
} else {
expect(
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
isFalse,
reason: '$key should not be pressed with metaState $modifier.',
);
}
}
}
});
test('modifier keys are recognized when combined', () {
for (final int modifier in modifierTests.keys) {
if (modifier == RawKeyEventDataIos.modifierCapsLock) {
// No need to combine caps lock key with itself.
continue;
}
final RawKeyEvent event = RawKeyEvent.fromMessage(<String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x04,
'characters': 'a',
'charactersIgnoringModifiers': 'a',
'modifiers': modifier | RawKeyEventDataIos.modifierCapsLock,
});
final RawKeyEventDataIos data = event.data as RawKeyEventDataIos;
for (final ModifierKey key in ModifierKey.values) {
if (modifierTests[modifier]!.key == key || key == ModifierKey.capsLockModifier) {
expect(
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
isTrue,
reason: '$key should be pressed with metaState $modifier '
"and additional key ${RawKeyEventDataIos.modifierCapsLock}, but isn't.",
);
if (key != ModifierKey.capsLockModifier) {
expect(data.getModifierSide(key), equals(modifierTests[modifier]!.side));
} else {
expect(data.getModifierSide(key), equals(KeyboardSide.all));
}
} else {
expect(
data.isModifierPressed(key, side: modifierTests[modifier]!.side),
isFalse,
reason: '$key should not be pressed with metaState $modifier '
'and additional key ${RawKeyEventDataIos.modifierCapsLock}.',
);
}
}
}
});
test('Printable keyboard keys are correctly translated', () {
const String unmodifiedCharacter = 'a';
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x00000004,
'characters': 'a',
'charactersIgnoringModifiers': unmodifiedCharacter,
'modifiers': 0x0,
});
final RawKeyEventDataIos data = keyAEvent.data as RawKeyEventDataIos;
expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA));
expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
expect(data.keyLabel, equals('a'));
});
test('Control keyboard keys are correctly translated', () {
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x00000029,
'characters': '',
'charactersIgnoringModifiers': '',
'modifiers': 0x0,
});
final RawKeyEventDataIos data = escapeKeyEvent.data as RawKeyEventDataIos;
expect(data.physicalKey, equals(PhysicalKeyboardKey.escape));
expect(data.logicalKey, equals(LogicalKeyboardKey.escape));
expect(data.keyLabel, isEmpty);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
test('Modifier keyboard keys are correctly translated', () {
final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x000000e1,
'characters': '',
'charactersIgnoringModifiers': '',
'modifiers': RawKeyEventDataIos.modifierLeftShift,
});
final RawKeyEventDataIos data = shiftLeftKeyEvent.data as RawKeyEventDataIos;
expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
expect(data.keyLabel, isEmpty);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
test('Unprintable keyboard keys are correctly translated', () {
final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'ios',
'keyCode': 0x00000050,
'characters': '',
'charactersIgnoringModifiers': 'UIKeyInputLeftArrow',
'modifiers': RawKeyEventDataIos.modifierFunction,
});
final RawKeyEventDataIos data = leftArrowKey.data as RawKeyEventDataIos;
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
expect(data.logicalKey.keyLabel, isEmpty);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
});
group('RawKeyEventDataWindows', () {
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
RawKeyEventDataWindows.modifierLeftAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.left),
......
......@@ -39,6 +39,7 @@ class KeyEventSimulator {
case 'macos':
case 'linux':
case 'web':
case 'ios':
case 'windows':
return true;
}
......@@ -58,6 +59,9 @@ class KeyEventSimulator {
case 'macos':
map = kMacOsToPhysicalKey;
break;
case 'ios':
map = kIosToPhysicalKey;
break;
case 'linux':
map = kLinuxToPhysicalKey;
break;
......@@ -90,7 +94,10 @@ class KeyEventSimulator {
map = kFuchsiaToLogicalKey;
break;
case 'macos':
// macOS doesn't do key codes, just scan codes.
// macOS doesn't do key codes, just scan codes.
return -1;
case 'ios':
// iOS doesn't do key codes, just scan codes.
return -1;
case 'web':
// web doesn't have int type code
......@@ -137,6 +144,9 @@ class KeyEventSimulator {
case 'macos':
map = kMacOsToPhysicalKey;
break;
case 'ios':
map = kIosToPhysicalKey;
break;
case 'linux':
map = kLinuxToPhysicalKey;
break;
......@@ -213,6 +223,12 @@ class KeyEventSimulator {
}
result['modifiers'] = _getMacOsModifierFlags(key, isDown);
break;
case 'ios':
result['keyCode'] = scanCode;
result['characters'] = key.keyLabel;
result['charactersIgnoringModifiers'] = key.keyLabel;
result['modifiers'] = _getIOSModifierFlags(key, isDown);
break;
case 'web':
result['code'] = _getWebKeyCode(key);
result['key'] = key.keyLabel;
......@@ -504,6 +520,73 @@ class KeyEventSimulator {
return result;
}
static int _getIOSModifierFlags(LogicalKeyboardKey newKey, bool isDown) {
int result = 0;
final Set<LogicalKeyboardKey> pressed = RawKeyboard.instance.keysPressed;
if (isDown) {
pressed.add(newKey);
} else {
pressed.remove(newKey);
}
if (pressed.contains(LogicalKeyboardKey.shiftLeft)) {
result |= RawKeyEventDataIos.modifierLeftShift | RawKeyEventDataIos.modifierShift;
}
if (pressed.contains(LogicalKeyboardKey.shiftRight)) {
result |= RawKeyEventDataIos.modifierRightShift | RawKeyEventDataIos.modifierShift;
}
if (pressed.contains(LogicalKeyboardKey.metaLeft)) {
result |= RawKeyEventDataIos.modifierLeftCommand | RawKeyEventDataIos.modifierCommand;
}
if (pressed.contains(LogicalKeyboardKey.metaRight)) {
result |= RawKeyEventDataIos.modifierRightCommand | RawKeyEventDataIos.modifierCommand;
}
if (pressed.contains(LogicalKeyboardKey.controlLeft)) {
result |= RawKeyEventDataIos.modifierLeftControl | RawKeyEventDataIos.modifierControl;
}
if (pressed.contains(LogicalKeyboardKey.controlRight)) {
result |= RawKeyEventDataIos.modifierRightControl | RawKeyEventDataIos.modifierControl;
}
if (pressed.contains(LogicalKeyboardKey.altLeft)) {
result |= RawKeyEventDataIos.modifierLeftOption | RawKeyEventDataIos.modifierOption;
}
if (pressed.contains(LogicalKeyboardKey.altRight)) {
result |= RawKeyEventDataIos.modifierRightOption | RawKeyEventDataIos.modifierOption;
}
final Set<LogicalKeyboardKey> functionKeys = <LogicalKeyboardKey>{
LogicalKeyboardKey.f1,
LogicalKeyboardKey.f2,
LogicalKeyboardKey.f3,
LogicalKeyboardKey.f4,
LogicalKeyboardKey.f5,
LogicalKeyboardKey.f6,
LogicalKeyboardKey.f7,
LogicalKeyboardKey.f8,
LogicalKeyboardKey.f9,
LogicalKeyboardKey.f10,
LogicalKeyboardKey.f11,
LogicalKeyboardKey.f12,
LogicalKeyboardKey.f13,
LogicalKeyboardKey.f14,
LogicalKeyboardKey.f15,
LogicalKeyboardKey.f16,
LogicalKeyboardKey.f17,
LogicalKeyboardKey.f18,
LogicalKeyboardKey.f19,
LogicalKeyboardKey.f20,
LogicalKeyboardKey.f21,
};
if (pressed.intersection(functionKeys).isNotEmpty) {
result |= RawKeyEventDataIos.modifierFunction;
}
if (pressed.intersection(kMacOsNumPadMap.values.toSet()).isNotEmpty) {
result |= RawKeyEventDataIos.modifierNumericPad;
}
if (pressed.contains(LogicalKeyboardKey.capsLock)) {
result |= RawKeyEventDataIos.modifierCapsLock;
}
return result;
}
/// Simulates sending a hardware key down event through the system channel.
///
/// This only simulates key presses coming from a physical keyboard, not from a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment