mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[gen_keycodes] Move GLFW keys to logical_key_data (#87086)
This commit is contained in:
parent
b50991d683
commit
c6a24e3fb2
@ -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,
|
||||
);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user