Skip to content

Commit 65ea767

Browse files
authored
[gen_keycode, RawKeyboard] Apply derived keyboard layout from Linux (#102709)
1 parent 5288ff8 commit 65ea767

File tree

15 files changed

+146
-30
lines changed

15 files changed

+146
-30
lines changed

dev/tools/gen_keycodes/bin/gen_keycodes.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ Future<void> main(List<String> rawArguments) async {
206206
logicalData = LogicalKeyData.fromJson(json.decode(await File(parsedArguments['logical-data'] as String).readAsString()) as Map<String, dynamic>);
207207
}
208208

209+
final Map<String, bool> layoutGoals = parseMapOfBool(readDataFile('layout_goals.json'));
210+
209211
final File codeFile = File(parsedArguments['code'] as String);
210212
if (!codeFile.existsSync()) {
211213
codeFile.createSync(recursive: true);
@@ -236,6 +238,7 @@ Future<void> main(List<String> rawArguments) async {
236238
'macos': MacOSCodeGenerator(
237239
physicalData,
238240
logicalData,
241+
layoutGoals,
239242
),
240243
'ios': IOSCodeGenerator(
241244
physicalData,
@@ -251,6 +254,7 @@ Future<void> main(List<String> rawArguments) async {
251254
logicalData,
252255
readDataFile('gtk_modifier_bit_mapping.json'),
253256
readDataFile('gtk_lock_bit_mapping.json'),
257+
layoutGoals,
254258
),
255259
'web': WebCodeGenerator(
256260
physicalData,

dev/tools/gen_keycodes/data/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
| [`chromium_modifiers.json`](chromium_modifiers.json) | Maps the web's `key` for modifier keys to the names of the logical keys for these keys' left and right variations.This is used when generating logical keys to provide independent values for sided logical keys. Web uses the same `key` for modifier keys of different sides, but Flutter's logical key model treats them as different keys.|
1212
| [`printable.json`](printable.json) | Maps Flutter key name to its printable character. This character is used as the key label.|
1313
| [`synonyms.json`](synonyms.json) | Maps pseudo-keys that represent other keys to the sets of keys they represent. For example, this contains the "shift" key that represents either a "shiftLeft" or "shiftRight" key.|
14+
| [`layout_goals.json`](layout_goals.json) | A list of layout goals, keys that the platform keyboard manager should find mappings for. Each key in this file is the key name of the goal, both logical and physical simultaneously, while its value represents whether the goal is mandatory. A mandatory goal must be fulfilled, and the manager will use the default value from this file if a mapping can not be found. A non-mandatory goal is suggestive, only used if the key mapping information is malformed (e.g. contains no ASCII characters.) |
1415

1516
### Framework
1617

dev/tools/gen_keycodes/data/gtk_key_mapping_cc.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@ void initialize_lock_bit_to_checked_keys(GHashTable* table) {
3535
@@@GTK_MODE_BIT_MAP@@@
3636
}
3737

38+
const std::vector<LayoutGoal> layout_goals = {
39+
@@@LAYOUT_GOALS@@@
40+
};
41+
3842
@@@MASK_CONSTANTS@@@
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"KeyA": true,
3+
"KeyB": true,
4+
"KeyC": true,
5+
"KeyD": true,
6+
"KeyE": true,
7+
"KeyF": true,
8+
"KeyG": true,
9+
"KeyH": true,
10+
"KeyI": true,
11+
"KeyJ": true,
12+
"KeyK": true,
13+
"KeyL": true,
14+
"KeyM": true,
15+
"KeyN": true,
16+
"KeyO": true,
17+
"KeyP": true,
18+
"KeyQ": true,
19+
"KeyR": true,
20+
"KeyS": true,
21+
"KeyT": true,
22+
"KeyU": true,
23+
"KeyV": true,
24+
"KeyW": true,
25+
"KeyX": true,
26+
"KeyY": true,
27+
"KeyZ": true,
28+
"Digit1": true,
29+
"Digit2": true,
30+
"Digit3": true,
31+
"Digit4": true,
32+
"Digit5": true,
33+
"Digit6": true,
34+
"Digit7": true,
35+
"Digit8": true,
36+
"Digit9": true,
37+
"Digit0": true,
38+
"Quote": false,
39+
"Comma": false,
40+
"Minus": false,
41+
"Period": false,
42+
"Slash": false,
43+
"Semicolon": false,
44+
"Equal": false,
45+
"BracketLeft": false,
46+
"Backslash": false,
47+
"BracketRight": false,
48+
"Backquote": false,
49+
"IntlBackslash": false
50+
}

dev/tools/gen_keycodes/lib/gtk_code_gen.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class GtkCodeGenerator extends PlatformCodeGenerator {
1919
super.logicalData,
2020
String modifierBitMapping,
2121
String lockBitMapping,
22+
this._layoutGoals,
2223
) : _modifierBitMapping = parseMapOfListOfString(modifierBitMapping),
2324
_lockBitMapping = parseMapOfListOfString(lockBitMapping);
2425

@@ -91,6 +92,24 @@ class GtkCodeGenerator extends PlatformCodeGenerator {
9192
}
9293
final Map<String, List<String>> _lockBitMapping;
9394

95+
final Map<String, bool> _layoutGoals;
96+
String get _layoutGoalsString {
97+
final OutputLines<int> lines = OutputLines<int>('GTK layout goals');
98+
_layoutGoals.forEach((String name, bool mandatory) {
99+
final PhysicalKeyEntry physicalEntry = keyData.entryByName(name);
100+
final LogicalKeyEntry logicalEntry = logicalData.entryByName(name);
101+
final String line = 'LayoutGoal{'
102+
'${toHex(physicalEntry.xKbScanCode, digits: 2)}, '
103+
'${toHex(logicalEntry.value, digits: 2)}, '
104+
'${mandatory ? 'true' : 'false'}'
105+
'},';
106+
lines.add(logicalEntry.value,
107+
' ${line.padRight(39)}'
108+
'// ${logicalEntry.name}');
109+
});
110+
return lines.sortedJoin().trimRight();
111+
}
112+
94113
/// This generates the mask values for the part of a key code that defines its plane.
95114
String get _maskConstants {
96115
final StringBuffer buffer = StringBuffer();
@@ -120,6 +139,7 @@ class GtkCodeGenerator extends PlatformCodeGenerator {
120139
'GTK_MODIFIER_BIT_MAP': _gtkModifierBitMap,
121140
'GTK_MODE_BIT_MAP': _gtkModeBitMap,
122141
'MASK_CONSTANTS': _maskConstants,
142+
'LAYOUT_GOALS': _layoutGoalsString,
123143
};
124144
}
125145
}

dev/tools/gen_keycodes/lib/ios_code_gen.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class IOSCodeGenerator extends PlatformCodeGenerator {
8989
String get _keyToModifierFlagMap {
9090
final StringBuffer modifierKeyMap = StringBuffer();
9191
for (final String name in kModifiersOfInterest) {
92-
final String line =' {${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}, kModifierFlag${lowerCamelToUpperCamel(name)}},';
92+
final String line = '{${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}, kModifierFlag${lowerCamelToUpperCamel(name)}},';
9393
modifierKeyMap.writeln(' ${line.padRight(42)}// $name');
9494
}
9595
return modifierKeyMap.toString().trimRight();
@@ -99,7 +99,7 @@ class IOSCodeGenerator extends PlatformCodeGenerator {
9999
String get _modifierFlagToKeyMap {
100100
final StringBuffer modifierKeyMap = StringBuffer();
101101
for (final String name in kModifiersOfInterest) {
102-
final String line =' {kModifierFlag${lowerCamelToUpperCamel(name)}, ${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}},';
102+
final String line = '{kModifierFlag${lowerCamelToUpperCamel(name)}, ${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}},';
103103
modifierKeyMap.writeln(' ${line.padRight(42)}// $name');
104104
}
105105
return modifierKeyMap.toString().trimRight();

dev/tools/gen_keycodes/lib/macos_code_gen.dart

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const List<String> kSpecialLogicalKeys = <String>['CapsLock'];
2828
/// Generates the key mapping for macOS, based on the information in the key
2929
/// data structure given to it.
3030
class MacOSCodeGenerator extends PlatformCodeGenerator {
31-
MacOSCodeGenerator(super.keyData, super.logicalData);
31+
MacOSCodeGenerator(super.keyData, super.logicalData, this._layoutGoals);
3232

3333
/// This generates the map of macOS key codes to physical keys.
3434
String get _scanCodeMap {
@@ -96,24 +96,21 @@ class MacOSCodeGenerator extends PlatformCodeGenerator {
9696
return specialKeyConstants.toString().trimRight();
9797
}
9898

99-
String get _layoutGoals {
99+
final Map<String, bool> _layoutGoals;
100+
String get _layoutGoalsString {
100101
final OutputLines<int> lines = OutputLines<int>('macOS layout goals');
101-
final Iterable<LogicalKeyEntry> asciiEntries = logicalData.entries.where(
102-
(LogicalKeyEntry entry) => entry.value <= 128);
103-
for (final LogicalKeyEntry logicalEntry in asciiEntries) {
104-
final int value = logicalEntry.value;
105-
final PhysicalKeyEntry? physicalEntry = keyData.tryEntryByName(logicalEntry.name);
106-
if (physicalEntry == null) {
107-
continue;
108-
}
109-
final bool mandatory = (value >= '0'.codeUnitAt(0) && value <= '9'.codeUnitAt(0))
110-
|| (value >= 'a'.codeUnitAt(0) && value <= 'z'.codeUnitAt(0));
111-
lines.add(value,
112-
' LayoutGoal{${toHex(physicalEntry.macOSScanCode, digits: 2)}, '
113-
'${toHex(value, digits: 2)}, '
114-
'${mandatory ? 'true}, ' : 'false},'}'
115-
' // ${logicalEntry.name}');
116-
}
102+
_layoutGoals.forEach((String name, bool mandatory) {
103+
final PhysicalKeyEntry physicalEntry = keyData.entryByName(name);
104+
final LogicalKeyEntry logicalEntry = logicalData.entryByName(name);
105+
final String line = 'LayoutGoal{'
106+
'${toHex(physicalEntry.macOSScanCode, digits: 2)}, '
107+
'${toHex(logicalEntry.value, digits: 2)}, '
108+
'${mandatory ? 'true' : 'false'}'
109+
'},';
110+
lines.add(logicalEntry.value,
111+
' ${line.padRight(39)}'
112+
'// ${logicalEntry.name}');
113+
});
117114
return lines.sortedJoin().trimRight();
118115
}
119116

@@ -136,7 +133,7 @@ class MacOSCodeGenerator extends PlatformCodeGenerator {
136133
'KEYCODE_TO_MODIFIER_FLAG_MAP': _keyToModifierFlagMap,
137134
'MODIFIER_FLAG_TO_KEYCODE_MAP': _modifierFlagToKeyMap,
138135
'SPECIAL_KEY_CONSTANTS': _specialKeyConstants,
139-
'LAYOUT_GOALS': _layoutGoals,
136+
'LAYOUT_GOALS': _layoutGoalsString,
140137
};
141138
}
142139
}

dev/tools/gen_keycodes/lib/physical_key_data.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class PhysicalKeyData {
158158
input = input.replaceAll(commentRegExp, '');
159159
for (final RegExpMatch match in usbMapRegExp.allMatches(input)) {
160160
final int usbHidCode = getHex(match.namedGroup('usb')!);
161-
final int linuxScanCode = getHex(match.namedGroup('evdev')!);
161+
final int evdevCode = getHex(match.namedGroup('evdev')!);
162162
final int xKbScanCode = getHex(match.namedGroup('xkb')!);
163163
final int windowsScanCode = getHex(match.namedGroup('win')!);
164164
final int macScanCode = getHex(match.namedGroup('mac')!);
@@ -174,7 +174,7 @@ class PhysicalKeyData {
174174
final PhysicalKeyEntry newEntry = PhysicalKeyEntry(
175175
usbHidCode: usbHidCode,
176176
androidScanCodes: nameToAndroidScanCodes[name] ?? <int>[],
177-
linuxScanCode: linuxScanCode == 0 ? null : linuxScanCode,
177+
evdevCode: evdevCode == 0 ? null : evdevCode,
178178
xKbScanCode: xKbScanCode == 0 ? null : xKbScanCode,
179179
windowsScanCode: windowsScanCode == 0 ? null : windowsScanCode,
180180
macOSScanCode: macScanCode == 0xffff ? null : macScanCode,
@@ -210,7 +210,7 @@ class PhysicalKeyEntry {
210210
required this.usbHidCode,
211211
required this.name,
212212
required this.androidScanCodes,
213-
required this.linuxScanCode,
213+
required this.evdevCode,
214214
required this.xKbScanCode,
215215
required this.windowsScanCode,
216216
required this.macOSScanCode,
@@ -227,7 +227,7 @@ class PhysicalKeyEntry {
227227
chromiumCode: names['chromium'] as String?,
228228
usbHidCode: scanCodes['usb'] as int,
229229
androidScanCodes: (scanCodes['android'] as List<dynamic>?)?.cast<int>() ?? <int>[],
230-
linuxScanCode: scanCodes['linux'] as int?,
230+
evdevCode: scanCodes['linux'] as int?,
231231
xKbScanCode: scanCodes['xkb'] as int?,
232232
windowsScanCode: scanCodes['windows'] as int?,
233233
macOSScanCode: scanCodes['macos'] as int?,
@@ -238,8 +238,8 @@ class PhysicalKeyEntry {
238238
/// The USB HID code of the key
239239
final int usbHidCode;
240240

241-
/// The Linux scan code of the key, from Chromium's header file.
242-
final int? linuxScanCode;
241+
/// The Evdev scan code of the key, from Chromium's header file.
242+
final int? evdevCode;
243243
/// The XKb scan code of the key from Chromium's header file.
244244
final int? xKbScanCode;
245245
/// The Windows scan code of the key from Chromium's header file.
@@ -269,7 +269,7 @@ class PhysicalKeyEntry {
269269
'scanCodes': <String, dynamic>{
270270
'android': androidScanCodes,
271271
'usb': usbHidCode,
272-
'linux': linuxScanCode,
272+
'linux': evdevCode,
273273
'xkb': xKbScanCode,
274274
'windows': windowsScanCode,
275275
'macos': macOSScanCode,
@@ -318,7 +318,7 @@ class PhysicalKeyEntry {
318318
@override
319319
String toString() {
320320
return """'$constantName': (name: "$name", usbHidCode: ${toHex(usbHidCode)}, """
321-
'linuxScanCode: ${toHex(linuxScanCode)}, xKbScanCode: ${toHex(xKbScanCode)}, '
321+
'linuxScanCode: ${toHex(evdevCode)}, xKbScanCode: ${toHex(xKbScanCode)}, '
322322
'windowsKeyCode: ${toHex(windowsScanCode)}, macOSScanCode: ${toHex(macOSScanCode)}, '
323323
'windowsScanCode: ${toHex(windowsScanCode)}, chromiumSymbolName: $chromiumCode '
324324
'iOSScanCode: ${toHex(iOSScanCode)})';

dev/tools/gen_keycodes/lib/utils.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ Map<String, List<String?>> parseMapOfListOfNullableString(String jsonString) {
184184
});
185185
}
186186

187+
Map<String, bool> parseMapOfBool(String jsonString) {
188+
return (json.decode(jsonString) as Map<String, dynamic>).cast<String, bool>();
189+
}
190+
187191
/// Reverse the map of { fromValue -> list of toValue } to { toValue -> fromValue } and return.
188192
Map<String, String> reverseMapOfListOfString(Map<String, List<String>> inMap, void Function(String fromValue, String newToValue) onDuplicate) {
189193
final Map<String, String> result = <String, String>{};

dev/tools/gen_keycodes/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: gen_keycodes
22
description: Generates keycode source files from various resources.
33

44
environment:
5-
sdk: ">=2.17.0-0 <3.0.0"
5+
sdk: ">=2.18.0-0 <3.0.0"
66

77
dependencies:
88
args: 2.3.0

0 commit comments

Comments
 (0)