From 8a66cf6d9217a628d8bddaf143a26ef9c0553d85 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:04:01 +0200 Subject: [PATCH] fix: add HID key labels for non-keyboard USB pages close #793 --- lib/data/hid_key_labels.dart | 335 +++++++++++++++++++++++++++++++++++ lib/models/hotkey_model.dart | 181 +------------------ 2 files changed, 338 insertions(+), 178 deletions(-) create mode 100644 lib/data/hid_key_labels.dart diff --git a/lib/data/hid_key_labels.dart b/lib/data/hid_key_labels.dart new file mode 100644 index 00000000..ca900630 --- /dev/null +++ b/lib/data/hid_key_labels.dart @@ -0,0 +1,335 @@ +// Generated from USB HID Usage Tables — do not edit by hand. + +/// Human-readable labels for physical keyboard keys, keyed by USB HID usage code. +const hidKeyLabels = { + // Special + 0x00000010: 'Hyper', + 0x00000011: 'Super', + 0x00000012: 'Fn', + 0x00000013: 'Fn Lock', + 0x00000014: 'Suspend', + 0x00000015: 'Resume', + 0x00000016: 'Turbo', + 0x00000017: 'Privacy Screen Toggle', + 0x00000018: 'Microphone Mute', + // Generic Desktop + 0x00010082: 'Sleep', + 0x00010083: 'Wake Up', + 0x000100b5: 'Display Toggle', + // Game Buttons + 0x0005ff01: 'Game Button 1', + 0x0005ff02: 'Game Button 2', + 0x0005ff03: 'Game Button 3', + 0x0005ff04: 'Game Button 4', + 0x0005ff05: 'Game Button 5', + 0x0005ff06: 'Game Button 6', + 0x0005ff07: 'Game Button 7', + 0x0005ff08: 'Game Button 8', + 0x0005ff09: 'Game Button 9', + 0x0005ff0a: 'Game Button 10', + 0x0005ff0b: 'Game Button 11', + 0x0005ff0c: 'Game Button 12', + 0x0005ff0d: 'Game Button 13', + 0x0005ff0e: 'Game Button 14', + 0x0005ff0f: 'Game Button 15', + 0x0005ff10: 'Game Button 16', + 0x0005ff11: 'Game Button A', + 0x0005ff12: 'Game Button B', + 0x0005ff13: 'Game Button C', + 0x0005ff14: 'Game Button Left 1', + 0x0005ff15: 'Game Button Left 2', + 0x0005ff16: 'Game Button Mode', + 0x0005ff17: 'Game Button Right 1', + 0x0005ff18: 'Game Button Right 2', + 0x0005ff19: 'Game Button Select', + 0x0005ff1a: 'Game Button Start', + 0x0005ff1b: 'Game Button Thumb Left', + 0x0005ff1c: 'Game Button Thumb Right', + 0x0005ff1d: 'Game Button X', + 0x0005ff1e: 'Game Button Y', + 0x0005ff1f: 'Game Button Z', + // Keyboard/Keypad + 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', + 0x0007001e: '1', + 0x0007001f: '2', + 0x00070020: '3', + 0x00070021: '4', + 0x00070022: '5', + 0x00070023: '6', + 0x00070024: '7', + 0x00070025: '8', + 0x00070026: '9', + 0x00070027: '0', + 0x00070028: 'Enter', + 0x00070029: 'Escape', + 0x0007002a: 'Backspace', + 0x0007002b: 'Tab', + 0x0007002c: 'Space', + 0x0007002d: '-', + 0x0007002e: '=', + 0x0007002f: '[', + 0x00070030: ']', + 0x00070031: r'\', + 0x00070033: ';', + 0x00070034: "'", + 0x00070035: '`', + 0x00070036: ',', + 0x00070037: '.', + 0x00070038: '/', + 0x00070039: 'Caps Lock', + 0x0007003a: 'F1', + 0x0007003b: 'F2', + 0x0007003c: 'F3', + 0x0007003d: 'F4', + 0x0007003e: 'F5', + 0x0007003f: 'F6', + 0x00070040: 'F7', + 0x00070041: 'F8', + 0x00070042: 'F9', + 0x00070043: 'F10', + 0x00070044: 'F11', + 0x00070045: 'F12', + 0x00070046: 'Print Screen', + 0x00070047: 'Scroll Lock', + 0x00070048: 'Pause', + 0x00070049: 'Insert', + 0x0007004a: 'Home', + 0x0007004b: 'Page Up', + 0x0007004c: 'Delete', + 0x0007004d: 'End', + 0x0007004e: 'Page Down', + 0x0007004f: 'Arrow Right', + 0x00070050: 'Arrow Left', + 0x00070051: 'Arrow Down', + 0x00070052: 'Arrow Up', + 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 =', + 0x00070068: 'F13', + 0x00070069: 'F14', + 0x0007006a: 'F15', + 0x0007006b: 'F16', + 0x0007006c: 'F17', + 0x0007006d: 'F18', + 0x0007006e: 'F19', + 0x0007006f: 'F20', + 0x00070070: 'F21', + 0x00070071: 'F22', + 0x00070072: 'F23', + 0x00070073: 'F24', + 0x00070074: 'Open', + 0x00070075: 'Help', + 0x00070077: 'Select', + 0x00070079: 'Again', + 0x0007007a: 'Undo', + 0x0007007b: 'Cut', + 0x0007007c: 'Copy', + 0x0007007d: 'Paste', + 0x0007007e: 'Find', + 0x0007007f: 'Volume Mute', + 0x00070080: 'Volume Up', + 0x00070081: 'Volume Down', + 0x00070085: 'Numpad ,', + 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', + 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', + 0x000700e0: 'Ctrl', + 0x000700e1: 'Shift', + 0x000700e2: 'Alt', + 0x000700e3: 'Meta', + 0x000700e4: 'Ctrl', + 0x000700e5: 'Shift', + 0x000700e6: 'Alt', + 0x000700e7: 'Meta', + // Consumer + 0x000c0030: 'Power', + 0x000c0032: 'Sleep', + 0x000c0040: 'Menu', + 0x000c0041: 'Menu Pick', + 0x000c0042: 'Menu Up', + 0x000c0043: 'Menu Down', + 0x000c0044: 'Menu Left', + 0x000c0045: 'Menu Right', + 0x000c0046: 'Menu Escape', + 0x000c0047: 'Menu Value Increase', + 0x000c0048: 'Menu Value Decrease', + 0x000c0060: 'Info', + 0x000c0061: 'Closed Caption', + 0x000c0062: 'Closed Caption Select', + 0x000c0063: 'VCR/TV', + 0x000c0064: 'Broadcast Mode', + 0x000c0065: 'Snapshot', + 0x000c0066: 'Still', + 0x000c0067: 'PiP Toggle', + 0x000c0068: 'PiP Swap', + 0x000c0069: 'Red Button', + 0x000c006a: 'Green Button', + 0x000c006b: 'Blue Button', + 0x000c006c: 'Yellow Button', + 0x000c006d: 'Aspect', + 0x000c006e: '3D Mode Select', + 0x000c006f: 'Brightness Up', + 0x000c0070: 'Brightness Down', + 0x000c0072: 'Brightness Toggle', + 0x000c0073: 'Brightness Min', + 0x000c0074: 'Brightness Max', + 0x000c0075: 'Brightness Auto', + 0x000c0079: 'Kbd Illum Up', + 0x000c007a: 'Kbd Illum Down', + 0x000c0082: 'Mode Step', + 0x000c0083: 'Recall Last', + 0x000c0084: 'Enter Channel', + 0x000c0085: 'Order Movie', + 0x000c0086: 'Channel', + 0x000c0088: 'Media Computer', + 0x000c0089: 'Media TV', + 0x000c008a: 'Media WWW', + 0x000c008b: 'Media DVD', + 0x000c008c: 'Media Telephone', + 0x000c008d: 'Program Guide', + 0x000c008e: 'Media Video Phone', + 0x000c008f: 'Media Games', + 0x000c0090: 'Media Messages', + 0x000c0091: 'Media CD', + 0x000c0092: 'Media VCR', + 0x000c0093: 'Media Tuner', + 0x000c0094: 'Quit', + 0x000c0095: 'Help', + 0x000c0096: 'Media Tape', + 0x000c0097: 'Media Cable', + 0x000c0098: 'Media Satellite', + 0x000c0099: 'Media Security', + 0x000c009a: 'Media Home', + 0x000c009b: 'Media Call', + 0x000c009c: 'Channel Up', + 0x000c009d: 'Channel Down', + 0x000c009e: 'Media SAP', + 0x000c00b0: 'Play', + 0x000c00b1: 'Pause', + 0x000c00b2: 'Record', + 0x000c00b3: 'Fast Forward', + 0x000c00b4: 'Rewind', + 0x000c00b5: 'Next Track', + 0x000c00b6: 'Previous Track', + 0x000c00b7: 'Stop', + 0x000c00b8: 'Eject', + 0x000c00b9: 'Random Play', + 0x000c00ba: 'Select Disc', + 0x000c00bb: 'Enter Disc', + 0x000c00bc: 'Repeat', + 0x000c00c0: 'Frame Forward', + 0x000c00c1: 'Frame Back', + 0x000c00cc: 'Stop/Eject', + 0x000c00cd: 'Play/Pause', + 0x000c00ce: 'Play/Skip', + 0x000c00cf: 'Voice Command', + 0x000c00e0: 'Volume', + 0x000c00e2: 'Mute', + 0x000c00e5: 'Bass Boost', + 0x000c00e6: 'Surround Mode', + 0x000c00e7: 'Loudness', + 0x000c00e9: 'Volume Up', + 0x000c00ea: 'Volume Down', + 0x000c0183: 'Media Select', + 0x000c0184: 'Launch Word Processor', + 0x000c0186: 'Launch Spreadsheet', + 0x000c018a: 'Launch Mail', + 0x000c018d: 'Launch Contacts', + 0x000c018e: 'Launch Calendar', + 0x000c0192: 'Launch Calculator', + 0x000c0194: 'Launch File Browser', + 0x000c0196: 'Launch Browser', + 0x000c019c: 'Log Off', + 0x000c019e: 'Lock Screen', + 0x000c019f: 'Launch Control Panel', + 0x000c01a2: 'Select Task', + 0x000c01a7: 'Launch Documents', + 0x000c01ab: 'Spell Check', + 0x000c01ae: 'Launch Keyboard Layout', + 0x000c01b1: 'Launch Screen Saver', + 0x000c01b7: 'Launch Audio Browser', + 0x000c01cb: 'Launch Assistant', + 0x000c0201: 'New', + 0x000c0203: 'Close', + 0x000c0207: 'Save', + 0x000c0208: 'Print', + 0x000c0221: 'Browser Search', + 0x000c0223: 'Browser Home', + 0x000c0224: 'Browser Back', + 0x000c0225: 'Browser Forward', + 0x000c0226: 'Browser Stop', + 0x000c0227: 'Browser Refresh', + 0x000c022a: 'Browser Favorites', + 0x000c022d: 'Zoom In', + 0x000c022e: 'Zoom Out', + 0x000c0232: 'Zoom Toggle', + 0x000c0279: 'Redo', + 0x000c0289: 'Mail Reply', + 0x000c028b: 'Mail Forward', + 0x000c028c: 'Mail Send', + 0x000c029d: 'Keyboard Layout Select', + 0x000c029f: 'Show All Windows', +}; diff --git a/lib/models/hotkey_model.dart b/lib/models/hotkey_model.dart index 49a2ea2b..31b7ddec 100644 --- a/lib/models/hotkey_model.dart +++ b/lib/models/hotkey_model.dart @@ -2,6 +2,8 @@ import 'dart:io' show Platform; import 'package:flutter/services.dart'; +import '../data/hid_key_labels.dart'; + /// Modifier keys that can be combined with a primary key to form a hotkey. /// /// Each value holds the physical keys that correspond to it (e.g. shift maps @@ -40,7 +42,7 @@ String physicalKeyLabel(PhysicalKeyboardKey key) { final macLabel = _macKeyLabels[key.usbHidUsage]; if (macLabel != null) return macLabel; } - return _keyLabels[key.usbHidUsage] ?? 'Unknown'; + return hidKeyLabels[key.usbHidUsage] ?? 'Key 0x${key.usbHidUsage.toRadixString(16).padLeft(8, '0')}'; } /// macOS-specific overrides for keys that have standard symbols. @@ -69,180 +71,3 @@ const _macKeyLabels = { 0x000700e7: '\u2318', // metaRight (Command) → ⌘ 0x00000012: 'fn', // fn }; - -/// 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', - 0x0007003d: 'F4', - 0x0007003e: 'F5', - 0x0007003f: 'F6', - 0x00070040: 'F7', - 0x00070041: 'F8', - 0x00070042: 'F9', - 0x00070043: 'F10', - 0x00070044: 'F11', - 0x00070045: 'F12', - 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', -};