simen-keyboard-listener 1.0.5 → 1.0.6
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/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +13 -0
- package/dist/index.mjs +12 -0
- package/package.json +2 -2
- package/src/native/simen_keyboard_listener.cc +33 -0
package/dist/index.d.mts
CHANGED
|
@@ -23,5 +23,14 @@ declare function getGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
|
23
23
|
* This function is kept for backward compatibility but now returns the singleton.
|
|
24
24
|
*/
|
|
25
25
|
declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
26
|
+
/**
|
|
27
|
+
* Check if the app has permission to listen to global keyboard events.
|
|
28
|
+
* - On macOS: checks accessibility permission (System Preferences > Security & Privacy > Accessibility)
|
|
29
|
+
* - On Windows: always returns true (no special permission needed)
|
|
30
|
+
* - On other platforms: returns false
|
|
31
|
+
*
|
|
32
|
+
* Call this before starting the listener to provide better UX when permission is missing.
|
|
33
|
+
*/
|
|
34
|
+
declare function checkKeyboardPermission(): boolean;
|
|
26
35
|
|
|
27
|
-
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
|
36
|
+
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, checkKeyboardPermission, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,5 +23,14 @@ declare function getGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
|
23
23
|
* This function is kept for backward compatibility but now returns the singleton.
|
|
24
24
|
*/
|
|
25
25
|
declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
26
|
+
/**
|
|
27
|
+
* Check if the app has permission to listen to global keyboard events.
|
|
28
|
+
* - On macOS: checks accessibility permission (System Preferences > Security & Privacy > Accessibility)
|
|
29
|
+
* - On Windows: always returns true (no special permission needed)
|
|
30
|
+
* - On other platforms: returns false
|
|
31
|
+
*
|
|
32
|
+
* Call this before starting the listener to provide better UX when permission is missing.
|
|
33
|
+
*/
|
|
34
|
+
declare function checkKeyboardPermission(): boolean;
|
|
26
35
|
|
|
27
|
-
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
|
36
|
+
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, checkKeyboardPermission, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
checkKeyboardPermission: () => checkKeyboardPermission,
|
|
33
34
|
createGlobalKeyboardListener: () => createGlobalKeyboardListener,
|
|
34
35
|
getGlobalKeyboardListener: () => getGlobalKeyboardListener
|
|
35
36
|
});
|
|
@@ -161,8 +162,20 @@ function getGlobalKeyboardListener() {
|
|
|
161
162
|
function createGlobalKeyboardListener() {
|
|
162
163
|
return getGlobalKeyboardListener();
|
|
163
164
|
}
|
|
165
|
+
function checkKeyboardPermission() {
|
|
166
|
+
if (process.platform !== "darwin" && process.platform !== "win32") {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const addon = getNativeAddon();
|
|
171
|
+
return addon.checkPermission();
|
|
172
|
+
} catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
164
176
|
// Annotate the CommonJS export names for ESM import in node:
|
|
165
177
|
0 && (module.exports = {
|
|
178
|
+
checkKeyboardPermission,
|
|
166
179
|
createGlobalKeyboardListener,
|
|
167
180
|
getGlobalKeyboardListener
|
|
168
181
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -132,7 +132,19 @@ function getGlobalKeyboardListener() {
|
|
|
132
132
|
function createGlobalKeyboardListener() {
|
|
133
133
|
return getGlobalKeyboardListener();
|
|
134
134
|
}
|
|
135
|
+
function checkKeyboardPermission() {
|
|
136
|
+
if (process.platform !== "darwin" && process.platform !== "win32") {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const addon = getNativeAddon();
|
|
141
|
+
return addon.checkPermission();
|
|
142
|
+
} catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
135
146
|
export {
|
|
147
|
+
checkKeyboardPermission,
|
|
136
148
|
createGlobalKeyboardListener,
|
|
137
149
|
getGlobalKeyboardListener
|
|
138
150
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simen-keyboard-listener",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Native global keyboard listener for macOS and Windows",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"build:native": "node-gyp rebuild --directory=src/native",
|
|
24
24
|
"build:ts": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
25
25
|
"build": "npm run build:native && npm run build:ts",
|
|
26
|
-
"prebuild": "prebuildify --napi --strip --cwd src/native",
|
|
26
|
+
"prebuild": "prebuildify --napi --strip --cwd src/native --out ../../prebuilds",
|
|
27
27
|
"prepublishOnly": "npm run build:ts"
|
|
28
28
|
},
|
|
29
29
|
"keywords": [
|
|
@@ -70,6 +70,16 @@ void emitKeyEvent(const std::string& name, const std::string& state) {
|
|
|
70
70
|
|
|
71
71
|
namespace {
|
|
72
72
|
|
|
73
|
+
// Check if the app has accessibility permission (required for CGEventTap)
|
|
74
|
+
static bool macHasAccessibilityPermission() {
|
|
75
|
+
// AXIsProcessTrusted returns true if the app has accessibility permission
|
|
76
|
+
return AXIsProcessTrusted();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
} // namespace
|
|
80
|
+
|
|
81
|
+
namespace {
|
|
82
|
+
|
|
73
83
|
CFMachPortRef g_eventTap = nullptr;
|
|
74
84
|
CFRunLoopSourceRef g_runLoopSource = nullptr;
|
|
75
85
|
CFRunLoopRef g_runLoop = nullptr;
|
|
@@ -226,6 +236,13 @@ static CGEventRef macEventTapCallback(CGEventTapProxy /*proxy*/, CGEventType typ
|
|
|
226
236
|
}
|
|
227
237
|
|
|
228
238
|
static void macThreadMain() {
|
|
239
|
+
// Pre-check accessibility permission before attempting to create event tap
|
|
240
|
+
if (!macHasAccessibilityPermission()) {
|
|
241
|
+
g_running.store(false);
|
|
242
|
+
setStartResult(-1);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
229
246
|
CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) |
|
|
230
247
|
CGEventMaskBit(kCGEventKeyUp) |
|
|
231
248
|
CGEventMaskBit(kCGEventFlagsChanged);
|
|
@@ -617,10 +634,26 @@ static Napi::Value IsRunning(const Napi::CallbackInfo& info) {
|
|
|
617
634
|
return Napi::Boolean::New(info.Env(), g_running.load());
|
|
618
635
|
}
|
|
619
636
|
|
|
637
|
+
// Check if the app has permission to listen to global keyboard events
|
|
638
|
+
// Returns: true if permission granted, false otherwise
|
|
639
|
+
// On Windows, always returns true (no special permission needed)
|
|
640
|
+
// On macOS, checks accessibility permission
|
|
641
|
+
static Napi::Value CheckPermission(const Napi::CallbackInfo& info) {
|
|
642
|
+
#if defined(__APPLE__)
|
|
643
|
+
return Napi::Boolean::New(info.Env(), macHasAccessibilityPermission());
|
|
644
|
+
#elif defined(_WIN32)
|
|
645
|
+
// Windows doesn't require special permission for keyboard hooks
|
|
646
|
+
return Napi::Boolean::New(info.Env(), true);
|
|
647
|
+
#else
|
|
648
|
+
return Napi::Boolean::New(info.Env(), false);
|
|
649
|
+
#endif
|
|
650
|
+
}
|
|
651
|
+
|
|
620
652
|
static Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
621
653
|
exports.Set("start", Napi::Function::New(env, Start));
|
|
622
654
|
exports.Set("stop", Napi::Function::New(env, Stop));
|
|
623
655
|
exports.Set("isRunning", Napi::Function::New(env, IsRunning));
|
|
656
|
+
exports.Set("checkPermission", Napi::Function::New(env, CheckPermission));
|
|
624
657
|
return exports;
|
|
625
658
|
}
|
|
626
659
|
|