@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,494 @@
|
|
|
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
|
+
#include <stdbool.h>
|
|
20
|
+
#include <stdio.h>
|
|
21
|
+
#include <stdlib.h>
|
|
22
|
+
#include <uiohook.h>
|
|
23
|
+
#include <X11/Xlib.h>
|
|
24
|
+
#include <X11/XKBlib.h>
|
|
25
|
+
|
|
26
|
+
#ifdef USE_XF86MISC
|
|
27
|
+
#include <X11/extensions/xf86misc.h>
|
|
28
|
+
#include <X11/extensions/xf86mscstr.h>
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#if defined(USE_XINERAMA) && !defined(USE_XRANDR)
|
|
32
|
+
#include <X11/extensions/Xinerama.h>
|
|
33
|
+
#elif defined(USE_XRANDR)
|
|
34
|
+
#include <pthread.h>
|
|
35
|
+
#include <X11/extensions/Xrandr.h>
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#ifdef USE_XT
|
|
39
|
+
#include <X11/Intrinsic.h>
|
|
40
|
+
|
|
41
|
+
static XtAppContext xt_context;
|
|
42
|
+
static Display *xt_disp;
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#include "input_helper.h"
|
|
46
|
+
#include "logger.h"
|
|
47
|
+
|
|
48
|
+
#ifdef USE_XRANDR
|
|
49
|
+
static pthread_mutex_t xrandr_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
50
|
+
static XRRScreenResources *xrandr_resources = NULL;
|
|
51
|
+
|
|
52
|
+
static void settings_cleanup_proc(void *arg) {
|
|
53
|
+
if (pthread_mutex_trylock(&xrandr_mutex) == 0) {
|
|
54
|
+
if (xrandr_resources != NULL) {
|
|
55
|
+
XRRFreeScreenResources(xrandr_resources);
|
|
56
|
+
xrandr_resources = NULL;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (arg != NULL) {
|
|
60
|
+
XCloseDisplay((Display *) arg);
|
|
61
|
+
arg = NULL;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
pthread_mutex_unlock(&xrandr_mutex);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static void *settings_thread_proc(void *arg) {
|
|
69
|
+
Display *settings_disp = XOpenDisplay(XDisplayName(NULL));;
|
|
70
|
+
if (settings_disp != NULL) {
|
|
71
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
|
|
72
|
+
__FUNCTION__, __LINE__, "XOpenDisplay success.");
|
|
73
|
+
|
|
74
|
+
pthread_cleanup_push(settings_cleanup_proc, settings_disp);
|
|
75
|
+
|
|
76
|
+
int event_base = 0;
|
|
77
|
+
int error_base = 0;
|
|
78
|
+
if (XRRQueryExtension(settings_disp, &event_base, &error_base)) {
|
|
79
|
+
Window root = XDefaultRootWindow(settings_disp);
|
|
80
|
+
unsigned long event_mask = RRScreenChangeNotifyMask;
|
|
81
|
+
XRRSelectInput(settings_disp, root, event_mask);
|
|
82
|
+
|
|
83
|
+
XEvent ev;
|
|
84
|
+
|
|
85
|
+
while(settings_disp != NULL) {
|
|
86
|
+
XNextEvent(settings_disp, &ev);
|
|
87
|
+
|
|
88
|
+
if (ev.type == event_base + RRScreenChangeNotifyMask) {
|
|
89
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: Received XRRScreenChangeNotifyEvent.\n",
|
|
90
|
+
__FUNCTION__, __LINE__);
|
|
91
|
+
|
|
92
|
+
pthread_mutex_lock(&xrandr_mutex);
|
|
93
|
+
if (xrandr_resources != NULL) {
|
|
94
|
+
XRRFreeScreenResources(xrandr_resources);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
xrandr_resources = XRRGetScreenResources(settings_disp, root);
|
|
98
|
+
if (xrandr_resources == NULL) {
|
|
99
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XRandR could not get screen resources!\n",
|
|
100
|
+
__FUNCTION__, __LINE__);
|
|
101
|
+
}
|
|
102
|
+
pthread_mutex_unlock(&xrandr_mutex);
|
|
103
|
+
} else {
|
|
104
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XRandR is not currently available!\n",
|
|
105
|
+
__FUNCTION__, __LINE__);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Execute the thread cleanup handler.
|
|
111
|
+
pthread_cleanup_pop(1);
|
|
112
|
+
|
|
113
|
+
} else {
|
|
114
|
+
logger(LOG_LEVEL_ERROR, "%s [%u]: XOpenDisplay failure!\n",
|
|
115
|
+
__FUNCTION__, __LINE__);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return NULL;
|
|
119
|
+
}
|
|
120
|
+
#endif
|
|
121
|
+
|
|
122
|
+
UIOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
|
|
123
|
+
*count = 0;
|
|
124
|
+
screen_data *screens = NULL;
|
|
125
|
+
|
|
126
|
+
// Check and make sure we could connect to the x server.
|
|
127
|
+
if (helper_disp != NULL) {
|
|
128
|
+
#if defined(USE_XINERAMA) && !defined(USE_XRANDR)
|
|
129
|
+
if (XineramaIsActive(helper_disp)) {
|
|
130
|
+
int xine_count = 0;
|
|
131
|
+
XineramaScreenInfo *xine_info = XineramaQueryScreens(helper_disp, &xine_count);
|
|
132
|
+
|
|
133
|
+
if (xine_info != NULL) {
|
|
134
|
+
if (xine_count > UINT8_MAX) {
|
|
135
|
+
*count = UINT8_MAX;
|
|
136
|
+
|
|
137
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
|
|
138
|
+
__FUNCTION__, __LINE__);
|
|
139
|
+
} else {
|
|
140
|
+
*count = (uint8_t) xine_count;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
screens = malloc(sizeof(screen_data) * xine_count);
|
|
144
|
+
|
|
145
|
+
if (screens != NULL) {
|
|
146
|
+
for (int i = 0; i < xine_count; i++) {
|
|
147
|
+
screens[i] = (screen_data) {
|
|
148
|
+
.number = xine_info[i].screen_number,
|
|
149
|
+
.x = xine_info[i].x_org,
|
|
150
|
+
.y = xine_info[i].y_org,
|
|
151
|
+
.width = xine_info[i].width,
|
|
152
|
+
.height = xine_info[i].height
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
XFree(xine_info);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
#elif defined(USE_XRANDR)
|
|
161
|
+
pthread_mutex_lock(&xrandr_mutex);
|
|
162
|
+
if (xrandr_resources != NULL) {
|
|
163
|
+
int xrandr_count = xrandr_resources->ncrtc;
|
|
164
|
+
if (xrandr_count > UINT8_MAX) {
|
|
165
|
+
*count = UINT8_MAX;
|
|
166
|
+
|
|
167
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
|
|
168
|
+
__FUNCTION__, __LINE__);
|
|
169
|
+
} else {
|
|
170
|
+
*count = (uint8_t) xrandr_count;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
screens = malloc(sizeof(screen_data) * xrandr_count);
|
|
174
|
+
|
|
175
|
+
if (screens != NULL) {
|
|
176
|
+
for (int i = 0; i < xrandr_count; i++) {
|
|
177
|
+
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(helper_disp, xrandr_resources, xrandr_resources->crtcs[i]);
|
|
178
|
+
|
|
179
|
+
if (crtc_info != NULL) {
|
|
180
|
+
screens[i] = (screen_data) {
|
|
181
|
+
.number = i + 1,
|
|
182
|
+
.x = crtc_info->x,
|
|
183
|
+
.y = crtc_info->y,
|
|
184
|
+
.width = crtc_info->width,
|
|
185
|
+
.height = crtc_info->height
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
XRRFreeCrtcInfo(crtc_info);
|
|
189
|
+
} else {
|
|
190
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XRandr failed to return crtc information! (%#X)\n",
|
|
191
|
+
__FUNCTION__, __LINE__, xrandr_resources->crtcs[i]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
pthread_mutex_unlock(&xrandr_mutex);
|
|
197
|
+
#else
|
|
198
|
+
Screen* default_screen = DefaultScreenOfDisplay(helper_disp);
|
|
199
|
+
|
|
200
|
+
if (default_screen->width > 0 && default_screen->height > 0) {
|
|
201
|
+
screens = malloc(sizeof(screen_data));
|
|
202
|
+
|
|
203
|
+
if (screens != NULL) {
|
|
204
|
+
*count = 1;
|
|
205
|
+
screens[0] = (screen_data) {
|
|
206
|
+
.number = 1,
|
|
207
|
+
.x = 0,
|
|
208
|
+
.y = 0,
|
|
209
|
+
.width = default_screen->width,
|
|
210
|
+
.height = default_screen->height
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
#endif
|
|
215
|
+
} else {
|
|
216
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
217
|
+
__FUNCTION__, __LINE__);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return screens;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
UIOHOOK_API long int hook_get_auto_repeat_rate() {
|
|
224
|
+
bool successful = false;
|
|
225
|
+
long int value = -1;
|
|
226
|
+
unsigned int delay = 0, rate = 0;
|
|
227
|
+
|
|
228
|
+
// Check and make sure we could connect to the x server.
|
|
229
|
+
if (helper_disp != NULL) {
|
|
230
|
+
// Attempt to acquire the keyboard auto repeat rate using the XKB extension.
|
|
231
|
+
if (!successful) {
|
|
232
|
+
successful = XkbGetAutoRepeatRate(helper_disp, XkbUseCoreKbd, &delay, &rate);
|
|
233
|
+
|
|
234
|
+
if (successful) {
|
|
235
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
|
|
236
|
+
__FUNCTION__, __LINE__, rate);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#ifdef USE_XF86MISC
|
|
241
|
+
// Fallback to the XF86 Misc extension if available and other efforts failed.
|
|
242
|
+
if (!successful) {
|
|
243
|
+
XF86MiscKbdSettings kb_info;
|
|
244
|
+
successful = (bool) XF86MiscGetKbdSettings(helper_disp, &kb_info);
|
|
245
|
+
if (successful) {
|
|
246
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
|
|
247
|
+
__FUNCTION__, __LINE__, kbdinfo.rate);
|
|
248
|
+
|
|
249
|
+
delay = (unsigned int) kbdinfo.delay;
|
|
250
|
+
rate = (unsigned int) kbdinfo.rate;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
#endif
|
|
254
|
+
} else {
|
|
255
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
256
|
+
__FUNCTION__, __LINE__);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (successful) {
|
|
260
|
+
value = (long int) rate;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return value;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
UIOHOOK_API long int hook_get_auto_repeat_delay() {
|
|
267
|
+
bool successful = false;
|
|
268
|
+
long int value = -1;
|
|
269
|
+
unsigned int delay = 0, rate = 0;
|
|
270
|
+
|
|
271
|
+
// Check and make sure we could connect to the x server.
|
|
272
|
+
if (helper_disp != NULL) {
|
|
273
|
+
// Attempt to acquire the keyboard auto repeat rate using the XKB extension.
|
|
274
|
+
if (!successful) {
|
|
275
|
+
successful = XkbGetAutoRepeatRate(helper_disp, XkbUseCoreKbd, &delay, &rate);
|
|
276
|
+
|
|
277
|
+
if (successful) {
|
|
278
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
|
|
279
|
+
__FUNCTION__, __LINE__, delay);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
#ifdef USE_XF86MISC
|
|
284
|
+
// Fallback to the XF86 Misc extension if available and other efforts failed.
|
|
285
|
+
if (!successful) {
|
|
286
|
+
XF86MiscKbdSettings kb_info;
|
|
287
|
+
successful = (bool) XF86MiscGetKbdSettings(helper_disp, &kb_info);
|
|
288
|
+
if (successful) {
|
|
289
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
|
|
290
|
+
__FUNCTION__, __LINE__, kbdinfo.delay);
|
|
291
|
+
|
|
292
|
+
delay = (unsigned int) kbdinfo.delay;
|
|
293
|
+
rate = (unsigned int) kbdinfo.rate;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
#endif
|
|
297
|
+
} else {
|
|
298
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
299
|
+
__FUNCTION__, __LINE__);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (successful) {
|
|
303
|
+
value = (long int) delay;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return value;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
UIOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
|
|
310
|
+
long int value = -1;
|
|
311
|
+
int accel_numerator, accel_denominator, threshold;
|
|
312
|
+
|
|
313
|
+
// Check and make sure we could connect to the x server.
|
|
314
|
+
if (helper_disp != NULL) {
|
|
315
|
+
XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
|
|
316
|
+
if (accel_denominator >= 0) {
|
|
317
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
|
|
318
|
+
__FUNCTION__, __LINE__, accel_denominator);
|
|
319
|
+
|
|
320
|
+
value = (long int) accel_denominator;
|
|
321
|
+
}
|
|
322
|
+
} else {
|
|
323
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
324
|
+
__FUNCTION__, __LINE__);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return value;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
UIOHOOK_API long int hook_get_pointer_acceleration_threshold() {
|
|
331
|
+
long int value = -1;
|
|
332
|
+
int accel_numerator, accel_denominator, threshold;
|
|
333
|
+
|
|
334
|
+
// Check and make sure we could connect to the x server.
|
|
335
|
+
if (helper_disp != NULL) {
|
|
336
|
+
XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
|
|
337
|
+
if (threshold >= 0) {
|
|
338
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
|
|
339
|
+
__FUNCTION__, __LINE__, threshold);
|
|
340
|
+
|
|
341
|
+
value = (long int) threshold;
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
345
|
+
__FUNCTION__, __LINE__);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return value;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
UIOHOOK_API long int hook_get_pointer_sensitivity() {
|
|
352
|
+
long int value = -1;
|
|
353
|
+
int accel_numerator, accel_denominator, threshold;
|
|
354
|
+
|
|
355
|
+
// Check and make sure we could connect to the x server.
|
|
356
|
+
if (helper_disp != NULL) {
|
|
357
|
+
XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
|
|
358
|
+
if (accel_numerator >= 0) {
|
|
359
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
|
|
360
|
+
__FUNCTION__, __LINE__, accel_numerator);
|
|
361
|
+
|
|
362
|
+
value = (long int) accel_numerator;
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
366
|
+
__FUNCTION__, __LINE__);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return value;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
UIOHOOK_API long int hook_get_multi_click_time() {
|
|
373
|
+
long int value = 200;
|
|
374
|
+
int click_time;
|
|
375
|
+
bool successful = false;
|
|
376
|
+
|
|
377
|
+
#ifdef USE_XT
|
|
378
|
+
// Check and make sure we could connect to the x server.
|
|
379
|
+
if (xt_disp != NULL) {
|
|
380
|
+
// Try and use the Xt extention to get the current multi-click.
|
|
381
|
+
if (!successful) {
|
|
382
|
+
// Fall back to the X Toolkit extension if available and other efforts failed.
|
|
383
|
+
click_time = XtGetMultiClickTime(xt_disp);
|
|
384
|
+
if (click_time >= 0) {
|
|
385
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: XtGetMultiClickTime: %i.\n",
|
|
386
|
+
__FUNCTION__, __LINE__, click_time);
|
|
387
|
+
|
|
388
|
+
successful = true;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
} else {
|
|
392
|
+
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
|
393
|
+
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
|
394
|
+
}
|
|
395
|
+
#endif
|
|
396
|
+
|
|
397
|
+
// Check and make sure we could connect to the x server.
|
|
398
|
+
if (helper_disp != NULL) {
|
|
399
|
+
// Try and acquire the multi-click time from the user defined X defaults.
|
|
400
|
+
if (!successful) {
|
|
401
|
+
char *xprop = XGetDefault(helper_disp, "*", "multiClickTime");
|
|
402
|
+
if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
|
|
403
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: X default 'multiClickTime' property: %i.\n",
|
|
404
|
+
__FUNCTION__, __LINE__, click_time);
|
|
405
|
+
|
|
406
|
+
successful = true;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (!successful) {
|
|
411
|
+
char *xprop = XGetDefault(helper_disp, "OpenWindows", "MultiClickTimeout");
|
|
412
|
+
if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
|
|
413
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: X default 'MultiClickTimeout' property: %i.\n",
|
|
414
|
+
__FUNCTION__, __LINE__, click_time);
|
|
415
|
+
|
|
416
|
+
successful = true;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
} else {
|
|
420
|
+
logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
|
|
421
|
+
__FUNCTION__, __LINE__);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (successful) {
|
|
425
|
+
value = (long int) click_time;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return value;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Create a shared object constructor.
|
|
432
|
+
__attribute__ ((constructor))
|
|
433
|
+
void on_library_load() {
|
|
434
|
+
// Make sure we are initialized for threading.
|
|
435
|
+
XInitThreads();
|
|
436
|
+
|
|
437
|
+
// Open local display.
|
|
438
|
+
helper_disp = XOpenDisplay(XDisplayName(NULL));
|
|
439
|
+
if (helper_disp == NULL) {
|
|
440
|
+
logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
|
|
441
|
+
__FUNCTION__, __LINE__, "XOpenDisplay failure!");
|
|
442
|
+
} else {
|
|
443
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
|
|
444
|
+
__FUNCTION__, __LINE__, "XOpenDisplay success.");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
#ifdef USE_XRANDR
|
|
448
|
+
// Create the thread attribute.
|
|
449
|
+
pthread_attr_t settings_thread_attr;
|
|
450
|
+
pthread_attr_init(&settings_thread_attr);
|
|
451
|
+
|
|
452
|
+
pthread_t settings_thread_id;
|
|
453
|
+
if (pthread_create(&settings_thread_id, &settings_thread_attr, settings_thread_proc, NULL) == 0) {
|
|
454
|
+
logger(LOG_LEVEL_DEBUG, "%s [%u]: Successfully created settings thread.\n",
|
|
455
|
+
__FUNCTION__, __LINE__);
|
|
456
|
+
} else {
|
|
457
|
+
logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to create settings thread!\n",
|
|
458
|
+
__FUNCTION__, __LINE__);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Make sure the thread attribute is removed.
|
|
462
|
+
pthread_attr_destroy(&settings_thread_attr);
|
|
463
|
+
#endif
|
|
464
|
+
|
|
465
|
+
#ifdef USE_XT
|
|
466
|
+
XtToolkitInitialize();
|
|
467
|
+
xt_context = XtCreateApplicationContext();
|
|
468
|
+
|
|
469
|
+
int argc = 0;
|
|
470
|
+
char ** argv = { NULL };
|
|
471
|
+
xt_disp = XtOpenDisplay(xt_context, NULL, "UIOHook", "libuiohook", NULL, 0, &argc, argv);
|
|
472
|
+
#endif
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Create a shared object destructor.
|
|
476
|
+
__attribute__ ((destructor))
|
|
477
|
+
void on_library_unload() {
|
|
478
|
+
// Disable the event hook.
|
|
479
|
+
//hook_stop();
|
|
480
|
+
|
|
481
|
+
// Cleanup.
|
|
482
|
+
unload_input_helper();
|
|
483
|
+
|
|
484
|
+
#ifdef USE_XT
|
|
485
|
+
XtCloseDisplay(xt_disp);
|
|
486
|
+
XtDestroyApplicationContext(xt_context);
|
|
487
|
+
#endif
|
|
488
|
+
|
|
489
|
+
// Destroy the native displays.
|
|
490
|
+
if (helper_disp != NULL) {
|
|
491
|
+
XCloseDisplay(helper_disp);
|
|
492
|
+
helper_disp = NULL;
|
|
493
|
+
}
|
|
494
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mukea/uiohook-napi",
|
|
3
|
+
"version": "1.5.4",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "mukea.cc"
|
|
6
|
+
},
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mukea-org/uiohook-napi"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"iohook",
|
|
14
|
+
"uiohook",
|
|
15
|
+
"libuiohook",
|
|
16
|
+
"hook",
|
|
17
|
+
"input",
|
|
18
|
+
"keyboard",
|
|
19
|
+
"mouse"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"install": "node-gyp-build",
|
|
29
|
+
"prebuild": "prebuildify --napi",
|
|
30
|
+
"prepublishOnly": "npm run build-ts && npm run prebuild",
|
|
31
|
+
"build-ts": "tsc",
|
|
32
|
+
"demo": "ts-node src/demo.ts",
|
|
33
|
+
"make-libuiohook-patch": "git -C ./libuiohook diff --cached > ./src/libuiohook.patch",
|
|
34
|
+
"apply-libuiohook-patch": "git -C ./libuiohook apply ../src/libuiohook.patch"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"binding.gyp",
|
|
39
|
+
"libuiohook/src",
|
|
40
|
+
"libuiohook/include",
|
|
41
|
+
"src/lib",
|
|
42
|
+
"prebuilds"
|
|
43
|
+
],
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^20.11.30",
|
|
46
|
+
"prebuildify": "^6.0.1",
|
|
47
|
+
"ts-node": "^10.9.2",
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"node-gyp-build": "4.x.x"
|
|
52
|
+
},
|
|
53
|
+
"prebuild": {
|
|
54
|
+
"test": "dist/prebuild-test-noop.js"
|
|
55
|
+
},
|
|
56
|
+
"gypfile": true,
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|