simen-keyboard-listener 1.0.8 → 1.0.10
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 +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +87 -2
- package/dist/index.mjs +85 -2
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
type IGlobalKeyState = 'DOWN' | 'UP';
|
|
1
|
+
type IGlobalKeyState = 'DOWN' | 'UP' | 'PERMISSION_LOST';
|
|
2
2
|
interface IGlobalKeyEvent {
|
|
3
3
|
readonly name: string;
|
|
4
4
|
readonly state: IGlobalKeyState;
|
|
5
5
|
}
|
|
6
6
|
type IGlobalKeyDownMap = Record<string, boolean>;
|
|
7
7
|
type IGlobalKeyListener = (event: IGlobalKeyEvent, isDown: IGlobalKeyDownMap) => void;
|
|
8
|
+
type IPermissionLostListener = () => void;
|
|
8
9
|
interface IGlobalKeyboardListener {
|
|
9
10
|
addListener(listener: IGlobalKeyListener): void;
|
|
10
11
|
removeListener(listener: IGlobalKeyListener): void;
|
|
12
|
+
onPermissionLost(listener: IPermissionLostListener): void;
|
|
13
|
+
removePermissionLostListener(listener: IPermissionLostListener): void;
|
|
11
14
|
kill(): void;
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
@@ -32,5 +35,7 @@ declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
|
32
35
|
* Call this before starting the listener to provide better UX when permission is missing.
|
|
33
36
|
*/
|
|
34
37
|
declare function checkKeyboardPermission(): boolean;
|
|
38
|
+
declare function getFocusedInputValue(): string | null;
|
|
39
|
+
declare function getFocusedInputSelectedText(): string | null;
|
|
35
40
|
|
|
36
|
-
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, checkKeyboardPermission, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
|
41
|
+
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
type IGlobalKeyState = 'DOWN' | 'UP';
|
|
1
|
+
type IGlobalKeyState = 'DOWN' | 'UP' | 'PERMISSION_LOST';
|
|
2
2
|
interface IGlobalKeyEvent {
|
|
3
3
|
readonly name: string;
|
|
4
4
|
readonly state: IGlobalKeyState;
|
|
5
5
|
}
|
|
6
6
|
type IGlobalKeyDownMap = Record<string, boolean>;
|
|
7
7
|
type IGlobalKeyListener = (event: IGlobalKeyEvent, isDown: IGlobalKeyDownMap) => void;
|
|
8
|
+
type IPermissionLostListener = () => void;
|
|
8
9
|
interface IGlobalKeyboardListener {
|
|
9
10
|
addListener(listener: IGlobalKeyListener): void;
|
|
10
11
|
removeListener(listener: IGlobalKeyListener): void;
|
|
12
|
+
onPermissionLost(listener: IPermissionLostListener): void;
|
|
13
|
+
removePermissionLostListener(listener: IPermissionLostListener): void;
|
|
11
14
|
kill(): void;
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
@@ -32,5 +35,7 @@ declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
|
|
|
32
35
|
* Call this before starting the listener to provide better UX when permission is missing.
|
|
33
36
|
*/
|
|
34
37
|
declare function checkKeyboardPermission(): boolean;
|
|
38
|
+
declare function getFocusedInputValue(): string | null;
|
|
39
|
+
declare function getFocusedInputSelectedText(): string | null;
|
|
35
40
|
|
|
36
|
-
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, checkKeyboardPermission, createGlobalKeyboardListener, getGlobalKeyboardListener };
|
|
41
|
+
export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener };
|
package/dist/index.js
CHANGED
|
@@ -32,11 +32,14 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
checkKeyboardPermission: () => checkKeyboardPermission,
|
|
34
34
|
createGlobalKeyboardListener: () => createGlobalKeyboardListener,
|
|
35
|
+
getFocusedInputSelectedText: () => getFocusedInputSelectedText,
|
|
36
|
+
getFocusedInputValue: () => getFocusedInputValue,
|
|
35
37
|
getGlobalKeyboardListener: () => getGlobalKeyboardListener
|
|
36
38
|
});
|
|
37
39
|
module.exports = __toCommonJS(index_exports);
|
|
38
40
|
var path = __toESM(require("path"));
|
|
39
41
|
var fs = __toESM(require("fs"));
|
|
42
|
+
var import_node_child_process = require("child_process");
|
|
40
43
|
var import_node_module = require("module");
|
|
41
44
|
var import_url = require("url");
|
|
42
45
|
var import_meta = {};
|
|
@@ -73,8 +76,11 @@ function getNativeAddon() {
|
|
|
73
76
|
const localRequire = getRequire();
|
|
74
77
|
if (packageName) {
|
|
75
78
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const candidate = localRequire(packageName);
|
|
80
|
+
if (candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function" && typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function") {
|
|
81
|
+
nativeAddon = candidate;
|
|
82
|
+
return nativeAddon;
|
|
83
|
+
}
|
|
78
84
|
} catch {
|
|
79
85
|
}
|
|
80
86
|
}
|
|
@@ -103,6 +109,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
103
109
|
static _instance = null;
|
|
104
110
|
started = false;
|
|
105
111
|
listeners = /* @__PURE__ */ new Set();
|
|
112
|
+
permissionLostListeners = /* @__PURE__ */ new Set();
|
|
106
113
|
static getInstance() {
|
|
107
114
|
if (!_NativeKeyboardListener._instance) {
|
|
108
115
|
const addon = getNativeAddon();
|
|
@@ -114,6 +121,10 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
114
121
|
this.listeners.add(listener);
|
|
115
122
|
if (!this.started) {
|
|
116
123
|
const ok = this.addon.start((event) => {
|
|
124
|
+
if (event.state === "PERMISSION_LOST") {
|
|
125
|
+
this.handlePermissionLost();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
117
128
|
const listenersCopy = Array.from(this.listeners);
|
|
118
129
|
for (const cb of listenersCopy) {
|
|
119
130
|
try {
|
|
@@ -128,6 +139,22 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
128
139
|
this.started = true;
|
|
129
140
|
}
|
|
130
141
|
}
|
|
142
|
+
onPermissionLost(listener) {
|
|
143
|
+
this.permissionLostListeners.add(listener);
|
|
144
|
+
}
|
|
145
|
+
removePermissionLostListener(listener) {
|
|
146
|
+
this.permissionLostListeners.delete(listener);
|
|
147
|
+
}
|
|
148
|
+
handlePermissionLost() {
|
|
149
|
+
this.started = false;
|
|
150
|
+
const listenersCopy = Array.from(this.permissionLostListeners);
|
|
151
|
+
for (const cb of listenersCopy) {
|
|
152
|
+
try {
|
|
153
|
+
cb();
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
131
158
|
removeListener(listener) {
|
|
132
159
|
this.listeners.delete(listener);
|
|
133
160
|
if (this.listeners.size === 0 && this.started) {
|
|
@@ -160,6 +187,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
160
187
|
} finally {
|
|
161
188
|
this.started = false;
|
|
162
189
|
this.listeners.clear();
|
|
190
|
+
this.permissionLostListeners.clear();
|
|
163
191
|
_NativeKeyboardListener._instance = null;
|
|
164
192
|
}
|
|
165
193
|
}
|
|
@@ -184,9 +212,66 @@ function checkKeyboardPermission() {
|
|
|
184
212
|
return false;
|
|
185
213
|
}
|
|
186
214
|
}
|
|
215
|
+
var lastMacAccessibilitySettingsOpenTs = 0;
|
|
216
|
+
function openMacAccessibilitySettings() {
|
|
217
|
+
if (process.platform !== "darwin") {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
if (now - lastMacAccessibilitySettingsOpenTs < 15e3) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
lastMacAccessibilitySettingsOpenTs = now;
|
|
225
|
+
try {
|
|
226
|
+
(0, import_node_child_process.execFileSync)("open", ["x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"], {
|
|
227
|
+
stdio: "ignore"
|
|
228
|
+
});
|
|
229
|
+
} catch {
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function ensureAccessibilityPermission(addon) {
|
|
233
|
+
try {
|
|
234
|
+
if (addon.checkPermission()) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
openMacAccessibilitySettings();
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
function getFocusedInputValue() {
|
|
243
|
+
if (process.platform !== "darwin") {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
const addon = getNativeAddon();
|
|
247
|
+
if (!ensureAccessibilityPermission(addon)) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
return addon.getFocusedInputValue();
|
|
252
|
+
} catch {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function getFocusedInputSelectedText() {
|
|
257
|
+
if (process.platform !== "darwin") {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const addon = getNativeAddon();
|
|
261
|
+
if (!ensureAccessibilityPermission(addon)) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
return addon.getFocusedInputSelectedText();
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
187
270
|
// Annotate the CommonJS export names for ESM import in node:
|
|
188
271
|
0 && (module.exports = {
|
|
189
272
|
checkKeyboardPermission,
|
|
190
273
|
createGlobalKeyboardListener,
|
|
274
|
+
getFocusedInputSelectedText,
|
|
275
|
+
getFocusedInputValue,
|
|
191
276
|
getGlobalKeyboardListener
|
|
192
277
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
import * as path from "path";
|
|
10
10
|
import * as fs from "fs";
|
|
11
|
+
import { execFileSync } from "child_process";
|
|
11
12
|
import { createRequire } from "module";
|
|
12
13
|
import { fileURLToPath } from "url";
|
|
13
14
|
var PLATFORM_PACKAGES = {
|
|
@@ -43,8 +44,11 @@ function getNativeAddon() {
|
|
|
43
44
|
const localRequire = getRequire();
|
|
44
45
|
if (packageName) {
|
|
45
46
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const candidate = localRequire(packageName);
|
|
48
|
+
if (candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function" && typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function") {
|
|
49
|
+
nativeAddon = candidate;
|
|
50
|
+
return nativeAddon;
|
|
51
|
+
}
|
|
48
52
|
} catch {
|
|
49
53
|
}
|
|
50
54
|
}
|
|
@@ -73,6 +77,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
73
77
|
static _instance = null;
|
|
74
78
|
started = false;
|
|
75
79
|
listeners = /* @__PURE__ */ new Set();
|
|
80
|
+
permissionLostListeners = /* @__PURE__ */ new Set();
|
|
76
81
|
static getInstance() {
|
|
77
82
|
if (!_NativeKeyboardListener._instance) {
|
|
78
83
|
const addon = getNativeAddon();
|
|
@@ -84,6 +89,10 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
84
89
|
this.listeners.add(listener);
|
|
85
90
|
if (!this.started) {
|
|
86
91
|
const ok = this.addon.start((event) => {
|
|
92
|
+
if (event.state === "PERMISSION_LOST") {
|
|
93
|
+
this.handlePermissionLost();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
87
96
|
const listenersCopy = Array.from(this.listeners);
|
|
88
97
|
for (const cb of listenersCopy) {
|
|
89
98
|
try {
|
|
@@ -98,6 +107,22 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
98
107
|
this.started = true;
|
|
99
108
|
}
|
|
100
109
|
}
|
|
110
|
+
onPermissionLost(listener) {
|
|
111
|
+
this.permissionLostListeners.add(listener);
|
|
112
|
+
}
|
|
113
|
+
removePermissionLostListener(listener) {
|
|
114
|
+
this.permissionLostListeners.delete(listener);
|
|
115
|
+
}
|
|
116
|
+
handlePermissionLost() {
|
|
117
|
+
this.started = false;
|
|
118
|
+
const listenersCopy = Array.from(this.permissionLostListeners);
|
|
119
|
+
for (const cb of listenersCopy) {
|
|
120
|
+
try {
|
|
121
|
+
cb();
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
101
126
|
removeListener(listener) {
|
|
102
127
|
this.listeners.delete(listener);
|
|
103
128
|
if (this.listeners.size === 0 && this.started) {
|
|
@@ -130,6 +155,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
|
|
|
130
155
|
} finally {
|
|
131
156
|
this.started = false;
|
|
132
157
|
this.listeners.clear();
|
|
158
|
+
this.permissionLostListeners.clear();
|
|
133
159
|
_NativeKeyboardListener._instance = null;
|
|
134
160
|
}
|
|
135
161
|
}
|
|
@@ -154,8 +180,65 @@ function checkKeyboardPermission() {
|
|
|
154
180
|
return false;
|
|
155
181
|
}
|
|
156
182
|
}
|
|
183
|
+
var lastMacAccessibilitySettingsOpenTs = 0;
|
|
184
|
+
function openMacAccessibilitySettings() {
|
|
185
|
+
if (process.platform !== "darwin") {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const now = Date.now();
|
|
189
|
+
if (now - lastMacAccessibilitySettingsOpenTs < 15e3) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
lastMacAccessibilitySettingsOpenTs = now;
|
|
193
|
+
try {
|
|
194
|
+
execFileSync("open", ["x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"], {
|
|
195
|
+
stdio: "ignore"
|
|
196
|
+
});
|
|
197
|
+
} catch {
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function ensureAccessibilityPermission(addon) {
|
|
201
|
+
try {
|
|
202
|
+
if (addon.checkPermission()) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
openMacAccessibilitySettings();
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
function getFocusedInputValue() {
|
|
211
|
+
if (process.platform !== "darwin") {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const addon = getNativeAddon();
|
|
215
|
+
if (!ensureAccessibilityPermission(addon)) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
return addon.getFocusedInputValue();
|
|
220
|
+
} catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function getFocusedInputSelectedText() {
|
|
225
|
+
if (process.platform !== "darwin") {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const addon = getNativeAddon();
|
|
229
|
+
if (!ensureAccessibilityPermission(addon)) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
return addon.getFocusedInputSelectedText();
|
|
234
|
+
} catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
157
238
|
export {
|
|
158
239
|
checkKeyboardPermission,
|
|
159
240
|
createGlobalKeyboardListener,
|
|
241
|
+
getFocusedInputSelectedText,
|
|
242
|
+
getFocusedInputValue,
|
|
160
243
|
getGlobalKeyboardListener
|
|
161
244
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simen-keyboard-listener",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Native global keyboard listener for macOS and Windows",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"node-addon-api": "^8.0.0"
|
|
46
46
|
},
|
|
47
47
|
"optionalDependencies": {
|
|
48
|
-
"@simen-keyboard-listener/darwin-arm64": "1.0.
|
|
49
|
-
"@simen-keyboard-listener/win32-x64": "1.0.
|
|
48
|
+
"@simen-keyboard-listener/darwin-arm64": "1.0.10",
|
|
49
|
+
"@simen-keyboard-listener/win32-x64": "1.0.10"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^20.0.0",
|