diff --git a/lib/models/hotkey_model.dart b/lib/models/hotkey_model.dart index 3c0c6367..49a2ea2b 100644 --- a/lib/models/hotkey_model.dart +++ b/lib/models/hotkey_model.dart @@ -40,7 +40,7 @@ String physicalKeyLabel(PhysicalKeyboardKey key) { final macLabel = _macKeyLabels[key.usbHidUsage]; if (macLabel != null) return macLabel; } - return _knownKeyLabels[key.usbHidUsage] ?? key.debugName ?? 'Unknown'; + return _keyLabels[key.usbHidUsage] ?? 'Unknown'; } /// macOS-specific overrides for keys that have standard symbols. @@ -70,60 +70,68 @@ const _macKeyLabels = { 0x00000012: 'fn', // fn }; -const _knownKeyLabels = { - 0x00070004: 'A', // keyA - 0x00070005: 'B', // keyB - 0x00070006: 'C', // keyC - 0x00070007: 'D', // keyD - 0x00070008: 'E', // keyE - 0x00070009: 'F', // keyF - 0x0007000a: 'G', // keyG - 0x0007000b: 'H', // keyH - 0x0007000c: 'I', // keyI - 0x0007000d: 'J', // keyJ - 0x0007000e: 'K', // keyK - 0x0007000f: 'L', // keyL - 0x00070010: 'M', // keyM - 0x00070011: 'N', // keyN - 0x00070012: 'O', // keyO - 0x00070013: 'P', // keyP - 0x00070014: 'Q', // keyQ - 0x00070015: 'R', // keyR - 0x00070016: 'S', // keyS - 0x00070017: 'T', // keyT - 0x00070018: 'U', // keyU - 0x00070019: 'V', // keyV - 0x0007001a: 'W', // keyW - 0x0007001b: 'X', // keyX - 0x0007001c: 'Y', // keyY - 0x0007001d: 'Z', // keyZ - 0x0007001e: '1', // digit1 - 0x0007001f: '2', // digit2 - 0x00070020: '3', // digit3 - 0x00070021: '4', // digit4 - 0x00070022: '5', // digit5 - 0x00070023: '6', // digit6 - 0x00070024: '7', // digit7 - 0x00070025: '8', // digit8 - 0x00070026: '9', // digit9 - 0x00070027: '0', // digit0 - 0x00070028: 'Enter', // enter - 0x00070029: 'Escape', // escape - 0x0007002a: 'Backspace', // backspace - 0x0007002b: 'Tab', // tab - 0x0007002c: 'Space', // space - 0x0007002d: '=', // equal - 0x0007002e: '-', // minus - 0x0007002f: '[', // bracketLeft - 0x00070030: ']', // bracketRight - 0x00070031: r'\', // backslash - 0x00070033: ';', // semicolon - 0x00070034: "'", // quote - 0x00070035: '`', // backquote - 0x00070036: ',', // comma - 0x00070037: '.', // period - 0x00070038: '/', // slash - 0x00070039: 'CapsLock', // capsLock +/// Comprehensive key labels sourced from Flutter's PhysicalKeyboardKey._debugNames +/// (keyboard_key.g.dart, USB HID keyboard usage page 0x0007). +/// Common keys use short curated labels; the rest use Flutter's default names. +const _keyLabels = { + // Letters + 0x00070004: 'A', + 0x00070005: 'B', + 0x00070006: 'C', + 0x00070007: 'D', + 0x00070008: 'E', + 0x00070009: 'F', + 0x0007000a: 'G', + 0x0007000b: 'H', + 0x0007000c: 'I', + 0x0007000d: 'J', + 0x0007000e: 'K', + 0x0007000f: 'L', + 0x00070010: 'M', + 0x00070011: 'N', + 0x00070012: 'O', + 0x00070013: 'P', + 0x00070014: 'Q', + 0x00070015: 'R', + 0x00070016: 'S', + 0x00070017: 'T', + 0x00070018: 'U', + 0x00070019: 'V', + 0x0007001a: 'W', + 0x0007001b: 'X', + 0x0007001c: 'Y', + 0x0007001d: 'Z', + // Digits + 0x0007001e: '1', + 0x0007001f: '2', + 0x00070020: '3', + 0x00070021: '4', + 0x00070022: '5', + 0x00070023: '6', + 0x00070024: '7', + 0x00070025: '8', + 0x00070026: '9', + 0x00070027: '0', + // Special keys + 0x00070028: 'Enter', + 0x00070029: 'Escape', + 0x0007002a: 'Backspace', + 0x0007002b: 'Tab', + 0x0007002c: 'Space', + // Symbols + 0x0007002d: '-', + 0x0007002e: '=', + 0x0007002f: '[', + 0x00070030: ']', + 0x00070031: r'\', + 0x00070033: ';', + 0x00070034: "'", + 0x00070035: '`', + 0x00070036: ',', + 0x00070037: '.', + 0x00070038: '/', + // Lock & function keys + 0x00070039: 'Caps Lock', 0x0007003a: 'F1', 0x0007003b: 'F2', 0x0007003c: 'F3', @@ -136,22 +144,105 @@ const _knownKeyLabels = { 0x00070043: 'F10', 0x00070044: 'F11', 0x00070045: 'F12', - 0x0007004a: 'Home', // home - 0x0007004b: 'Page Up', // pageUp - 0x0007004c: 'Delete', // delete - 0x0007004d: 'End', // end - 0x0007004e: 'Page Down', // pageDown - 0x0007004f: 'Arrow Right', // arrowRight - 0x00070050: 'Arrow Left', // arrowLeft - 0x00070051: 'Arrow Down', // arrowDown - 0x00070052: 'Arrow Up', // arrowUp - 0x000700e0: 'Ctrl', // controlLeft - 0x000700e1: 'Shift', // shiftLeft - 0x000700e2: 'Alt', // altLeft - 0x000700e3: 'Meta', // metaLeft - 0x000700e4: 'Ctrl', // controlRight - 0x000700e5: 'Shift', // shiftRight - 0x000700e6: 'Alt', // altRight - 0x000700e7: 'Meta', // metaRight - 0x00000012: 'Fn', // fn + 0x00070046: 'Print Screen', + 0x00070047: 'Scroll Lock', + 0x00070048: 'Pause', + 0x00070049: 'Insert', + // Navigation + 0x0007004a: 'Home', + 0x0007004b: 'Page Up', + 0x0007004c: 'Delete', + 0x0007004d: 'End', + 0x0007004e: 'Page Down', + 0x0007004f: 'Arrow Right', + 0x00070050: 'Arrow Left', + 0x00070051: 'Arrow Down', + 0x00070052: 'Arrow Up', + // Numpad + 0x00070053: 'Num Lock', + 0x00070054: 'Numpad /', + 0x00070055: 'Numpad *', + 0x00070056: 'Numpad -', + 0x00070057: 'Numpad +', + 0x00070058: 'Numpad Enter', + 0x00070059: 'Numpad 1', + 0x0007005a: 'Numpad 2', + 0x0007005b: 'Numpad 3', + 0x0007005c: 'Numpad 4', + 0x0007005d: 'Numpad 5', + 0x0007005e: 'Numpad 6', + 0x0007005f: 'Numpad 7', + 0x00070060: 'Numpad 8', + 0x00070061: 'Numpad 9', + 0x00070062: 'Numpad 0', + 0x00070063: 'Numpad .', + 0x00070064: 'Intl Backslash', + 0x00070065: 'Context Menu', + 0x00070066: 'Power', + 0x00070067: 'Numpad =', + // Extended function keys + 0x00070068: 'F13', + 0x00070069: 'F14', + 0x0007006a: 'F15', + 0x0007006b: 'F16', + 0x0007006c: 'F17', + 0x0007006d: 'F18', + 0x0007006e: 'F19', + 0x0007006f: 'F20', + 0x00070070: 'F21', + 0x00070071: 'F22', + 0x00070072: 'F23', + 0x00070073: 'F24', + // Editing + 0x00070074: 'Open', + 0x00070075: 'Help', + 0x00070077: 'Select', + 0x00070079: 'Again', + 0x0007007a: 'Undo', + 0x0007007b: 'Cut', + 0x0007007c: 'Copy', + 0x0007007d: 'Paste', + 0x0007007e: 'Find', + // Audio + 0x0007007f: 'Volume Mute', + 0x00070080: 'Volume Up', + 0x00070081: 'Volume Down', + // Numpad extras + 0x00070085: 'Numpad ,', + // International + 0x00070087: 'Intl Ro', + 0x00070088: 'Kana Mode', + 0x00070089: 'Intl Yen', + 0x0007008a: 'Convert', + 0x0007008b: 'Non Convert', + 0x00070090: 'Lang 1', + 0x00070091: 'Lang 2', + 0x00070092: 'Lang 3', + 0x00070093: 'Lang 4', + 0x00070094: 'Lang 5', + 0x0007009b: 'Abort', + 0x000700a3: 'Props', + // Numpad advanced + 0x000700b6: 'Numpad (', + 0x000700b7: 'Numpad )', + 0x000700bb: 'Numpad Backspace', + 0x000700d0: 'Numpad Memory Store', + 0x000700d1: 'Numpad Memory Recall', + 0x000700d2: 'Numpad Memory Clear', + 0x000700d3: 'Numpad Memory Add', + 0x000700d4: 'Numpad Memory Subtract', + 0x000700d7: 'Numpad Sign Change', + 0x000700d8: 'Numpad Clear', + 0x000700d9: 'Numpad Clear Entry', + // Modifiers + 0x000700e0: 'Ctrl', + 0x000700e1: 'Shift', + 0x000700e2: 'Alt', + 0x000700e3: 'Meta', + 0x000700e4: 'Ctrl', + 0x000700e5: 'Shift', + 0x000700e6: 'Alt', + 0x000700e7: 'Meta', + // Fn + 0x00000012: 'Fn', }; diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 4b2b7cf8..46039865 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -606,8 +606,9 @@ class SettingsService extends BaseSharedPreferencesService { .cast() .toList(); - // Try direct USB HID lookup first (new format), fall back to string parsing (backwards compat) - final key = _usbHidKeyMap[keyString] ?? _findKeyByString(keyString); + // Try parsing as USB HID code first (new format), fall back to string parsing (backwards compat) + final usbHidCode = int.tryParse(keyString, radix: 16); + final key = usbHidCode != null ? PhysicalKeyboardKey(usbHidCode) : _findKeyByString(keyString); if (key != null) { return HotKey(key: key, modifiers: modifiers.isNotEmpty ? modifiers : null); } @@ -617,82 +618,6 @@ class SettingsService extends BaseSharedPreferencesService { return null; } - // Unified map for USB HID codes to PhysicalKeyboardKey - static const _usbHidKeyMap = { - // Special keys - '0007002c': PhysicalKeyboardKey.space, - '0007002a': PhysicalKeyboardKey.backspace, - '0007004c': PhysicalKeyboardKey.delete, - '00070028': PhysicalKeyboardKey.enter, - '00070029': PhysicalKeyboardKey.escape, - '0007002b': PhysicalKeyboardKey.tab, - '00070039': PhysicalKeyboardKey.capsLock, - // Arrow keys - '00070050': PhysicalKeyboardKey.arrowLeft, - '00070052': PhysicalKeyboardKey.arrowUp, - '0007004f': PhysicalKeyboardKey.arrowRight, - '00070051': PhysicalKeyboardKey.arrowDown, - // Navigation keys - '0007004a': PhysicalKeyboardKey.home, - '0007004d': PhysicalKeyboardKey.end, - '0007004b': PhysicalKeyboardKey.pageUp, - '0007004e': PhysicalKeyboardKey.pageDown, - // Symbol keys - '0007002d': PhysicalKeyboardKey.equal, - '0007002e': PhysicalKeyboardKey.minus, - // Function keys - '0007003a': PhysicalKeyboardKey.f1, - '0007003b': PhysicalKeyboardKey.f2, - '0007003c': PhysicalKeyboardKey.f3, - '0007003d': PhysicalKeyboardKey.f4, - '0007003e': PhysicalKeyboardKey.f5, - '0007003f': PhysicalKeyboardKey.f6, - '00070040': PhysicalKeyboardKey.f7, - '00070041': PhysicalKeyboardKey.f8, - '00070042': PhysicalKeyboardKey.f9, - '00070043': PhysicalKeyboardKey.f10, - '00070044': PhysicalKeyboardKey.f11, - '00070045': PhysicalKeyboardKey.f12, - // Number keys - '00070027': PhysicalKeyboardKey.digit0, - '0007001e': PhysicalKeyboardKey.digit1, - '0007001f': PhysicalKeyboardKey.digit2, - '00070020': PhysicalKeyboardKey.digit3, - '00070021': PhysicalKeyboardKey.digit4, - '00070022': PhysicalKeyboardKey.digit5, - '00070023': PhysicalKeyboardKey.digit6, - '00070024': PhysicalKeyboardKey.digit7, - '00070025': PhysicalKeyboardKey.digit8, - '00070026': PhysicalKeyboardKey.digit9, - // Letter keys - '00070004': PhysicalKeyboardKey.keyA, - '00070005': PhysicalKeyboardKey.keyB, - '00070006': PhysicalKeyboardKey.keyC, - '00070007': PhysicalKeyboardKey.keyD, - '00070008': PhysicalKeyboardKey.keyE, - '00070009': PhysicalKeyboardKey.keyF, - '0007000a': PhysicalKeyboardKey.keyG, - '0007000b': PhysicalKeyboardKey.keyH, - '0007000c': PhysicalKeyboardKey.keyI, - '0007000d': PhysicalKeyboardKey.keyJ, - '0007000e': PhysicalKeyboardKey.keyK, - '0007000f': PhysicalKeyboardKey.keyL, - '00070010': PhysicalKeyboardKey.keyM, - '00070011': PhysicalKeyboardKey.keyN, - '00070012': PhysicalKeyboardKey.keyO, - '00070013': PhysicalKeyboardKey.keyP, - '00070014': PhysicalKeyboardKey.keyQ, - '00070015': PhysicalKeyboardKey.keyR, - '00070016': PhysicalKeyboardKey.keyS, - '00070017': PhysicalKeyboardKey.keyT, - '00070018': PhysicalKeyboardKey.keyU, - '00070019': PhysicalKeyboardKey.keyV, - '0007001a': PhysicalKeyboardKey.keyW, - '0007001b': PhysicalKeyboardKey.keyX, - '0007001c': PhysicalKeyboardKey.keyY, - '0007001d': PhysicalKeyboardKey.keyZ, - }; - // Map for pattern-based key name matching (lowercase keys for case-insensitive matching) static const _keyNameMap = { 'space': PhysicalKeyboardKey.space, @@ -782,9 +707,8 @@ class SettingsService extends BaseSharedPreferencesService { // Format: PhysicalKeyboardKey#ec9ed(usbHidUsage: "0x0007002c", debugName: "Space") final usbHidMatch = RegExp(r'usbhidusage: "0x([0-9a-f]+)"').firstMatch(normalized); if (usbHidMatch != null) { - final usbHidCode = usbHidMatch.group(1)!; - final key = _usbHidKeyMap[usbHidCode]; - if (key != null) return key; + final code = int.tryParse(usbHidMatch.group(1)!, radix: 16); + if (code != null) return PhysicalKeyboardKey(code); } // Try direct name matches