Skip to content

Commit 0ac05f1

Browse files
authored
[Keyboard, Web] Map from "Esc" to the Escape key (#106133)
* Impl * Fix build * Add test
1 parent df55dbb commit 0ac05f1

13 files changed

+125
-51
lines changed

dev/tools/gen_keycodes/data/logical_key_data.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,8 @@
15521552
"value": 4294967323,
15531553
"names": {
15541554
"web": [
1555-
"Escape"
1555+
"Escape",
1556+
"Esc"
15561557
],
15571558
"macos": [
15581559
"Escape"

dev/tools/gen_keycodes/data/physical_key_data.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,9 @@
11921192
"name": "Escape",
11931193
"chromium": "Escape"
11941194
},
1195+
"otherWebCodes": [
1196+
"Esc"
1197+
],
11951198
"scanCodes": {
11961199
"android": [
11971200
1

dev/tools/gen_keycodes/data/supplemental_hid_codes.inc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@
5050
DOM_CODE(0x05ff1e, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonY", BUTTON_Y),
5151
DOM_CODE(0x05ff1f, 0x0000, 0x0000, 0x0000, 0xffff, "GameButtonZ", BUTTON_Z),
5252

53+
// Sometimes the Escape key produces "Esc" instead of "Escape". This includes
54+
// older IE and Firefox browsers, and the current Cobalt browser.
55+
// See: https://github.com/flutter/flutter/issues/106062
56+
DOM_CODE(0x070029, 0x0000, 0x0000, 0x0000, 0xffff, "Esc", ESCAPE),
57+
5358
// ============================================================
5459
// Fn key for Mac
5560
// ============================================================
@@ -58,4 +63,4 @@
5863
// defined on other platforms. Chromium does define an "Fn" row, but doesn't
5964
// give it a Mac keycode. This overrides their definition.
6065
// USB HID evdev XKB Win Mac DOMKey Code
61-
DOM_CODE(0x000012, 0x0000, 0x0000, 0x0000, 0x003f, "Fn", FN),
66+
DOM_CODE(0x000012, 0x0000, 0x0000, 0x0000, 0x003f, "Fn", FN),

dev/tools/gen_keycodes/data/supplemental_key_data.inc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@
7676
DOM_KEY_UNI("Tilde", TILDE, '~'),
7777
DOM_KEY_UNI("Bar", BAR, '|'),
7878

79+
// ============================================================
80+
// Unprintable keys (Unicode plane)
81+
// ============================================================
82+
83+
// Key Enum Value
84+
// Sometimes the Escape key produces "Esc" instead of "Escape". This includes
85+
// older IE and Firefox browsers, and the current Cobalt browser.
86+
// See: https://github.com/flutter/flutter/issues/106062
87+
DOM_KEY_MAP("Esc", ESC, 0x1B),
88+
7989
// The following keys reside in the Flutter plane (0x0100000000).
8090

8191
// ============================================================

dev/tools/gen_keycodes/lib/keyboard_keys_code_gen.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ $otherComments static const PhysicalKeyboardKey ${entry.constantName} = Physica
7878

7979
/// Gets the generated definitions of LogicalKeyboardKeys.
8080
String get _logicalDefinitions {
81-
final OutputLines<int> lines = OutputLines<int>('Logical debug names');
81+
final OutputLines<int> lines = OutputLines<int>('Logical debug names', behavior: DeduplicateBehavior.kSkip);
8282
void printKey(int flutterId, String constantName, String commentName, {String? otherComments}) {
8383
final String firstComment = _wrapString('Represents the logical "$commentName" key on the keyboard.');
8484
otherComments ??= _wrapString('See the function [RawKeyEvent.logicalKey] for more information.');
@@ -122,7 +122,7 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK
122122
}
123123

124124
String get _logicalKeyLabels {
125-
final OutputLines<int> lines = OutputLines<int>('Logical key labels');
125+
final OutputLines<int> lines = OutputLines<int>('Logical key labels', behavior: DeduplicateBehavior.kSkip);
126126
for (final LogicalKeyEntry entry in logicalData.entries) {
127127
lines.add(entry.value, '''
128128
${toHex(entry.value, digits: 11)}: '${entry.commentName}',''');
@@ -141,15 +141,15 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK
141141

142142
/// This generates the map of Flutter key codes to logical keys.
143143
String get _predefinedKeyCodeMap {
144-
final OutputLines<int> lines = OutputLines<int>('Logical key map');
144+
final OutputLines<int> lines = OutputLines<int>('Logical key map', behavior: DeduplicateBehavior.kSkip);
145145
for (final LogicalKeyEntry entry in logicalData.entries) {
146146
lines.add(entry.value, ' ${toHex(entry.value, digits: 11)}: ${entry.constantName},');
147147
}
148148
return lines.sortedJoin().trimRight();
149149
}
150150

151151
String get _maskConstantVariables {
152-
final OutputLines<int> lines = OutputLines<int>('Mask constants', checkDuplicate: false);
152+
final OutputLines<int> lines = OutputLines<int>('Mask constants', behavior: DeduplicateBehavior.kKeep);
153153
for (final MaskConstant constant in _maskConstants) {
154154
lines.add(constant.value, '''
155155
${_wrapString(constant.description)} ///

dev/tools/gen_keycodes/lib/keyboard_maps_code_gen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
303303

304304
/// This generates the map of Web KeyboardEvent codes to physical keys.
305305
String get _webPhysicalKeyMap {
306-
final OutputLines<String> lines = OutputLines<String>('Web physical key map');
306+
final OutputLines<String> lines = OutputLines<String>('Web physical key map', behavior: DeduplicateBehavior.kKeep);
307307
for (final PhysicalKeyEntry entry in keyData.entries) {
308308
for (final String webCodes in entry.webCodes()) {
309309
lines.add(entry.name, " '$webCodes': PhysicalKeyboardKey.${entry.constantName},");

dev/tools/gen_keycodes/lib/logical_key_data.dart

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ class LogicalKeyData {
5353
String glfwNameMap,
5454
PhysicalKeyData physicalKeyData,
5555
) {
56-
final Map<String, LogicalKeyEntry> data = <String, LogicalKeyEntry>{};
57-
_readKeyEntries(data, chromiumKeys);
56+
final Map<String, LogicalKeyEntry> data = _readKeyEntries(chromiumKeys);
5857
_readWindowsKeyCodes(data, windowsKeyCodeHeader, parseMapOfListOfString(windowsNameMap));
5958
_readGtkKeyCodes(data, gtkKeyCodeHeader, parseMapOfListOfString(gtkNameMap));
6059
_readAndroidKeyCodes(data, androidKeyCodeHeader, parseMapOfListOfString(androidNameMap));
@@ -130,7 +129,8 @@ class LogicalKeyData {
130129
/// The following format should be mapped to the Flutter plane.
131130
/// Key Enum Character
132131
/// FLUTTER_KEY_MAP("Lang4", LANG4, 0x00013),
133-
static void _readKeyEntries(Map<String, LogicalKeyEntry> data, String input) {
132+
static Map<String, LogicalKeyEntry> _readKeyEntries(String input) {
133+
final Map<int, LogicalKeyEntry> dataByValue = <int, LogicalKeyEntry>{};
134134
final RegExp domKeyRegExp = RegExp(
135135
r'(?<source>DOM|FLUTTER)_KEY_(?<kind>UNI|MAP)\s*\(\s*'
136136
r'"(?<name>[^\s]+?)",\s*'
@@ -162,17 +162,23 @@ class LogicalKeyData {
162162
}
163163

164164
final bool isPrintable = keyLabel != null;
165-
data.putIfAbsent(name, () {
166-
final LogicalKeyEntry entry = LogicalKeyEntry.fromName(
167-
value: toPlane(value, _sourceToPlane(source, isPrintable)),
165+
final int entryValue = toPlane(value, _sourceToPlane(source, isPrintable));
166+
final LogicalKeyEntry entry = dataByValue.putIfAbsent(entryValue, () =>
167+
LogicalKeyEntry.fromName(
168+
value: entryValue,
168169
name: name,
169170
keyLabel: keyLabel,
170-
);
171-
if (source == 'DOM' && !isPrintable)
172-
entry.webNames.add(webName);
173-
return entry;
174-
});
171+
),
172+
);
173+
if (source == 'DOM' && !isPrintable) {
174+
entry.webNames.add(webName);
175+
}
175176
}
177+
return Map<String, LogicalKeyEntry>.fromEntries(
178+
dataByValue.values.map((LogicalKeyEntry entry) =>
179+
MapEntry<String, LogicalKeyEntry>(entry.name, entry),
180+
),
181+
);
176182
}
177183

178184
static void _readMacOsKeyCodes(

dev/tools/gen_keycodes/lib/physical_key_data.dart

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,22 @@ class PhysicalKeyData {
171171
// Skip key that is not actually generated by any keyboard.
172172
continue;
173173
}
174+
final PhysicalKeyEntry? existing = entries[usbHidCode];
175+
// Allow duplicate entries for Fn, which overwrites.
176+
if (existing != null && existing.name != 'Fn') {
177+
// If it's an existing entry, the only thing we currently support is
178+
// to insert an extra DOMKey. The other entries must be empty.
179+
assert(evdevCode == 0
180+
&& xKbScanCode == 0
181+
&& windowsScanCode == 0
182+
&& macScanCode == 0xffff
183+
&& chromiumCode != null
184+
&& chromiumCode.isNotEmpty,
185+
'Duplicate usbHidCode ${existing.usbHidCode} of key ${existing.name} '
186+
'conflicts with existing ${entries[existing.usbHidCode]!.name}.');
187+
existing.otherWebCodes.add(chromiumCode!);
188+
continue;
189+
}
174190
final PhysicalKeyEntry newEntry = PhysicalKeyEntry(
175191
usbHidCode: usbHidCode,
176192
androidScanCodes: nameToAndroidScanCodes[name] ?? <int>[],
@@ -182,15 +198,6 @@ class PhysicalKeyData {
182198
name: name,
183199
chromiumCode: chromiumCode,
184200
);
185-
// Remove duplicates: last one wins, so that supplemental codes
186-
// override.
187-
if (entries.containsKey(newEntry.usbHidCode)) {
188-
// This is expected for Fn. Warn for other keys.
189-
if (newEntry.name != 'Fn') {
190-
print('Duplicate usbHidCode ${newEntry.usbHidCode} of key ${newEntry.name} '
191-
'conflicts with existing ${entries[newEntry.usbHidCode]!.name}. Keeping the new one.');
192-
}
193-
}
194201
entries[newEntry.usbHidCode] = newEntry;
195202
}
196203
return entries.map((int code, PhysicalKeyEntry entry) =>
@@ -216,7 +223,8 @@ class PhysicalKeyEntry {
216223
required this.macOSScanCode,
217224
required this.iOSScanCode,
218225
required this.chromiumCode,
219-
});
226+
List<String>? otherWebCodes,
227+
}) : otherWebCodes = otherWebCodes ?? <String>[];
220228

221229
/// Populates the key from a JSON map.
222230
factory PhysicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map) {
@@ -232,6 +240,7 @@ class PhysicalKeyEntry {
232240
windowsScanCode: scanCodes['windows'] as int?,
233241
macOSScanCode: scanCodes['macos'] as int?,
234242
iOSScanCode: scanCodes['ios'] as int?,
243+
otherWebCodes: (map['otherWebCodes'] as List<dynamic>?)?.cast<String>(),
235244
);
236245
}
237246

@@ -258,11 +267,14 @@ class PhysicalKeyEntry {
258267
final String name;
259268
/// The Chromium event code for the key.
260269
final String? chromiumCode;
270+
/// Other codes used by Web besides chromiumCode.
271+
final List<String> otherWebCodes;
261272

262273
Iterable<String> webCodes() sync* {
263274
if (chromiumCode != null) {
264275
yield chromiumCode!;
265276
}
277+
yield* otherWebCodes;
266278
}
267279

268280
/// Creates a JSON map from the key data.
@@ -272,6 +284,7 @@ class PhysicalKeyEntry {
272284
'name': name,
273285
'chromium': chromiumCode,
274286
},
287+
'otherWebCodes': otherWebCodes,
275288
'scanCodes': <String, dynamic>{
276289
'android': androidScanCodes,
277290
'usb': usbHidCode,
@@ -323,11 +336,14 @@ class PhysicalKeyEntry {
323336

324337
@override
325338
String toString() {
339+
final String otherWebStr = otherWebCodes.isEmpty
340+
? ''
341+
: ', otherWebCodes: [${otherWebCodes.join(', ')}]';
326342
return """'$constantName': (name: "$name", usbHidCode: ${toHex(usbHidCode)}, """
327343
'linuxScanCode: ${toHex(evdevCode)}, xKbScanCode: ${toHex(xKbScanCode)}, '
328344
'windowsKeyCode: ${toHex(windowsScanCode)}, macOSScanCode: ${toHex(macOSScanCode)}, '
329345
'windowsScanCode: ${toHex(windowsScanCode)}, chromiumSymbolName: $chromiumCode '
330-
'iOSScanCode: ${toHex(iOSScanCode)})';
346+
'iOSScanCode: ${toHex(iOSScanCode)})$otherWebStr';
331347
}
332348

333349
static int compareByUsbHidCode(PhysicalKeyEntry a, PhysicalKeyEntry b) =>

dev/tools/gen_keycodes/lib/testing_key_codes_cc_gen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ constexpr uint64_t kPhysical${_toUpperCammel(entry.constantName)} = ${toHex(entr
3030

3131
/// Gets the generated definitions of PhysicalKeyboardKeys.
3232
String get _logicalDefinitions {
33-
final OutputLines<int> lines = OutputLines<int>('Logical Key list');
33+
final OutputLines<int> lines = OutputLines<int>('Logical Key list', behavior: DeduplicateBehavior.kSkip);
3434
for (final LogicalKeyEntry entry in logicalData.entries) {
3535
lines.add(entry.value, '''
3636
constexpr uint64_t kLogical${_toUpperCammel(entry.constantName)} = ${toHex(entry.value, digits: 11)};''');

dev/tools/gen_keycodes/lib/testing_key_codes_java_gen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class KeyCodesJavaGenerator extends BaseCodeGenerator {
4242

4343
/// Gets the generated definitions of PhysicalKeyboardKeys.
4444
String get _logicalDefinitions {
45-
final OutputLines<int> lines = OutputLines<int>('Logical Key list');
45+
final OutputLines<int> lines = OutputLines<int>('Logical Key list', behavior: DeduplicateBehavior.kSkip);
4646
for (final LogicalKeyEntry entry in logicalData.entries) {
4747
lines.add(entry.value, '''
4848
public static final long LOGICAL_${_toUpperSnake(entry.constantName)} = ${toHex(entry.value, digits: 11)}L;''');

0 commit comments

Comments
 (0)