-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKB.ck
357 lines (334 loc) · 14 KB
/
KB.ck
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
//-----------------------------------------------------------------------------
// name: KB.ck
// desc: keyboard input for ChuGL and general usage
//
// Tracks which keys are held down at any given time.
// Uses msg.key for this because:
// - consistent across mac and windows
// - differentiates between keys like left shift, right shift
// - msg.which not consistent across platforms
// - msg.ascii doesn't pick up many keys like shift and arrow keys
//
// author: Andrew Zhu Aday (https://ccrma.stanford.edu/~azaday/)
// date: May 2023
//
// note: may eventually want to add this to builtin cpp HID input manager
//-----------------------------------------------------------------------------
public class KB
{
// =========================
// Key mappings from https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
// =========================
/**
* Modifier masks - used for the first byte in the HID report.
* NOTE: The second byte in the report is reserved, 0x00
*/
0x00 => static int KEY_MOD_LCTRL;
0x01 => static int KEY_MOD_LSHIFT;
0x03 => static int KEY_MOD_LALT;
0x07 => static int KEY_MOD_LMETA;
0x0f => static int KEY_MOD_RCTRL;
0x1f => static int KEY_MOD_RSHIFT;
0x3f => static int KEY_MOD_RALT;
0x80 => static int KEY_MOD_RMETA;
/**
* Scan codes - last N slots in the HID report (usually 6).
* 0x00 if no key pressed.
*
* If more than N keys are pressed, the HID reports
* KEY_ERR_OVF in all slots to indicate this condition.
*/
0x00 => static int KEY_NONE; // No key pressed
0x01 => static int KEY_ERR_OVF; // Keyboard Error Roll Over; used for all slots if too many keys are pressed ("Phantom key")
0x04 => static int KEY_A; // Keyboard a and A
0x05 => static int KEY_B; // Keyboard b and B
0x06 => static int KEY_C; // Keyboard c and C
0x07 => static int KEY_D; // Keyboard d and D
0x08 => static int KEY_E; // Keyboard e and E
0x09 => static int KEY_F; // Keyboard f and F
0x0a => static int KEY_G; // Keyboard g and G
0x0b => static int KEY_H; // Keyboard h and H
0x0c => static int KEY_I; // Keyboard i and I
0x0d => static int KEY_J; // Keyboard j and J
0x0e => static int KEY_K; // Keyboard k and K
0x0f => static int KEY_L; // Keyboard l and L
0x10 => static int KEY_M; // Keyboard m and M
0x11 => static int KEY_N; // Keyboard n and N
0x12 => static int KEY_O; // Keyboard o and O
0x13 => static int KEY_P; // Keyboard p and P
0x14 => static int KEY_Q; // Keyboard q and Q
0x15 => static int KEY_R; // Keyboard r and R
0x16 => static int KEY_S; // Keyboard s and S
0x17 => static int KEY_T; // Keyboard t and T
0x18 => static int KEY_U; // Keyboard u and U
0x19 => static int KEY_V; // Keyboard v and V
0x1a => static int KEY_W; // Keyboard w and W
0x1b => static int KEY_X; // Keyboard x and X
0x1c => static int KEY_Y; // Keyboard y and Y
0x1d => static int KEY_Z; // Keyboard z and Z
0x1e => static int KEY_1; // Keyboard 1 and !
0x1f => static int KEY_2; // Keyboard 2 and @
0x20 => static int KEY_3; // Keyboard 3 and #
0x21 => static int KEY_4; // Keyboard 4 and $
0x22 => static int KEY_5; // Keyboard 5 and %
0x23 => static int KEY_6; // Keyboard 6 and ^
0x24 => static int KEY_7; // Keyboard 7 and &
0x25 => static int KEY_8; // Keyboard 8 and *
0x26 => static int KEY_9; // Keyboard 9 and (
0x27 => static int KEY_0; // Keyboard 0 and )
0x28 => static int KEY_ENTER; // Keyboard Return (ENTER)
0x29 => static int KEY_ESC; // Keyboard ESCAPE
0x2a => static int KEY_BACKSPACE; // Keyboard DELETE (Backspace)
0x2b => static int KEY_TAB; // Keyboard Tab
0x2c => static int KEY_SPACE; // Keyboard Spacebar
0x2d => static int KEY_MINUS; // Keyboard - and _
0x2e => static int KEY_EQUAL; // Keyboard = and +
0x2f => static int KEY_LEFTBRACE; // Keyboard [ and {
0x30 => static int KEY_RIGHTBRACE; // Keyboard ] and }
0x31 => static int KEY_BACKSLASH; // Keyboard \ and |
0x32 => static int KEY_HASHTILDE; // Keyboard Non-US # and ~
0x33 => static int KEY_SEMICOLON; // Keyboard ; and :
0x34 => static int KEY_APOSTROPHE; // Keyboard ' and "
0x35 => static int KEY_GRAVE; // Keyboard ` and ~
0x36 => static int KEY_COMMA; // Keyboard , and <
0x37 => static int KEY_DOT; // Keyboard . and >
0x38 => static int KEY_SLASH; // Keyboard / and ?
0x39 => static int KEY_CAPSLOCK; // Keyboard Caps Lock
0x3a => static int KEY_F1; // Keyboard F1
0x3b => static int KEY_F2; // Keyboard F2
0x3c => static int KEY_F3; // Keyboard F3
0x3d => static int KEY_F4; // Keyboard F4
0x3e => static int KEY_F5; // Keyboard F5
0x3f => static int KEY_F6; // Keyboard F6
0x40 => static int KEY_F7; // Keyboard F7
0x41 => static int KEY_F8; // Keyboard F8
0x42 => static int KEY_F9; // Keyboard F9
0x43 => static int KEY_F10; // Keyboard F10
0x44 => static int KEY_F11; // Keyboard F11
0x45 => static int KEY_F12; // Keyboard F12
0x46 => static int KEY_SYSRQ; // Keyboard Print Screen
0x47 => static int KEY_SCROLLLOCK; // Keyboard Scroll Lock
0x48 => static int KEY_PAUSE; // Keyboard Pause
0x49 => static int KEY_INSERT; // Keyboard Insert
0x4a => static int KEY_HOME; // Keyboard Home
0x4b => static int KEY_PAGEUP; // Keyboard Page Up
0x4c => static int KEY_DELETE; // Keyboard Delete Forward
0x4d => static int KEY_END; // Keyboard End
0x4e => static int KEY_PAGEDOWN; // Keyboard Page Down
0x4f => static int KEY_RIGHT; // Keyboard Right Arrow
0x50 => static int KEY_LEFT; // Keyboard Left Arrow
0x51 => static int KEY_DOWN; // Keyboard Down Arrow
0x52 => static int KEY_UP; // Keyboard Up Arrow
0x53 => static int KEY_NUMLOCK; // Keyboard Num Lock and Clear
0x54 => static int KEY_KPSLASH; // Keypad /
0x55 => static int KEY_KPASTERISK; // Keypad *
0x56 => static int KEY_KPMINUS; // Keypad -
0x57 => static int KEY_KPPLUS; // Keypad +
0x58 => static int KEY_KPENTER; // Keypad ENTER
0x59 => static int KEY_KP1; // Keypad 1 and End
0x5a => static int KEY_KP2; // Keypad 2 and Down Arrow
0x5b => static int KEY_KP3; // Keypad 3 and PageDn
0x5c => static int KEY_KP4; // Keypad 4 and Left Arrow
0x5d => static int KEY_KP5; // Keypad 5
0x5e => static int KEY_KP6; // Keypad 6 and Right Arrow
0x5f => static int KEY_KP7; // Keypad 7 and Home
0x60 => static int KEY_KP8; // Keypad 8 and Up Arrow
0x61 => static int KEY_KP9; // Keypad 9 and Page Up
0x62 => static int KEY_KP0; // Keypad 0 and Insert
0x63 => static int KEY_KPDOT; // Keypad . and Delete
0x64 => static int KEY_102ND; // Keyboard Non-US \ and |
0x65 => static int KEY_COMPOSE; // Keyboard Application
0x66 => static int KEY_POWER; // Keyboard Power
0x67 => static int KEY_KPEQUAL; // Keypad =
0x68 => static int KEY_F13; // Keyboard F13
0x69 => static int KEY_F14; // Keyboard F14
0x6a => static int KEY_F15; // Keyboard F15
0x6b => static int KEY_F16; // Keyboard F16
0x6c => static int KEY_F17; // Keyboard F17
0x6d => static int KEY_F18; // Keyboard F18
0x6e => static int KEY_F19; // Keyboard F19
0x6f => static int KEY_F20; // Keyboard F20
0x70 => static int KEY_F21; // Keyboard F21
0x71 => static int KEY_F22; // Keyboard F22
0x72 => static int KEY_F23; // Keyboard F23
0x73 => static int KEY_F24; // Keyboard F24
0x74 => static int KEY_OPEN; // Keyboard Execute
0x75 => static int KEY_HELP; // Keyboard Help
0x76 => static int KEY_PROPS; // Keyboard Menu
0x77 => static int KEY_FRONT; // Keyboard Select
0x78 => static int KEY_STOP; // Keyboard Stop
0x79 => static int KEY_AGAIN; // Keyboard Again
0x7a => static int KEY_UNDO; // Keyboard Undo
0x7b => static int KEY_CUT; // Keyboard Cut
0x7c => static int KEY_COPY; // Keyboard Copy
0x7d => static int KEY_PASTE; // Keyboard Paste
0x7e => static int KEY_FIND; // Keyboard Find
0x7f => static int KEY_MUTE; // Keyboard Mute
0x80 => static int KEY_VOLUMEUP; // Keyboard Volume Up
0x81 => static int KEY_VOLUMEDOWN; // Keyboard Volume Down
0x85 => static int KEY_KPCOMMA; // Keypad Comma
0x87 => static int KEY_RO; // Keyboard International1
0x88 => static int KEY_KATAKANAHIRAGANA; // Keyboard International2
0x89 => static int KEY_YEN; // Keyboard International3
0x8a => static int KEY_HENKAN; // Keyboard International4
0x8b => static int KEY_MUHENKAN; // Keyboard International5
0x8c => static int KEY_KPJPCOMMA; // Keyboard International6
0x90 => static int KEY_HANGEUL; // Keyboard LANG1
0x91 => static int KEY_HANJA; // Keyboard LANG2
0x92 => static int KEY_KATAKANA; // Keyboard LANG3
0x93 => static int KEY_HIRAGANA; // Keyboard LANG4
0x94 => static int KEY_ZENKAKUHANKAKU; // Keyboard LANG5
0xb6 => static int KEY_KPLEFTPAREN; // Keypad (
0xb7 => static int KEY_KPRIGHTPAREN; // Keypad )
0xe0 => static int KEY_LEFTCTRL; // Keyboard Left Control
0xe1 => static int KEY_LEFTSHIFT; // Keyboard Left Shift
0xe2 => static int KEY_LEFTALT; // Keyboard Left Alt
0xe3 => static int KEY_LEFTMETA; // Keyboard Left GUI
0xe4 => static int KEY_RIGHTCTRL; // Keyboard Right Control
0xe5 => static int KEY_RIGHTSHIFT; // Keyboard Right Shift
0xe6 => static int KEY_RIGHTALT; // Keyboard Right Alt
0xe7 => static int KEY_RIGHTMETA; // Keyboard Right GUI
0xe8 => static int KEY_MEDIA_PLAYPAUSE;
0xe9 => static int KEY_MEDIA_STOPCD;
0xea => static int KEY_MEDIA_PREVIOUSSONG;
0xeb => static int KEY_MEDIA_NEXTSONG;
0xec => static int KEY_MEDIA_EJECTCD;
0xed => static int KEY_MEDIA_VOLUMEUP;
0xee => static int KEY_MEDIA_VOLUMEDOWN;
0xef => static int KEY_MEDIA_MUTE;
0xf0 => static int KEY_MEDIA_WWW;
0xf1 => static int KEY_MEDIA_BACK;
0xf2 => static int KEY_MEDIA_FORWARD;
0xf3 => static int KEY_MEDIA_STOP;
0xf4 => static int KEY_MEDIA_FIND;
0xf5 => static int KEY_MEDIA_SCROLLUP;
0xf6 => static int KEY_MEDIA_SCROLLDOWN;
0xf7 => static int KEY_MEDIA_EDIT;
0xf8 => static int KEY_MEDIA_SLEEP;
0xf9 => static int KEY_MEDIA_COFFEE;
0xfa => static int KEY_MEDIA_REFRESH;
0xfb => static int KEY_MEDIA_CALC;
// open kb devices
static KBManager devices[];
// init flag
static int isInit;
// starts all keyboard devices
fun static void initialize()
{
// test flag
if( isInit ) return;
// set flag
true => isInit;
// num to open
int num;
Hid tester;
while( true )
{
// try to open keyboard
if( !tester.openKeyboard( num, true ) ) break;
// create a new manager
KBManager kb;
// start it
spork ~ kb.start( num );
// append it
devices << kb;
// increment it
num++;
}
}
// get number of KB devices
fun static int numDevices()
{
return devices.size();
}
// is key down (on any device?)
fun static int isKeyDown(int keycode)
{
// iterate over all open devices
for( auto device : devices )
if( device.isKeyDown(keycode) ) return true;
// not found, the key is not down on any device
return false;
}
fun static Event @ keyDownEvent(int keycode, int whichDevice) {
// in bound?
if( whichDevice < 0 || whichDevice >= devices.size() ) return null;
// return event on the specified device
return devices[whichDevice].keyDownEvent( keycode );
}
fun static Event @ keyDownEvent(int keycode, string nameSubstr) {
// iterate over all open devices
for( auto device : devices )
if( device.name().find(nameSubstr) >= 0 ) return device.keyDownEvent(keycode);
// no match for name
return null;
}
fun static void start()
{
// check flag
if( isInit ) return;
// HACK just to initialize the pre-ctor
KB kb;
// start it
KB.initialize();
// keep all child shreds in play
while( true ) eon => now;
}
}
// do this once
if( KB.isInit ) me.exit();
// static instantiate (hack)
new KBManager[0] @=> KB.devices;
// start
KB.start();
// KBManager class (not public, used by KB)
class KBManager
{
// state
-1 => int lastKeyPressed;
// events
Event keyDownEvents[0xff];
Event anyKeyDownEvent;
// name of the device
string deviceName;
// state vector
int keyState[0xff]; // keycodes are 1byte, max size is 2^8 = 256
fun int isKeyDown(int keycode) {
if (keycode < 0 || keycode >= keyState.size()) { return 0; }
return keyState[keycode];
}
fun Event @ keyDownEvent(int keycode) {
return keyDownEvents[keycode];
}
fun string name() { return deviceName; }
// start listening for kbd input and tracking state
fun void start(int device) {
Hid hi;
HidMsg msg;
// open keyboard (get device number from command line)
if( !hi.openKeyboard( device ) ) {
cherr <= "keyboard " + device + " not found" <= IO.newline();
me.exit();
}
<<< "keyboard '" + hi.name() + "' ready", "" >>>;
hi.name() => this.deviceName;
while( true )
{
hi => now;
while( hi.recv( msg ) )
{
if( msg.isButtonDown() )
{
msg.key => lastKeyPressed;
1 => keyState[msg.key];
keyDownEvents[msg.key].broadcast();
anyKeyDownEvent.broadcast();
}
else // button up
{
0 => keyState[msg.key];
}
}
}
}
}