Unverified Commit c6a24e3f authored by Tong Mu's avatar Tong Mu Committed by GitHub

[gen_keycodes] Move GLFW keys to logical_key_data (#87086)

parent b50991d6
......@@ -163,14 +163,10 @@ Future<void> main(List<String> rawArguments) async {
final String supplementalHidCodes = readDataFile('supplemental_hid_codes.inc');
final String androidScanCodes = await getAndroidScanCodes();
final String androidToDomKey = readDataFile('android_key_name_to_name.json');
final String glfwKeyCodes = await getGlfwKeyCodes();
final String glfwToDomKey = readDataFile('glfw_key_name_to_name.json');
physicalData = PhysicalKeyData(
<String>[baseHidCodes, supplementalHidCodes].join('\n'),
androidScanCodes,
androidToDomKey,
glfwKeyCodes,
glfwToDomKey,
);
// Logical
......@@ -183,6 +179,8 @@ Future<void> main(List<String> rawArguments) async {
final String macosLogicalToPhysical = readDataFile('macos_logical_to_physical.json');
final String iosLogicalToPhysical = readDataFile('ios_logical_to_physical.json');
final String androidKeyCodes = await getAndroidKeyCodes();
final String glfwKeyCodes = await getGlfwKeyCodes();
final String glfwToDomKey = readDataFile('glfw_key_name_to_name.json');
logicalData = LogicalKeyData(
<String>[webLogicalKeys, supplementalKeyData].join('\n'),
......@@ -194,6 +192,8 @@ Future<void> main(List<String> rawArguments) async {
androidToDomKey,
macosLogicalToPhysical,
iosLogicalToPhysical,
glfwKeyCodes,
glfwToDomKey,
physicalData,
);
......
......@@ -63,7 +63,8 @@ class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
String get _glfwNumpadMap {
final OutputLines<int> lines = OutputLines<int>('GLFW numpad map');
for (final PhysicalKeyEntry entry in _numpadKeyData) {
for (final int code in entry.glfwKeyCodes) {
final LogicalKeyEntry logicalKey = logicalData.entryByName(entry.name);
for (final int code in logicalKey.glfwValues) {
lines.add(code, ' $code: LogicalKeyboardKey.${entry.constantName},');
}
}
......@@ -73,9 +74,9 @@ class KeyboardMapsCodeGenerator extends BaseCodeGenerator {
/// This generates the map of GLFW key codes to logical keys.
String get _glfwKeyCodeMap {
final OutputLines<int> lines = OutputLines<int>('GLFW key code map');
for (final PhysicalKeyEntry entry in keyData.entries) {
for (final int code in entry.glfwKeyCodes) {
lines.add(code, ' $code: LogicalKeyboardKey.${entry.constantName},');
for (final LogicalKeyEntry entry in logicalData.entries) {
for (final int value in entry.glfwValues) {
lines.add(value, ' $value: LogicalKeyboardKey.${entry.constantName},');
}
}
return lines.sortedJoin().trimRight();
......
......@@ -50,6 +50,8 @@ class LogicalKeyData {
String androidNameMap,
String macosLogicalToPhysical,
String iosLogicalToPhysical,
String glfwHeaderFile,
String glfwNameMap,
PhysicalKeyData physicalKeyData,
) {
final Map<String, LogicalKeyEntry> data = <String, LogicalKeyEntry>{};
......@@ -60,6 +62,7 @@ class LogicalKeyData {
_readMacOsKeyCodes(data, physicalKeyData, parseMapOfListOfString(macosLogicalToPhysical));
_readIosKeyCodes(data, physicalKeyData, parseMapOfListOfString(iosLogicalToPhysical));
_readFuchsiaKeyCodes(data, physicalKeyData);
_readGlfwKeyCodes(data, glfwHeaderFile, parseMapOfListOfString(glfwNameMap));
// Sort entries by value
final List<MapEntry<String, LogicalKeyEntry>> sortedEntries = data.entries.toList()..sort(
(MapEntry<String, LogicalKeyEntry> a, MapEntry<String, LogicalKeyEntry> b) =>
......@@ -333,6 +336,54 @@ class LogicalKeyData {
}
}
/// Parses entries from GLFW's keycodes.h key code data file.
///
/// Lines in this file look like this (without the ///):
/// /** Space key. */
/// #define GLFW_KEY_SPACE 32,
/// #define GLFW_KEY_LAST GLFW_KEY_MENU
static void _readGlfwKeyCodes(Map<String, LogicalKeyEntry> data, String headerFile, Map<String, List<String>> nameMap) {
final Map<String, String> nameToFlutterName = reverseMapOfListOfString(nameMap,
(String flutterName, String glfwName) { print('Duplicate GLFW logical name $glfwName'); });
// Only get the KEY definitions, ignore the rest (mouse, joystick, etc).
final RegExp definedCodes = RegExp(
r'define\s+'
r'GLFW_KEY_(?<name>[A-Z0-9_]+)\s+'
r'(?<value>[A-Z0-9_]+),?',
);
final Map<String, dynamic> replaced = <String, dynamic>{};
for (final RegExpMatch match in definedCodes.allMatches(headerFile)) {
final String name = match.namedGroup('name')!;
final String value = match.namedGroup('value')!;
replaced[name] = int.tryParse(value) ?? value.replaceAll('GLFW_KEY_', '');
}
final Map<String, int> glfwNameToKeyCode = <String, int>{};
replaced.forEach((String key, dynamic value) {
// Some definition values point to other definitions (e.g #define GLFW_KEY_LAST GLFW_KEY_MENU).
if (value is String) {
glfwNameToKeyCode[key] = replaced[value] as int;
} else {
glfwNameToKeyCode[key] = value as int;
}
});
glfwNameToKeyCode.forEach((String glfwName, int value) {
final String? name = nameToFlutterName[glfwName];
final LogicalKeyEntry? entry = data[nameToFlutterName[glfwName]];
if (entry == null) {
print('Invalid logical entry by name $name (from GLFW $glfwName)');
return;
}
addNameValue(
entry.glfwNames,
entry.glfwValues,
glfwName,
value,
);
});
}
// Map Web key to the pair of key names
static late final Map<String, _ModifierPair> _chromeModifiers = () {
final String rawJson = File(path.join(dataRoot, 'chromium_modifiers.json',)).readAsStringSync();
......@@ -401,7 +452,9 @@ class LogicalKeyEntry {
windowsValues = <int>[],
androidNames = <String>[],
androidValues = <int>[],
fuchsiaValues = <int>[];
fuchsiaValues = <int>[],
glfwNames = <String>[],
glfwValues = <int>[];
LogicalKeyEntry.fromName({
required int value,
......@@ -429,6 +482,8 @@ class LogicalKeyEntry {
androidNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['android']),
androidValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['android']),
fuchsiaValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['fuchsia']),
glfwNames = _toNonEmptyArray<String>((map['names'] as Map<String, dynamic>)['glfw']),
glfwValues = _toNonEmptyArray<int>((map['values'] as Map<String, dynamic>?)?['glfw']),
keyLabel = map['keyLabel'] as String?;
final int value;
......@@ -490,6 +545,15 @@ class LogicalKeyEntry {
final List<int> fuchsiaValues;
/// The list of names that GLFW gives to this key (symbol names minus the
/// prefix).
final List<String> glfwNames;
/// The list of GLFW key codes matching this key, created by looking up the
/// GLFW name in the Chromium data, and substituting the GLFW key code
/// value.
final List<int> glfwValues;
/// A string indicating the letter on the keycap of a letter key.
///
/// This is only used to generate the key label mapping in keyboard_map.dart.
......@@ -510,6 +574,7 @@ class LogicalKeyEntry {
'gtk': gtkNames,
'windows': windowsNames,
'android': androidNames,
'glfw': glfwNames,
},
'values': <String, List<int>>{
'macos': macOSKeyCodeValues,
......@@ -518,6 +583,7 @@ class LogicalKeyEntry {
'windows': windowsValues,
'android': androidValues,
'fuchsia': fuchsiaValues,
'glfw': glfwValues,
},
});
}
......
......@@ -17,15 +17,11 @@ class PhysicalKeyData {
String chromiumHidCodes,
String androidKeyboardLayout,
String androidNameMap,
String glfwHeaderFile,
String glfwNameMap,
) {
final Map<String, List<int>> nameToAndroidScanCodes = _readAndroidScanCodes(androidKeyboardLayout, androidNameMap);
final Map<String, List<int>> nameToGlfwKeyCodes = _readGlfwKeyCodes(glfwHeaderFile, glfwNameMap);
final Map<String, PhysicalKeyEntry> data = _readHidEntries(
chromiumHidCodes,
nameToAndroidScanCodes,
nameToGlfwKeyCodes,
);
final List<MapEntry<String, PhysicalKeyEntry>> sortedEntries = data.entries.toList()..sort(
(MapEntry<String, PhysicalKeyEntry> a, MapEntry<String, PhysicalKeyEntry> b) =>
......@@ -134,54 +130,6 @@ class PhysicalKeyData {
return result;
}
/// Parses entries from GLFW's keycodes.h key code data file.
///
/// Lines in this file look like this (without the ///):
/// /** Space key. */
/// #define GLFW_KEY_SPACE 32,
/// #define GLFW_KEY_LAST GLFW_KEY_MENU
static Map<String, List<int>> _readGlfwKeyCodes(String headerFile, String nameMap) {
// Only get the KEY definitions, ignore the rest (mouse, joystick, etc).
final RegExp definedCodes = RegExp(
r'define\s+'
r'GLFW_KEY_(?<name>[A-Z0-9_]+)\s+'
r'(?<value>[A-Z0-9_]+),?',
);
final Map<String, dynamic> replaced = <String, dynamic>{};
for (final RegExpMatch match in definedCodes.allMatches(headerFile)) {
final String name = match.namedGroup('name')!;
final String value = match.namedGroup('value')!;
replaced[name] = int.tryParse(value) ?? value.replaceAll('GLFW_KEY_', '');
}
final Map<String, int> glfwNameToKeyCode = <String, int>{};
replaced.forEach((String key, dynamic value) {
// Some definition values point to other definitions (e.g #define GLFW_KEY_LAST GLFW_KEY_MENU).
if (value is String) {
glfwNameToKeyCode[key] = replaced[value] as int;
} else {
glfwNameToKeyCode[key] = value as int;
}
});
final Map<String, List<String>> nameToGlfwNames = (json.decode(nameMap) as Map<String, dynamic>)
.cast<String, List<dynamic>>()
.map<String, List<String>>((String key, List<dynamic> value) {
return MapEntry<String, List<String>>(key, value.cast<String>());
});
final Map<String, List<int>> result = nameToGlfwNames.map((String name, List<String> glfwNames) {
final Set<int> keyCodes = <int>{};
for (final String glfwName in glfwNames) {
if (glfwNameToKeyCode[glfwName] != null)
keyCodes.add(glfwNameToKeyCode[glfwName]!);
}
return MapEntry<String, List<int>>(name, keyCodes.toList()..sort());
});
return result;
}
/// Parses entries from Chromium's HID code mapping header file.
///
/// Lines in this file look like this (without the ///):
......@@ -190,7 +138,6 @@ class PhysicalKeyData {
static Map<String, PhysicalKeyEntry> _readHidEntries(
String input,
Map<String, List<int>> nameToAndroidScanCodes,
Map<String, List<int>> nameToGlfwKeyCodes,
) {
final Map<int, PhysicalKeyEntry> entries = <int, PhysicalKeyEntry>{};
final RegExp usbMapRegExp = RegExp(
......@@ -227,7 +174,6 @@ class PhysicalKeyData {
final PhysicalKeyEntry newEntry = PhysicalKeyEntry(
usbHidCode: usbHidCode,
androidScanCodes: nameToAndroidScanCodes[name] ?? <int>[],
glfwKeyCodes: nameToGlfwKeyCodes[name] ?? <int>[],
linuxScanCode: linuxScanCode == 0 ? null : linuxScanCode,
xKbScanCode: xKbScanCode == 0 ? null : xKbScanCode,
windowsScanCode: windowsScanCode == 0 ? null : windowsScanCode,
......@@ -270,14 +216,12 @@ class PhysicalKeyEntry {
required this.macOSScanCode,
required this.iOSScanCode,
required this.chromiumCode,
required this.glfwKeyCodes,
});
/// Populates the key from a JSON map.
factory PhysicalKeyEntry.fromJsonMapEntry(Map<String, dynamic> map) {
final Map<String, dynamic> names = map['names'] as Map<String, dynamic>;
final Map<String, dynamic> scanCodes = map['scanCodes'] as Map<String, dynamic>;
final Map<String, dynamic>? keyCodes = map['keyCodes'] as Map<String, dynamic>?;
return PhysicalKeyEntry(
name: names['name'] as String,
chromiumCode: names['chromium'] as String?,
......@@ -288,7 +232,6 @@ class PhysicalKeyEntry {
windowsScanCode: scanCodes['windows'] as int?,
macOSScanCode: scanCodes['macos'] as int?,
iOSScanCode: scanCodes['ios'] as int?,
glfwKeyCodes: (keyCodes?['glfw'] as List<dynamic>?)?.cast<int>() ?? <int>[],
);
}
......@@ -309,10 +252,6 @@ class PhysicalKeyEntry {
/// the Android name in the Chromium data, and substituting the Android scan
/// code value.
final List<int> androidScanCodes;
/// The list of GLFW key codes matching this key, created by looking up the
/// Linux name in the Chromium data, and substituting the GLFW key code
/// value.
final List<int> glfwKeyCodes;
/// 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.
......@@ -336,9 +275,6 @@ class PhysicalKeyEntry {
'macos': macOSScanCode,
'ios': iOSScanCode,
},
'keyCodes': <String, List<int>>{
'glfw': glfwKeyCodes,
},
});
}
......
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