DP/app/js_to_hid.py

166 lines
3.9 KiB
Python
Raw Permalink Normal View History

2023-04-24 11:36:47 +00:00
import dataclasses
class Error(Exception):
pass
class UnrecognizedKeyCodeError(Error):
pass
@dataclasses.dataclass
class JavaScriptKeyEvent:
meta_modifier: bool
alt_modifier: bool
shift_modifier: bool
ctrl_modifier: bool
key: str
key_code: int
# JS keycodes source: https://github.com/wesbos/keycodes
# HID keycodes source: https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
# TODO: For simplicity, we map all modifiers keys to the left key, but we could
# support distinct keys for left and right if we check the location parameter
# from the JavaScript message.
_JS_TO_HID_KEYCODES = {
3: 0x48, # Pause / Break
8: 0x2a, # Backspace / Delete
9: 0x2b, # Tab
12: 0x53, # Clear
13: 0x28, # Enter
16: 0xe1, # Shift (Left)
17: 0xe0, # Ctrl (left)
18: 0xe1, # Alt (left)
19: 0x48, # Pause / Break
20: 0x39, # Caps Lock
21: 0x90, # Hangeul
25: 0x91, # Hanja
27: 0x29, # Escape
32: 0x2c, # Spacebar
33: 0x4b, # Page Up
34: 0x4e, # Page Down
35: 0x4d, # End
36: 0x4a, # Home
37: 0x50, # Left Arrow
38: 0x52, # Up Arrow
39: 0x4f, # Right Arrow
40: 0x51, # Down Arrow
41: 0x77, # Select
43: 0x74, # Execute
44: 0x46, # Print Screen
45: 0x49, # Insert
46: 0x4c, # Delete
47: 0x75, # Help
48: 0x27, # 0
49: 0x1e, # 1
50: 0x1f, # 2
51: 0x20, # 3
52: 0x21, # 4
53: 0x22, # 5
54: 0x23, # 6
55: 0x24, # 7
56: 0x25, # 8
57: 0x26, # 9
59: 0x33, # Semicolon
60: 0xc5, # <
61: 0x2e, # Equal sign
65: 0x04, # a
66: 0x05, # b
67: 0x06, # c
68: 0x07, # d
69: 0x08, # e
70: 0x09, # f
71: 0x0a, # g
72: 0x0b, # h
73: 0x0c, # i
74: 0x0d, # j
75: 0x0e, # k
76: 0x0f, # l
77: 0x10, # m
78: 0x11, # n
79: 0x12, # o
80: 0x13, # p
81: 0x14, # q
82: 0x15, # r
83: 0x16, # s
84: 0x17, # t
85: 0x18, # u
86: 0x19, # v
87: 0x1a, # w
88: 0x1b, # x
89: 0x1c, # y
90: 0x1d, # z
91: 0xe3, # Windows key / Meta Key (Left)
96: 0x62, # Numpad 0
97: 0x59, # Numpad 1
98: 0x5a, # Numpad 2
99: 0x5b, # Numpad 3
100: 0x5c, # Numpad 4
101: 0x5d, # Numpad 5
102: 0x5e, # Numpad 6
103: 0x5f, # Numpad 7
104: 0x60, # Numpad 8
105: 0x61, # Numpad 9
112: 0x3a, # F1
113: 0x3b, # F2
114: 0x3c, # F3
115: 0x3d, # F4
116: 0x3e, # F5
117: 0x3f, # F6
118: 0x40, # F7
119: 0x41, # F8
120: 0x42, # F9
121: 0x43, # F10
122: 0x44, # F11
123: 0x45, # F12
124: 0x68, # F13
125: 0x69, # F14
126: 0x6a, # F15
127: 0x6b, # F16
128: 0x6c, # F17
129: 0x6d, # F18
130: 0x6e, # F19
131: 0x6f, # F20
132: 0x70, # F21
133: 0x71, # F22
134: 0x72, # F23
144: 0x53, # Num Lock
145: 0x47, # Scroll Lock
161: 0x1e, # !
163: 0x32, # Hash
173: 0x2d, # Minus
179: 0xe8, # Media play/pause
168: 0xfa, # Refresh
186: 0x33, # Semicolon
187: 0x2e, # Equal sign
188: 0x36, # Comma
189: 0x2d, # Minus sign
190: 0x37, # Period
191: 0x38, # Forward slash
192: 0x35, # Accent grave
219: 0x2f, # Left bracket ([, {])
220: 0x31, # Back slash
221: 0x30, # Right bracket (], })
222: 0x34, # Single quote
223: 0x35, # Accent grave (`)
}
def convert(js_key_event):
control_chars = 0
for i, pressed in enumerate([
js_key_event.ctrl_modifier, js_key_event.shift_modifier,
js_key_event.alt_modifier, js_key_event.meta_modifier
]):
if pressed:
control_chars |= 1 << i
try:
return control_chars, _JS_TO_HID_KEYCODES[js_key_event.key_code]
except KeyError:
raise UnrecognizedKeyCodeError(
'Unrecognized key code %s (%d)' %
(js_key_event.key, js_key_event.key_code))