@mukea/uiohook-napi 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/binding.gyp +85 -0
- package/dist/index.d.ts +194 -0
- package/dist/index.js +206 -0
- package/dist/index.js.map +1 -0
- package/dist/prebuild-test-noop.d.ts +0 -0
- package/dist/prebuild-test-noop.js +3 -0
- package/dist/prebuild-test-noop.js.map +1 -0
- package/libuiohook/include/uiohook.h +457 -0
- package/libuiohook/src/darwin/input_helper.c +535 -0
- package/libuiohook/src/darwin/input_helper.h +203 -0
- package/libuiohook/src/darwin/input_hook.c +1436 -0
- package/libuiohook/src/darwin/post_event.c +303 -0
- package/libuiohook/src/darwin/system_properties.c +479 -0
- package/libuiohook/src/logger.c +40 -0
- package/libuiohook/src/logger.h +32 -0
- package/libuiohook/src/windows/input_helper.c +913 -0
- package/libuiohook/src/windows/input_helper.h +146 -0
- package/libuiohook/src/windows/input_hook.c +722 -0
- package/libuiohook/src/windows/post_event.c +248 -0
- package/libuiohook/src/windows/system_properties.c +231 -0
- package/libuiohook/src/x11/input_helper.c +1846 -0
- package/libuiohook/src/x11/input_helper.h +108 -0
- package/libuiohook/src/x11/input_hook.c +1116 -0
- package/libuiohook/src/x11/post_event.c +427 -0
- package/libuiohook/src/x11/system_properties.c +494 -0
- package/package.json +60 -0
- package/prebuilds/darwin/darwin-arm64/@mukea+uiohook-napi.node +0 -0
- package/prebuilds/darwin/darwin-x64/@mukea+uiohook-napi.node +0 -0
- package/prebuilds/linux/linux-arm64/@mukea+uiohook-napi.node +0 -0
- package/prebuilds/linux/linux-x64/@mukea+uiohook-napi.node +0 -0
- package/prebuilds/windows/win32-x64/@mukea+uiohook-napi.node +0 -0
- package/src/lib/addon.c +337 -0
- package/src/lib/napi_helpers.c +51 -0
- package/src/lib/napi_helpers.h +53 -0
- package/src/lib/uiohook_worker.c +200 -0
- package/src/lib/uiohook_worker.h +12 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/* libUIOHook: Cross-platform keyboard and mouse hooking from userland.
|
|
2
|
+
* Copyright (C) 2006-2023 Alexander Barker. All Rights Reserved.
|
|
3
|
+
* https://github.com/kwhat/libuiohook/
|
|
4
|
+
*
|
|
5
|
+
* libUIOHook is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Lesser General Public License as published
|
|
7
|
+
* by the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
* (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* libUIOHook is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#ifdef USE_APPLICATION_SERVICES
|
|
20
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
21
|
+
#endif
|
|
22
|
+
#ifndef USE_WEAK_IMPORT
|
|
23
|
+
#include <dlfcn.h>
|
|
24
|
+
#endif
|
|
25
|
+
#include <stdbool.h>
|
|
26
|
+
#include <uiohook.h>
|
|
27
|
+
|
|
28
|
+
#include "input_helper.h"
|
|
29
|
+
#include "logger.h"
|
|
30
|
+
|
|
31
|
+
// Current dead key state.
|
|
32
|
+
#if defined(USE_CARBON_LEGACY) || defined(USE_APPLICATION_SERVICES)
|
|
33
|
+
static UInt32 deadkey_state;
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
// Input source data for the keyboard.
|
|
37
|
+
#if defined(USE_CARBON_LEGACY)
|
|
38
|
+
static KeyboardLayoutRef prev_keyboard_layout = NULL;
|
|
39
|
+
#elif defined(USE_APPLICATION_SERVICES)
|
|
40
|
+
static TISInputSourceRef prev_keyboard_layout = NULL;
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
bool is_accessibility_enabled() {
|
|
44
|
+
bool is_enabled = false;
|
|
45
|
+
|
|
46
|
+
// Dynamically load the application services framework for examination.
|
|
47
|
+
Boolean (*AXIsProcessTrustedWithOptions_t)(CFDictionaryRef);
|
|
48
|
+
*(void **) (&AXIsProcessTrustedWithOptions_t) = dlsym(RTLD_DEFAULT, "AXIsProcessTrustedWithOptions");
|
|
49
|
+
const char *dlError = dlerror();
|
|
50
|
+
if (AXIsProcessTrustedWithOptions_t != NULL) {
|
|
51
|
+
// Check for property CFStringRef kAXTrustedCheckOptionPrompt
|
|
52
|
+
void ** kAXTrustedCheckOptionPrompt_t = dlsym(RTLD_DEFAULT, "kAXTrustedCheckOptionPrompt");
|
|
53
|
+
|
|
54
|
+
dlError = dlerror();
|
|
55
|
+
if (dlError != NULL) {
|
|
56
|
+
// Could not load the AXIsProcessTrustedWithOptions function!
|
|
57
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: %s.\n",
|
|
58
|
+
__FUNCTION__, __LINE__, dlError);
|
|
59
|
+
} else if (kAXTrustedCheckOptionPrompt_t != NULL) {
|
|
60
|
+
// New accessibility API 10.9 and later.
|
|
61
|
+
const void * keys[] = { *kAXTrustedCheckOptionPrompt_t };
|
|
62
|
+
const void * values[] = { kCFBooleanTrue };
|
|
63
|
+
|
|
64
|
+
CFDictionaryRef options = CFDictionaryCreate(
|
|
65
|
+
kCFAllocatorDefault,
|
|
66
|
+
keys,
|
|
67
|
+
values,
|
|
68
|
+
sizeof(keys) / sizeof(*keys),
|
|
69
|
+
&kCFCopyStringDictionaryKeyCallBacks,
|
|
70
|
+
&kCFTypeDictionaryValueCallBacks);
|
|
71
|
+
|
|
72
|
+
is_enabled = (*AXIsProcessTrustedWithOptions_t)(options);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
if (dlError != NULL) {
|
|
76
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: %s.\n",
|
|
77
|
+
__FUNCTION__, __LINE__, dlError);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: AXIsProcessTrustedWithOptions not found.\n",
|
|
81
|
+
__FUNCTION__, __LINE__);
|
|
82
|
+
|
|
83
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: Falling back to AXAPIEnabled().\n",
|
|
84
|
+
__FUNCTION__, __LINE__);
|
|
85
|
+
|
|
86
|
+
// Old accessibility check 10.8 and older.
|
|
87
|
+
Boolean (*AXAPIEnabled_f)();
|
|
88
|
+
*(void **) (&AXAPIEnabled_f) = dlsym(RTLD_DEFAULT, "AXAPIEnabled");
|
|
89
|
+
dlError = dlerror();
|
|
90
|
+
if (dlError != NULL) {
|
|
91
|
+
// Could not load the AXIsProcessTrustedWithOptions function!
|
|
92
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: %s.\n",
|
|
93
|
+
__FUNCTION__, __LINE__, dlError);
|
|
94
|
+
} else if (AXAPIEnabled_f != NULL) {
|
|
95
|
+
is_enabled = (*AXAPIEnabled_f)();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return is_enabled;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
UniCharCount keycode_to_unicode(CGEventRef event_ref, UniChar *buffer, UniCharCount size) {
|
|
104
|
+
UniCharCount count = 0;
|
|
105
|
+
CFDataRef inputData = NULL;
|
|
106
|
+
|
|
107
|
+
#if defined(USE_CARBON_LEGACY)
|
|
108
|
+
KeyboardLayoutRef curr_keyboard_layout;
|
|
109
|
+
if (KLGetCurrentKeyboardLayout(&curr_keyboard_layout) == noErr) {
|
|
110
|
+
if (KLGetKeyboardLayoutProperty(curr_keyboard_layout, kKLuchrData, (const void **) &inputData) != noErr) {
|
|
111
|
+
inputData = NULL;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
#elif defined(USE_APPLICATION_SERVICES)
|
|
115
|
+
// TODO Try https://developer.apple.com/documentation/coregraphics/1456120-cgeventkeyboardgetunicodestring?language=objc
|
|
116
|
+
if (CFEqual(CFRunLoopGetCurrent(), CFRunLoopGetMain())) {
|
|
117
|
+
// NOTE The following block must execute on the main runloop,
|
|
118
|
+
// Ex: CFEqual(CFRunLoopGetCurrent(), CFRunLoopGetMain()) to avoid
|
|
119
|
+
// Exception detected while handling key input and TSMProcessRawKeyCode failed
|
|
120
|
+
// (-192) errors.
|
|
121
|
+
TISInputSourceRef curr_keyboard_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
|
122
|
+
if (curr_keyboard_layout != NULL && CFGetTypeID(curr_keyboard_layout) == TISInputSourceGetTypeID()) {
|
|
123
|
+
CFDataRef data = (CFDataRef) TISGetInputSourceProperty(curr_keyboard_layout, kTISPropertyUnicodeKeyLayoutData);
|
|
124
|
+
if (data != NULL && CFGetTypeID(data) == CFDataGetTypeID() && CFDataGetLength(data) > 0) {
|
|
125
|
+
inputData = (CFDataRef) data;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check if the keyboard layout has changed to see if the dead key state needs to be discarded.
|
|
130
|
+
if (prev_keyboard_layout != NULL && curr_keyboard_layout != NULL && CFEqual(curr_keyboard_layout, prev_keyboard_layout) == false) {
|
|
131
|
+
deadkey_state = 0x00;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Release the previous keyboard layout.
|
|
135
|
+
if (prev_keyboard_layout != NULL) {
|
|
136
|
+
CFRelease(prev_keyboard_layout);
|
|
137
|
+
prev_keyboard_layout = NULL;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Set the previous keyboard layout to the current layout.
|
|
141
|
+
if (curr_keyboard_layout != NULL) {
|
|
142
|
+
prev_keyboard_layout = curr_keyboard_layout;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
#endif
|
|
146
|
+
|
|
147
|
+
#if defined(USE_CARBON_LEGACY) || defined(USE_APPLICATION_SERVICES)
|
|
148
|
+
if (inputData != NULL) {
|
|
149
|
+
#ifdef USE_CARBON_LEGACY
|
|
150
|
+
const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout *) inputData;
|
|
151
|
+
#else
|
|
152
|
+
const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout*) CFDataGetBytePtr(inputData);
|
|
153
|
+
#endif
|
|
154
|
+
|
|
155
|
+
if (keyboard_layout != NULL) {
|
|
156
|
+
//Extract keycode and modifier information.
|
|
157
|
+
CGKeyCode keycode = CGEventGetIntegerValueField(event_ref, kCGKeyboardEventKeycode);
|
|
158
|
+
CGEventFlags modifiers = CGEventGetFlags(event_ref);
|
|
159
|
+
|
|
160
|
+
// Disable all command modifiers for translation. This is required
|
|
161
|
+
// so UCKeyTranslate will provide a keysym for the separate event.
|
|
162
|
+
static const CGEventFlags cmd_modifiers = kCGEventFlagMaskCommand |
|
|
163
|
+
kCGEventFlagMaskControl | kCGEventFlagMaskAlternate;
|
|
164
|
+
modifiers &= ~cmd_modifiers;
|
|
165
|
+
|
|
166
|
+
// I don't know why but UCKeyTranslate does not process the
|
|
167
|
+
// kCGEventFlagMaskAlphaShift (A.K.A. Caps Lock Mask) correctly.
|
|
168
|
+
// We need to basically turn off the mask and process the capital
|
|
169
|
+
// letters after UCKeyTranslate().
|
|
170
|
+
bool is_caps_lock = modifiers & kCGEventFlagMaskAlphaShift;
|
|
171
|
+
modifiers &= ~kCGEventFlagMaskAlphaShift;
|
|
172
|
+
|
|
173
|
+
// Run the translation with the saved deadkey_state.
|
|
174
|
+
OSStatus status = UCKeyTranslate(
|
|
175
|
+
keyboard_layout,
|
|
176
|
+
keycode,
|
|
177
|
+
kUCKeyActionDown, //kUCKeyActionDisplay,
|
|
178
|
+
(modifiers >> 16) & 0xFF, //(modifiers >> 16) & 0xFF, || (modifiers >> 8) & 0xFF,
|
|
179
|
+
LMGetKbdType(),
|
|
180
|
+
kNilOptions, //kNilOptions, //kUCKeyTranslateNoDeadKeysMask
|
|
181
|
+
&deadkey_state,
|
|
182
|
+
size,
|
|
183
|
+
&count,
|
|
184
|
+
buffer);
|
|
185
|
+
|
|
186
|
+
if (status == noErr && count > 0) {
|
|
187
|
+
if (is_caps_lock) {
|
|
188
|
+
// We *had* a caps lock mask so we need to convert to uppercase.
|
|
189
|
+
CFMutableStringRef keytxt = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault, buffer, count, size, kCFAllocatorNull);
|
|
190
|
+
if (keytxt != NULL) {
|
|
191
|
+
CFLocaleRef locale = CFLocaleCopyCurrent();
|
|
192
|
+
CFStringUppercase(keytxt, locale);
|
|
193
|
+
CFRelease(locale);
|
|
194
|
+
CFRelease(keytxt);
|
|
195
|
+
} else {
|
|
196
|
+
// There was an problem creating the CFMutableStringRef.
|
|
197
|
+
count = 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
// Make sure the buffer count is zero if an error occurred.
|
|
202
|
+
count = 0;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
#else
|
|
207
|
+
CGEventKeyboardGetUnicodeString(event_ref, size, &count, buffer);
|
|
208
|
+
#endif
|
|
209
|
+
|
|
210
|
+
// The following codes should not be processed because they are invalid.
|
|
211
|
+
if (count == 1) {
|
|
212
|
+
switch (buffer[0]) {
|
|
213
|
+
case 0x01: // Home
|
|
214
|
+
case 0x04: // End
|
|
215
|
+
case 0x05: // Help Key
|
|
216
|
+
case 0x10: // Function Keys
|
|
217
|
+
case 0x0B: // Page Up
|
|
218
|
+
case 0x0C: // Page Down
|
|
219
|
+
case 0x1F: // Volume Up
|
|
220
|
+
count = 0;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return count;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
static const uint16_t keycode_scancode_table[][2] = {
|
|
229
|
+
/* idx { keycode, scancode }, */
|
|
230
|
+
/* 0 */ { VC_A, kVK_Undefined }, // 0x00
|
|
231
|
+
/* 1 */ { VC_S, kVK_Escape }, // 0x01
|
|
232
|
+
/* 2 */ { VC_D, kVK_ANSI_1 }, // 0x02
|
|
233
|
+
/* 3 */ { VC_F, kVK_ANSI_2 }, // 0x03
|
|
234
|
+
/* 4 */ { VC_H, kVK_ANSI_3 }, // 0x04
|
|
235
|
+
/* 5 */ { VC_G, kVK_ANSI_4 }, // 0x05
|
|
236
|
+
/* 6 */ { VC_Z, kVK_ANSI_5 }, // 0x07
|
|
237
|
+
/* 7 */ { VC_X, kVK_ANSI_6 }, // 0x08
|
|
238
|
+
/* 8 */ { VC_C, kVK_ANSI_7 }, // 0x09
|
|
239
|
+
/* 9 */ { VC_V, kVK_ANSI_8 }, // 0x0A
|
|
240
|
+
/* 10 */ { VC_UNDEFINED, kVK_ANSI_9 }, // 0x0B
|
|
241
|
+
/* 11 */ { VC_B, kVK_ANSI_0 }, // 0x0C
|
|
242
|
+
/* 12 */ { VC_Q, kVK_ANSI_Minus }, // 0x0D
|
|
243
|
+
/* 13 */ { VC_W, kVK_ANSI_Equal }, // 0x0E
|
|
244
|
+
/* 14 */ { VC_E, kVK_Delete }, // 0x0F
|
|
245
|
+
/* 15 */ { VC_R, kVK_Tab }, // 0x10
|
|
246
|
+
/* 16 */ { VC_Y, kVK_ANSI_Q }, // 0x11
|
|
247
|
+
/* 17 */ { VC_T, kVK_ANSI_W }, // 0x12
|
|
248
|
+
/* 18 */ { VC_1, kVK_ANSI_E }, // 0x13
|
|
249
|
+
/* 19 */ { VC_2, kVK_ANSI_R }, // 0x14
|
|
250
|
+
/* 20 */ { VC_3, kVK_ANSI_T }, // 0x15
|
|
251
|
+
/* 21 */ { VC_4, kVK_ANSI_Y }, // 0x16
|
|
252
|
+
/* 22 */ { VC_6, kVK_ANSI_U }, // 0x17
|
|
253
|
+
/* 23 */ { VC_5, kVK_ANSI_I }, // 0x18
|
|
254
|
+
/* 24 */ { VC_EQUALS, kVK_ANSI_O }, // 0x19
|
|
255
|
+
/* 25 */ { VC_9, kVK_ANSI_P }, // 0x19
|
|
256
|
+
/* 26 */ { VC_7, kVK_ANSI_LeftBracket }, // 0x1A
|
|
257
|
+
/* 27 */ { VC_MINUS, kVK_ANSI_RightBracket }, // 0x1B
|
|
258
|
+
/* 28 */ { VC_8, kVK_Return }, // 0x1C
|
|
259
|
+
/* 29 */ { VC_0, kVK_Control }, // 0x1D
|
|
260
|
+
/* 30 */ { VC_CLOSE_BRACKET, kVK_ANSI_A }, // 0x1E
|
|
261
|
+
/* 31 */ { VC_O, kVK_ANSI_S }, // 0x1F
|
|
262
|
+
/* 32 */ { VC_U, kVK_ANSI_D }, // 0x20
|
|
263
|
+
/* 33 */ { VC_OPEN_BRACKET, kVK_ANSI_F }, // 0x21
|
|
264
|
+
/* 34 */ { VC_I, kVK_ANSI_G }, // 0x22
|
|
265
|
+
/* 35 */ { VC_P, kVK_ANSI_H }, // 0x23
|
|
266
|
+
/* 36 */ { VC_ENTER, kVK_ANSI_J }, // 0x24
|
|
267
|
+
/* 37 */ { VC_L, kVK_ANSI_K }, // 0x25
|
|
268
|
+
/* 38 */ { VC_J, kVK_ANSI_L }, // 0x26
|
|
269
|
+
/* 39 */ { VC_QUOTE, kVK_ANSI_Semicolon }, // 0x27
|
|
270
|
+
/* 40 */ { VC_K, kVK_ANSI_Quote }, // 0x28
|
|
271
|
+
/* 41 */ { VC_SEMICOLON, kVK_ANSI_Grave }, // 0x29
|
|
272
|
+
/* 42 */ { VC_BACK_SLASH, kVK_Shift }, // 0x2A
|
|
273
|
+
/* 43 */ { VC_COMMA, kVK_ANSI_Backslash }, // 0x2B
|
|
274
|
+
/* 44 */ { VC_SLASH, kVK_ANSI_Z }, // 0x2C
|
|
275
|
+
/* 45 */ { VC_N, kVK_ANSI_X }, // 0x2D
|
|
276
|
+
/* 46 */ { VC_M, kVK_ANSI_C }, // 0x2E
|
|
277
|
+
/* 47 */ { VC_PERIOD, kVK_ANSI_V }, // 0x2F
|
|
278
|
+
/* 48 */ { VC_TAB, kVK_ANSI_B }, // 0x30
|
|
279
|
+
/* 49 */ { VC_SPACE, kVK_ANSI_N }, // 0x31
|
|
280
|
+
/* 50 */ { VC_BACKQUOTE, kVK_ANSI_M }, // 0x32
|
|
281
|
+
/* 51 */ { VC_BACKSPACE, kVK_ANSI_Comma }, // 0x33
|
|
282
|
+
/* 52 */ { VC_UNDEFINED, kVK_ANSI_Period }, // 0x34
|
|
283
|
+
/* 53 */ { VC_ESCAPE, kVK_ANSI_Slash }, // 0x35
|
|
284
|
+
/* 54 */ { VC_META_R, kVK_RightShift }, // 0x36
|
|
285
|
+
/* 55 */ { VC_META_L, kVK_ANSI_KeypadMultiply }, // 0x37
|
|
286
|
+
/* 56 */ { VC_SHIFT_L, kVK_Option }, // 0x38
|
|
287
|
+
/* 57 */ { VC_CAPS_LOCK, kVK_Space }, // 0x39
|
|
288
|
+
/* 58 */ { VC_ALT_L, kVK_CapsLock }, // 0x3A
|
|
289
|
+
/* 59 */ { VC_CONTROL_L, kVK_F1 }, // 0x3B
|
|
290
|
+
/* 60 */ { VC_SHIFT_R, kVK_F2 }, // 0x3C
|
|
291
|
+
/* 61 */ { VC_ALT_R, kVK_F3 }, // 0x3D
|
|
292
|
+
/* 62 */ { VC_CONTROL_R, kVK_F4 }, // 0x3E
|
|
293
|
+
/* 63 */ { VC_UNDEFINED, kVK_F5 }, // 0x3F
|
|
294
|
+
/* 64 */ { VC_F17, kVK_F6 }, // 0x40
|
|
295
|
+
/* 65 */ { VC_KP_SEPARATOR, kVK_F7 }, // 0x41
|
|
296
|
+
/* 66 */ { VC_UNDEFINED, kVK_F8 }, // 0x42
|
|
297
|
+
/* 67 */ { VC_KP_MULTIPLY, kVK_F9 }, // 0x43
|
|
298
|
+
/* 68 */ { VC_UNDEFINED, kVK_F10 }, // 0x44
|
|
299
|
+
/* 69 */ { VC_KP_ADD, kVK_ANSI_KeypadClear }, // 0x45
|
|
300
|
+
/* 70 */ { VC_UNDEFINED, kVK_Undefined }, // 0x46
|
|
301
|
+
/* 71 */ { VC_NUM_LOCK, kVK_ANSI_Keypad7 }, // 0x47
|
|
302
|
+
/* 72 */ { VC_VOLUME_UP, kVK_ANSI_Keypad8 }, // 0x48
|
|
303
|
+
/* 73 */ { VC_VOLUME_DOWN, kVK_ANSI_Keypad9 }, // 0x49
|
|
304
|
+
/* 74 */ { VC_VOLUME_MUTE, kVK_ANSI_KeypadMinus }, // 0x4A
|
|
305
|
+
/* 75 */ { VC_KP_DIVIDE, kVK_ANSI_Keypad4 }, // 0x4B
|
|
306
|
+
/* 76 */ { VC_KP_ENTER, kVK_ANSI_Keypad5 }, // 0x4C
|
|
307
|
+
/* 77 */ { VC_UNDEFINED, kVK_ANSI_Keypad6 }, // 0x4D
|
|
308
|
+
/* 78 */ { VC_KP_SUBTRACT, kVK_ANSI_KeypadPlus }, // 0x4E
|
|
309
|
+
/* 79 */ { VC_F18, kVK_ANSI_Keypad1 }, // 0x4F
|
|
310
|
+
/* 80 */ { VC_F19, kVK_ANSI_Keypad2 }, // 0x50
|
|
311
|
+
/* 81 */ { VC_KP_EQUALS, kVK_ANSI_Keypad3 }, // 0x51
|
|
312
|
+
/* 82 */ { VC_KP_0, kVK_ANSI_Keypad0 }, // 0x52
|
|
313
|
+
/* 83 */ { VC_KP_1, kVK_ANSI_KeypadDecimal }, // 0x53
|
|
314
|
+
/* 84 */ { VC_KP_2, kVK_Undefined }, // 0x54
|
|
315
|
+
/* 85 */ { VC_KP_3, kVK_Undefined }, // 0x55
|
|
316
|
+
/* 86 */ { VC_KP_4, kVK_Undefined }, // 0x56
|
|
317
|
+
/* 87 */ { VC_KP_5, kVK_F11 }, // 0x57
|
|
318
|
+
/* 88 */ { VC_KP_6, kVK_F12 }, // 0x58
|
|
319
|
+
/* 89 */ { VC_KP_7, kVK_Undefined }, // 0x59
|
|
320
|
+
/* 90 */ { VC_F20, kVK_Undefined }, // 0x5A
|
|
321
|
+
/* 91 */ { VC_KP_8, kVK_F13 }, // 0x5B
|
|
322
|
+
/* 92 */ { VC_KP_9, kVK_F14 }, // 0x5C
|
|
323
|
+
/* 93 */ { VC_YEN, kVK_F15 }, // 0x5D
|
|
324
|
+
/* 94 */ { VC_UNDERSCORE, kVK_Undefined }, // 0x5E
|
|
325
|
+
/* 95 */ { VC_KP_COMMA, kVK_Undefined }, // 0x5F
|
|
326
|
+
/* 96 */ { VC_F5, kVK_Undefined }, // 0x60
|
|
327
|
+
/* 97 */ { VC_F6, kVK_Undefined }, // 0x61
|
|
328
|
+
/* 98 */ { VC_F7, kVK_Undefined }, // 0x62
|
|
329
|
+
/* 99 */ { VC_F3, kVK_F16 }, // 0x63
|
|
330
|
+
/* 100 */ { VC_F8, kVK_F17 }, // 0x64
|
|
331
|
+
/* 101 */ { VC_F9, kVK_F18 }, // 0x65
|
|
332
|
+
/* 102 */ { VC_UNDEFINED, kVK_F19 }, // 0x66
|
|
333
|
+
/* 103 */ { VC_F11, kVK_F20 }, // 0x67
|
|
334
|
+
/* 104 */ { VC_KATAKANA, kVK_Undefined }, // 0x68
|
|
335
|
+
/* 105 */ { VC_F13, kVK_Undefined }, // 0x69
|
|
336
|
+
/* 106 */ { VC_F16, kVK_Undefined }, // 0x6A
|
|
337
|
+
/* 107 */ { VC_F14, kVK_Undefined }, // 0x6B
|
|
338
|
+
/* 108 */ { VC_UNDEFINED, kVK_Undefined }, // 0x6C FIXME kVK_JIS_Eisu same as Caps Lock ?
|
|
339
|
+
/* 109 */ { VC_F10, kVK_Undefined }, // 0x6D
|
|
340
|
+
/* 110 */ { VC_UNDEFINED, kVK_Undefined }, // 0x6E
|
|
341
|
+
/* 111 */ { VC_F12, kVK_Undefined }, // 0x6F
|
|
342
|
+
/* 112 */ { VC_UNDEFINED, kVK_JIS_Kana }, // 0x70
|
|
343
|
+
/* 113 */ { VC_F15, kVK_Undefined }, // 0x71
|
|
344
|
+
/* 114 */ { VC_INSERT, kVK_Undefined }, // 0x72
|
|
345
|
+
/* 115 */ { VC_HOME, kVK_JIS_Underscore }, // 0x73
|
|
346
|
+
/* 116 */ { VC_PAGE_UP, kVK_Undefined }, // 0x74
|
|
347
|
+
/* 117 */ { VC_DELETE, kVK_Undefined }, // 0x75
|
|
348
|
+
/* 118 */ { VC_F4, kVK_Undefined }, // 0x76
|
|
349
|
+
/* 119 */ { VC_END, kVK_Undefined }, // 0x77
|
|
350
|
+
/* 120 */ { VC_F2, kVK_Undefined }, // 0x78
|
|
351
|
+
/* 121 */ { VC_PAGE_DOWN, kVK_Undefined }, // 0x79
|
|
352
|
+
/* 122 */ { VC_F1, kVK_Undefined }, // 0x7A
|
|
353
|
+
/* 123 */ { VC_LEFT, kVK_Undefined }, // 0x7B
|
|
354
|
+
/* 124 */ { VC_RIGHT, kVK_Undefined }, // 0x7C
|
|
355
|
+
/* 125 */ { VC_DOWN, kVK_JIS_Yen }, // 0x7D
|
|
356
|
+
/* 126 */ { VC_UP, kVK_JIS_KeypadComma }, // 0x7E
|
|
357
|
+
/* 127 */ { VC_UNDEFINED, kVK_Undefined }, // 0x7F
|
|
358
|
+
|
|
359
|
+
// No Offset Offset (i & 0x007F) + 128
|
|
360
|
+
|
|
361
|
+
/* 128 */ { VC_UNDEFINED, kVK_Undefined }, // 0x80
|
|
362
|
+
/* 129 */ { VC_UNDEFINED, kVK_Undefined }, // 0x81
|
|
363
|
+
/* 130 */ { VC_UNDEFINED, kVK_Undefined }, // 0x82
|
|
364
|
+
/* 131 */ { VC_UNDEFINED, kVK_Undefined }, // 0x83
|
|
365
|
+
/* 132 */ { VC_UNDEFINED, kVK_Undefined }, // 0x84
|
|
366
|
+
/* 133 */ { VC_UNDEFINED, kVK_Undefined }, // 0x85
|
|
367
|
+
/* 134 */ { VC_UNDEFINED, kVK_Undefined }, // 0x86
|
|
368
|
+
/* 135 */ { VC_UNDEFINED, kVK_Undefined }, // 0x87
|
|
369
|
+
/* 136 */ { VC_UNDEFINED, kVK_Undefined }, // 0x88
|
|
370
|
+
/* 137 */ { VC_UNDEFINED, kVK_Undefined }, // 0x89
|
|
371
|
+
/* 138 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8A
|
|
372
|
+
/* 139 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8B
|
|
373
|
+
/* 140 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8C
|
|
374
|
+
/* 141 */ { VC_UNDEFINED, kVK_ANSI_KeypadEquals }, // 0x8D
|
|
375
|
+
/* 142 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8E
|
|
376
|
+
/* 143 */ { VC_UNDEFINED, kVK_Undefined }, // 0x8F
|
|
377
|
+
/* 144 */ { VC_UNDEFINED, kVK_MEDIA_Previous }, // 0x90
|
|
378
|
+
/* 145 */ { VC_UNDEFINED, kVK_Undefined }, // 0x91
|
|
379
|
+
/* 146 */ { VC_UNDEFINED, kVK_Undefined }, // 0x92
|
|
380
|
+
/* 147 */ { VC_UNDEFINED, kVK_Undefined }, // 0x93
|
|
381
|
+
/* 148 */ { VC_UNDEFINED, kVK_Undefined }, // 0x94
|
|
382
|
+
/* 149 */ { VC_UNDEFINED, kVK_Undefined }, // 0x95
|
|
383
|
+
/* 150 */ { VC_UNDEFINED, kVK_Undefined }, // 0x96
|
|
384
|
+
/* 151 */ { VC_UNDEFINED, kVK_Undefined }, // 0x97
|
|
385
|
+
/* 152 */ { VC_UNDEFINED, kVK_Undefined }, // 0x98
|
|
386
|
+
/* 153 */ { VC_UNDEFINED, kVK_MEDIA_Next }, // 0x99
|
|
387
|
+
/* 154 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9A
|
|
388
|
+
/* 155 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9B
|
|
389
|
+
/* 156 */ { VC_UNDEFINED, kVK_ANSI_KeypadEnter }, // 0x9C
|
|
390
|
+
/* 157 */ { VC_UNDEFINED, kVK_RightControl }, // 0x9D
|
|
391
|
+
/* 158 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9E
|
|
392
|
+
/* 159 */ { VC_UNDEFINED, kVK_Undefined }, // 0x9F
|
|
393
|
+
/* 160 */ { VC_UNDEFINED, kVK_Mute }, // 0xA0
|
|
394
|
+
/* 161 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA1
|
|
395
|
+
/* 162 */ { VC_UNDEFINED, kVK_MEDIA_Play }, // 0xA2
|
|
396
|
+
/* 163 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA3
|
|
397
|
+
/* 164 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA4
|
|
398
|
+
/* 165 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA5
|
|
399
|
+
/* 166 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA6
|
|
400
|
+
/* 167 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA7
|
|
401
|
+
/* 168 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA8
|
|
402
|
+
/* 169 */ { VC_UNDEFINED, kVK_Undefined }, // 0xA9
|
|
403
|
+
/* 170 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAA
|
|
404
|
+
/* 171 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAB
|
|
405
|
+
/* 172 */ { VC_UNDEFINED, kVK_NX_Eject }, // 0xAC
|
|
406
|
+
/* 173 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAD
|
|
407
|
+
/* 174 */ { VC_UNDEFINED, kVK_VolumeDown }, // 0xAE
|
|
408
|
+
/* 175 */ { VC_UNDEFINED, kVK_Undefined }, // 0xAF
|
|
409
|
+
/* 176 */ { VC_UNDEFINED, kVK_VolumeUp }, // 0xB0
|
|
410
|
+
/* 177 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB1
|
|
411
|
+
/* 178 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB2
|
|
412
|
+
/* 179 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB3
|
|
413
|
+
/* 180 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB4
|
|
414
|
+
/* 181 */ { VC_UNDEFINED, kVK_ANSI_KeypadDivide }, // 0xB5
|
|
415
|
+
/* 182 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB6
|
|
416
|
+
/* 183 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB7
|
|
417
|
+
/* 184 */ { VC_UNDEFINED, kVK_RightOption }, // 0xB8
|
|
418
|
+
/* 185 */ { VC_UNDEFINED, kVK_Undefined }, // 0xB9
|
|
419
|
+
/* 186 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBA
|
|
420
|
+
/* 187 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBB
|
|
421
|
+
/* 188 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBC
|
|
422
|
+
/* 189 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBD
|
|
423
|
+
/* 190 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBE
|
|
424
|
+
/* 191 */ { VC_UNDEFINED, kVK_Undefined }, // 0xBF
|
|
425
|
+
/* 192 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC0
|
|
426
|
+
/* 193 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC1
|
|
427
|
+
/* 194 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC2
|
|
428
|
+
/* 195 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC3
|
|
429
|
+
/* 196 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC4
|
|
430
|
+
/* 197 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC5
|
|
431
|
+
/* 198 */ { VC_UNDEFINED, kVK_Undefined }, // 0xC6
|
|
432
|
+
/* 199 */ { VC_UNDEFINED, kVK_Home }, // 0xC7
|
|
433
|
+
/* 200 */ { VC_UNDEFINED, kVK_UpArrow }, // 0xC8
|
|
434
|
+
/* 201 */ { VC_UNDEFINED, kVK_PageUp }, // 0xC9
|
|
435
|
+
/* 202 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCA
|
|
436
|
+
/* 203 */ { VC_UNDEFINED, kVK_LeftArrow }, // 0xCB
|
|
437
|
+
/* 204 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCC
|
|
438
|
+
/* 205 */ { VC_UNDEFINED, kVK_RightArrow }, // 0xCD
|
|
439
|
+
/* 206 */ { VC_UNDEFINED, kVK_Undefined }, // 0xCE
|
|
440
|
+
/* 207 */ { VC_UNDEFINED, kVK_End }, // 0xCF
|
|
441
|
+
/* 208 */ { VC_UNDEFINED, kVK_DownArrow }, // 0xD0
|
|
442
|
+
/* 209 */ { VC_UNDEFINED, kVK_PageDown }, // 0xD1
|
|
443
|
+
/* 210 */ { VC_UNDEFINED, kVK_Help }, // 0xD2
|
|
444
|
+
/* 211 */ { VC_UNDEFINED, kVK_ForwardDelete }, // 0xD3
|
|
445
|
+
/* 212 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD4
|
|
446
|
+
/* 213 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD5
|
|
447
|
+
/* 214 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD6
|
|
448
|
+
/* 215 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD7
|
|
449
|
+
/* 216 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD8
|
|
450
|
+
/* 217 */ { VC_UNDEFINED, kVK_Undefined }, // 0xD9
|
|
451
|
+
/* 218 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDA
|
|
452
|
+
/* 219 */ { VC_UNDEFINED, kVK_Command }, // 0xDB
|
|
453
|
+
/* 220 */ { VC_UNDEFINED, kVK_RightCommand }, // 0xDC
|
|
454
|
+
/* 221 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDD
|
|
455
|
+
/* 222 */ { VC_UNDEFINED, kVK_NX_Power }, // 0xDE
|
|
456
|
+
/* 223 */ { VC_UNDEFINED, kVK_Undefined }, // 0xDF
|
|
457
|
+
/* 224 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE0
|
|
458
|
+
/* 225 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE1
|
|
459
|
+
/* 226 */ { VC_LESSER_GREATER, kVK_Undefined }, // 0xE2
|
|
460
|
+
/* 227 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE3
|
|
461
|
+
/* 228 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE4
|
|
462
|
+
/* 229 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE5
|
|
463
|
+
/* 230 */ { VC_POWER, kVK_Undefined }, // 0xE6
|
|
464
|
+
/* 231 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE7
|
|
465
|
+
/* 232 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE8
|
|
466
|
+
/* 233 */ { VC_UNDEFINED, kVK_Undefined }, // 0xE9
|
|
467
|
+
/* 234 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEA
|
|
468
|
+
/* 235 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEB
|
|
469
|
+
/* 236 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEC
|
|
470
|
+
/* 237 */ { VC_UNDEFINED, kVK_Undefined }, // 0xED
|
|
471
|
+
/* 238 */ { VC_MEDIA_EJECT, kVK_Undefined }, // 0xEE
|
|
472
|
+
/* 239 */ { VC_UNDEFINED, kVK_Undefined }, // 0xEF
|
|
473
|
+
/* 240 */ { VC_MEDIA_PLAY, kVK_Undefined }, // 0xF0
|
|
474
|
+
/* 241 */ { VC_MEDIA_NEXT, kVK_Undefined }, // 0xF1
|
|
475
|
+
/* 242 */ { VC_MEDIA_PREVIOUS, kVK_Undefined }, // 0xF2
|
|
476
|
+
/* 243 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF3
|
|
477
|
+
/* 244 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF4
|
|
478
|
+
/* 245 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF5
|
|
479
|
+
/* 246 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF6
|
|
480
|
+
/* 247 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF7
|
|
481
|
+
/* 248 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF8
|
|
482
|
+
/* 249 */ { VC_UNDEFINED, kVK_Undefined }, // 0xF9
|
|
483
|
+
/* 250 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFA
|
|
484
|
+
/* 251 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFB
|
|
485
|
+
/* 252 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFC
|
|
486
|
+
/* 253 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFD
|
|
487
|
+
/* 254 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFE
|
|
488
|
+
/* 255 */ { VC_UNDEFINED, kVK_Undefined }, // 0xFF
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
uint16_t keycode_to_scancode(UInt64 keycode) {
|
|
492
|
+
uint16_t scancode = VC_UNDEFINED;
|
|
493
|
+
|
|
494
|
+
// Bound check 0 <= keycode < 256
|
|
495
|
+
if (keycode < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[0])) {
|
|
496
|
+
scancode = keycode_scancode_table[keycode][0];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return scancode;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
UInt64 scancode_to_keycode(uint16_t scancode) {
|
|
503
|
+
UInt64 keycode = kVK_Undefined;
|
|
504
|
+
|
|
505
|
+
// Bound check 0 <= keycode < 128
|
|
506
|
+
if (scancode < 128) {
|
|
507
|
+
keycode = keycode_scancode_table[scancode][1];
|
|
508
|
+
} else {
|
|
509
|
+
// Calculate the upper offset.
|
|
510
|
+
unsigned short i = (scancode & 0x007F) | 0x80;
|
|
511
|
+
|
|
512
|
+
if (i < sizeof(keycode_scancode_table) / sizeof(keycode_scancode_table[1])) {
|
|
513
|
+
keycode = keycode_scancode_table[i][1];
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return keycode;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
void load_input_helper() {
|
|
521
|
+
#if defined(USE_CARBON_LEGACY) || defined(USE_APPLICATION_SERVICES)
|
|
522
|
+
// Start with a fresh dead key state.
|
|
523
|
+
//curr_deadkey_state = 0;
|
|
524
|
+
#endif
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
void unload_input_helper() {
|
|
528
|
+
#if defined(USE_CARBON_LEGACY) || defined(USE_APPLICATION_SERVICES)
|
|
529
|
+
if (prev_keyboard_layout != NULL) {
|
|
530
|
+
// Cleanup tracking of the previous layout.
|
|
531
|
+
CFRelease(prev_keyboard_layout);
|
|
532
|
+
prev_keyboard_layout = NULL;
|
|
533
|
+
}
|
|
534
|
+
#endif
|
|
535
|
+
}
|