simen-keyboard-listener 1.1.3 → 1.1.5

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/README.md CHANGED
@@ -13,9 +13,7 @@ The package uses `optionalDependencies` to automatically install the correct nat
13
13
  | Package | Platform |
14
14
  |---------|----------|
15
15
  | `@simen-keyboard-listener/darwin-arm64` | macOS Apple Silicon |
16
- | `@simen-keyboard-listener/darwin-x64` | macOS Intel |
17
16
  | `@simen-keyboard-listener/win32-x64` | Windows x64 |
18
- | `@simen-keyboard-listener/win32-arm64` | Windows ARM64 |
19
17
 
20
18
  ### For Electron/Bundler Projects
21
19
 
@@ -37,9 +35,7 @@ If you're using webpack, electron-builder, or other bundlers, you may need to co
37
35
  module.exports = {
38
36
  externals: {
39
37
  '@simen-keyboard-listener/darwin-arm64': 'commonjs @simen-keyboard-listener/darwin-arm64',
40
- '@simen-keyboard-listener/darwin-x64': 'commonjs @simen-keyboard-listener/darwin-x64',
41
38
  '@simen-keyboard-listener/win32-x64': 'commonjs @simen-keyboard-listener/win32-x64',
42
- '@simen-keyboard-listener/win32-arm64': 'commonjs @simen-keyboard-listener/win32-arm64',
43
39
  }
44
40
  };
45
41
  ```
@@ -59,6 +55,75 @@ listener.addListener((event, isDown) => {
59
55
  listener.removeListener(myListener);
60
56
  ```
61
57
 
58
+ ## 开发与构建
59
+
60
+ ### 构建原生模块
61
+
62
+ 本项目包含 C++ 和 Swift 原生代码,需要编译为平台特定的二进制文件。构建脚本会自动处理编译和文件复制。
63
+
64
+ #### 一键构建(推荐)
65
+
66
+ 自动检测当前平台并构建:
67
+
68
+ ```bash
69
+ npm run prebuild
70
+ ```
71
+
72
+ 此命令会:
73
+ - 自动检测当前操作系统和架构
74
+ - macOS:编译 Swift 辅助文件 + 构建原生模块 + 复制到 `packages/darwin-arm64/`
75
+ - Windows:构建原生模块 + 复制到 `packages/win32-x64/`
76
+
77
+ #### 手动指定平台构建
78
+
79
+ **Windows 平台:**
80
+ ```bash
81
+ npm run prebuild:win
82
+ ```
83
+
84
+ **macOS 平台:**
85
+ ```bash
86
+ npm run prebuild:mac
87
+ ```
88
+
89
+ #### 仅复制已构建的文件
90
+
91
+ 如果已经构建完成,只需要复制文件到 packages 目录:
92
+
93
+ ```bash
94
+ npm run copy-native win32-x64 # Windows
95
+ npm run copy-native darwin-arm64 # macOS
96
+ ```
97
+
98
+ #### 完整构建流程
99
+
100
+ 如果需要构建 TypeScript 代码和原生模块:
101
+
102
+ ```bash
103
+ npm run build
104
+ ```
105
+
106
+ 这会执行:
107
+ 1. 编译 Swift 文件(macOS)
108
+ 2. 构建原生模块(node-gyp)
109
+ 3. 编译 TypeScript 代码
110
+
111
+ ### 发布流程
112
+
113
+ 发布所有平台包到 npm:
114
+
115
+ ```bash
116
+ npm run publish:all
117
+ ```
118
+
119
+ 发布脚本会:
120
+ 1. 同步所有平台包的版本号
121
+ 2. 检查 `.node` 文件是否存在
122
+ 3. 依次发布各平台包
123
+ 4. 最后发布主包
124
+
125
+ **注意:** 发布前需要确保所有平台的 `.node` 文件都已构建并复制到对应的 `packages/` 目录。
126
+
62
127
  ## API
63
128
 
64
129
  ### `getGlobalKeyboardListener(): IGlobalKeyboardListener`
@@ -91,8 +156,8 @@ interface IGlobalKeyEvent {
91
156
 
92
157
  ## Platform Support
93
158
 
94
- - macOS (x64, arm64)
95
- - Windows (x64, arm64)
159
+ - macOS ARM64 (Apple Silicon)
160
+ - Windows x64
96
161
 
97
162
  ## Requirements
98
163
 
package/dist/index.d.mts CHANGED
@@ -49,5 +49,20 @@ declare function getContextJSON(): string | null;
49
49
  * @returns 选中文本或 null
50
50
  */
51
51
  declare function getSelectedTextSmart(): string | null;
52
+ /**
53
+ * Set whether to block ALL system hotkeys involving modifier key combinations.
54
+ * This covers: Shift+Alt (IME switch), Ctrl+Shift (IME switch), Win+Space (IME switch),
55
+ * Alt release (menu activation), Win release (Start menu), etc.
56
+ *
57
+ * When enabled:
58
+ * - On modifier key DOWN with another modifier held: inject F13 to break system hotkey detection
59
+ * - On Alt release: inject F13 to prevent menu activation
60
+ * - On Win release: inject Shift+Win sequence to prevent Start menu
61
+ *
62
+ * Windows only - no-op on other platforms.
63
+ *
64
+ * @param block true = block all system hotkeys, false = allow normal behavior
65
+ */
66
+ declare function setBlockSystemHotkeys(block: boolean): void;
52
67
 
53
- export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getContextJSON, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener, getSelectedTextSmart };
68
+ export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getContextJSON, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener, getSelectedTextSmart, setBlockSystemHotkeys };
package/dist/index.d.ts CHANGED
@@ -49,5 +49,20 @@ declare function getContextJSON(): string | null;
49
49
  * @returns 选中文本或 null
50
50
  */
51
51
  declare function getSelectedTextSmart(): string | null;
52
+ /**
53
+ * Set whether to block ALL system hotkeys involving modifier key combinations.
54
+ * This covers: Shift+Alt (IME switch), Ctrl+Shift (IME switch), Win+Space (IME switch),
55
+ * Alt release (menu activation), Win release (Start menu), etc.
56
+ *
57
+ * When enabled:
58
+ * - On modifier key DOWN with another modifier held: inject F13 to break system hotkey detection
59
+ * - On Alt release: inject F13 to prevent menu activation
60
+ * - On Win release: inject Shift+Win sequence to prevent Start menu
61
+ *
62
+ * Windows only - no-op on other platforms.
63
+ *
64
+ * @param block true = block all system hotkeys, false = allow normal behavior
65
+ */
66
+ declare function setBlockSystemHotkeys(block: boolean): void;
52
67
 
53
- export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getContextJSON, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener, getSelectedTextSmart };
68
+ export { type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, checkKeyboardPermission, createGlobalKeyboardListener, getContextJSON, getFocusedInputSelectedText, getFocusedInputValue, getGlobalKeyboardListener, getSelectedTextSmart, setBlockSystemHotkeys };
package/dist/index.js CHANGED
@@ -36,7 +36,8 @@ __export(index_exports, {
36
36
  getFocusedInputSelectedText: () => getFocusedInputSelectedText,
37
37
  getFocusedInputValue: () => getFocusedInputValue,
38
38
  getGlobalKeyboardListener: () => getGlobalKeyboardListener,
39
- getSelectedTextSmart: () => getSelectedTextSmart
39
+ getSelectedTextSmart: () => getSelectedTextSmart,
40
+ setBlockSystemHotkeys: () => setBlockSystemHotkeys
40
41
  });
41
42
  module.exports = __toCommonJS(index_exports);
42
43
  var path = __toESM(require("path"));
@@ -45,6 +46,8 @@ var import_node_child_process = require("child_process");
45
46
  var import_node_module = require("module");
46
47
  var import_url = require("url");
47
48
  var import_meta = {};
49
+ var IS_MACOS = process.platform === "darwin";
50
+ var IS_WINDOWS = process.platform === "win32";
48
51
  var PLATFORM_PACKAGES = {
49
52
  "darwin-arm64": "@simen-keyboard-listener/darwin-arm64",
50
53
  "win32-x64": "@simen-keyboard-listener/win32-x64"
@@ -79,7 +82,9 @@ function getNativeAddon() {
79
82
  if (packageName) {
80
83
  try {
81
84
  const candidate = localRequire(packageName);
82
- 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") {
85
+ const hasCoreFunctions = candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function";
86
+ const hasMacOSFunctions = IS_MACOS ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
87
+ if (hasCoreFunctions && hasMacOSFunctions) {
83
88
  nativeAddon = candidate;
84
89
  return nativeAddon;
85
90
  }
@@ -195,7 +200,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
195
200
  }
196
201
  };
197
202
  function getGlobalKeyboardListener() {
198
- if (process.platform !== "darwin" && process.platform !== "win32") {
203
+ if (!IS_MACOS && !IS_WINDOWS) {
199
204
  throw new Error(`Unsupported platform for global keyboard listener: ${process.platform}`);
200
205
  }
201
206
  return NativeKeyboardListener.getInstance();
@@ -204,7 +209,7 @@ function createGlobalKeyboardListener() {
204
209
  return getGlobalKeyboardListener();
205
210
  }
206
211
  function checkKeyboardPermission() {
207
- if (process.platform !== "darwin" && process.platform !== "win32") {
212
+ if (!IS_MACOS && !IS_WINDOWS) {
208
213
  return false;
209
214
  }
210
215
  try {
@@ -216,7 +221,7 @@ function checkKeyboardPermission() {
216
221
  }
217
222
  var lastMacAccessibilitySettingsOpenTs = 0;
218
223
  function openMacAccessibilitySettings() {
219
- if (process.platform !== "darwin") {
224
+ if (!IS_MACOS) {
220
225
  return;
221
226
  }
222
227
  const now = Date.now();
@@ -242,7 +247,7 @@ function ensureAccessibilityPermission(addon) {
242
247
  return false;
243
248
  }
244
249
  function getFocusedInputValue() {
245
- if (process.platform !== "darwin") {
250
+ if (!IS_MACOS) {
246
251
  return null;
247
252
  }
248
253
  const addon = getNativeAddon();
@@ -256,7 +261,7 @@ function getFocusedInputValue() {
256
261
  }
257
262
  }
258
263
  function getFocusedInputSelectedText() {
259
- if (process.platform !== "darwin") {
264
+ if (!IS_MACOS) {
260
265
  return null;
261
266
  }
262
267
  const addon = getNativeAddon();
@@ -270,7 +275,7 @@ function getFocusedInputSelectedText() {
270
275
  }
271
276
  }
272
277
  function getContextJSON() {
273
- if (process.platform !== "darwin") return null;
278
+ if (!IS_MACOS) return null;
274
279
  const addon = getNativeAddon();
275
280
  if (!ensureAccessibilityPermission(addon)) return null;
276
281
  try {
@@ -280,7 +285,7 @@ function getContextJSON() {
280
285
  }
281
286
  }
282
287
  function getSelectedTextSmart() {
283
- if (process.platform !== "darwin") return null;
288
+ if (!IS_MACOS) return null;
284
289
  const addon = getNativeAddon();
285
290
  if (!ensureAccessibilityPermission(addon)) return null;
286
291
  try {
@@ -289,6 +294,16 @@ function getSelectedTextSmart() {
289
294
  return null;
290
295
  }
291
296
  }
297
+ function setBlockSystemHotkeys(block) {
298
+ if (!IS_WINDOWS) {
299
+ return;
300
+ }
301
+ try {
302
+ const addon = getNativeAddon();
303
+ addon.setBlockSystemHotkeys?.(block);
304
+ } catch {
305
+ }
306
+ }
292
307
  // Annotate the CommonJS export names for ESM import in node:
293
308
  0 && (module.exports = {
294
309
  checkKeyboardPermission,
@@ -297,5 +312,6 @@ function getSelectedTextSmart() {
297
312
  getFocusedInputSelectedText,
298
313
  getFocusedInputValue,
299
314
  getGlobalKeyboardListener,
300
- getSelectedTextSmart
315
+ getSelectedTextSmart,
316
+ setBlockSystemHotkeys
301
317
  });
package/dist/index.mjs CHANGED
@@ -11,6 +11,8 @@ import * as fs from "fs";
11
11
  import { execFileSync } from "child_process";
12
12
  import { createRequire } from "module";
13
13
  import { fileURLToPath } from "url";
14
+ var IS_MACOS = process.platform === "darwin";
15
+ var IS_WINDOWS = process.platform === "win32";
14
16
  var PLATFORM_PACKAGES = {
15
17
  "darwin-arm64": "@simen-keyboard-listener/darwin-arm64",
16
18
  "win32-x64": "@simen-keyboard-listener/win32-x64"
@@ -45,7 +47,9 @@ function getNativeAddon() {
45
47
  if (packageName) {
46
48
  try {
47
49
  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") {
50
+ const hasCoreFunctions = candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function";
51
+ const hasMacOSFunctions = IS_MACOS ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
52
+ if (hasCoreFunctions && hasMacOSFunctions) {
49
53
  nativeAddon = candidate;
50
54
  return nativeAddon;
51
55
  }
@@ -161,7 +165,7 @@ var NativeKeyboardListener = class _NativeKeyboardListener {
161
165
  }
162
166
  };
163
167
  function getGlobalKeyboardListener() {
164
- if (process.platform !== "darwin" && process.platform !== "win32") {
168
+ if (!IS_MACOS && !IS_WINDOWS) {
165
169
  throw new Error(`Unsupported platform for global keyboard listener: ${process.platform}`);
166
170
  }
167
171
  return NativeKeyboardListener.getInstance();
@@ -170,7 +174,7 @@ function createGlobalKeyboardListener() {
170
174
  return getGlobalKeyboardListener();
171
175
  }
172
176
  function checkKeyboardPermission() {
173
- if (process.platform !== "darwin" && process.platform !== "win32") {
177
+ if (!IS_MACOS && !IS_WINDOWS) {
174
178
  return false;
175
179
  }
176
180
  try {
@@ -182,7 +186,7 @@ function checkKeyboardPermission() {
182
186
  }
183
187
  var lastMacAccessibilitySettingsOpenTs = 0;
184
188
  function openMacAccessibilitySettings() {
185
- if (process.platform !== "darwin") {
189
+ if (!IS_MACOS) {
186
190
  return;
187
191
  }
188
192
  const now = Date.now();
@@ -208,7 +212,7 @@ function ensureAccessibilityPermission(addon) {
208
212
  return false;
209
213
  }
210
214
  function getFocusedInputValue() {
211
- if (process.platform !== "darwin") {
215
+ if (!IS_MACOS) {
212
216
  return null;
213
217
  }
214
218
  const addon = getNativeAddon();
@@ -222,7 +226,7 @@ function getFocusedInputValue() {
222
226
  }
223
227
  }
224
228
  function getFocusedInputSelectedText() {
225
- if (process.platform !== "darwin") {
229
+ if (!IS_MACOS) {
226
230
  return null;
227
231
  }
228
232
  const addon = getNativeAddon();
@@ -236,7 +240,7 @@ function getFocusedInputSelectedText() {
236
240
  }
237
241
  }
238
242
  function getContextJSON() {
239
- if (process.platform !== "darwin") return null;
243
+ if (!IS_MACOS) return null;
240
244
  const addon = getNativeAddon();
241
245
  if (!ensureAccessibilityPermission(addon)) return null;
242
246
  try {
@@ -246,7 +250,7 @@ function getContextJSON() {
246
250
  }
247
251
  }
248
252
  function getSelectedTextSmart() {
249
- if (process.platform !== "darwin") return null;
253
+ if (!IS_MACOS) return null;
250
254
  const addon = getNativeAddon();
251
255
  if (!ensureAccessibilityPermission(addon)) return null;
252
256
  try {
@@ -255,6 +259,16 @@ function getSelectedTextSmart() {
255
259
  return null;
256
260
  }
257
261
  }
262
+ function setBlockSystemHotkeys(block) {
263
+ if (!IS_WINDOWS) {
264
+ return;
265
+ }
266
+ try {
267
+ const addon = getNativeAddon();
268
+ addon.setBlockSystemHotkeys?.(block);
269
+ } catch {
270
+ }
271
+ }
258
272
  export {
259
273
  checkKeyboardPermission,
260
274
  createGlobalKeyboardListener,
@@ -262,5 +276,6 @@ export {
262
276
  getFocusedInputSelectedText,
263
277
  getFocusedInputValue,
264
278
  getGlobalKeyboardListener,
265
- getSelectedTextSmart
279
+ getSelectedTextSmart,
280
+ setBlockSystemHotkeys
266
281
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simen-keyboard-listener",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Native global keyboard listener for macOS and Windows",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,7 +20,10 @@
20
20
  "build:native": "npm run build:swift && node-gyp rebuild --directory=src/native",
21
21
  "build:ts": "tsup src/index.ts --format cjs,esm --dts --clean",
22
22
  "build": "npm run build:native && npm run build:ts",
23
- "prebuild": "npm run build:swift && prebuildify --napi --strip --cwd src/native --out ../../prebuilds",
23
+ "prebuild": "node scripts/prebuild-current.js",
24
+ "prebuild:win": "npx node-gyp rebuild --directory=src/native && node scripts/copy-native.js win32-x64",
25
+ "prebuild:mac": "npm run build:swift && npx node-gyp rebuild --directory=src/native && node scripts/copy-native.js darwin-arm64",
26
+ "copy-native": "node scripts/copy-native.js",
24
27
  "prepublishOnly": "npm run build:ts",
25
28
  "publish:all": "node scripts/publish.js"
26
29
  },
@@ -46,8 +49,8 @@
46
49
  "node-addon-api": "^8.0.0"
47
50
  },
48
51
  "optionalDependencies": {
49
- "@simen-keyboard-listener/darwin-arm64": "1.1.3",
50
- "@simen-keyboard-listener/win32-x64": "1.1.3"
52
+ "@simen-keyboard-listener/darwin-arm64": "1.1.5",
53
+ "@simen-keyboard-listener/win32-x64": "1.1.5"
51
54
  },
52
55
  "devDependencies": {
53
56
  "@types/node": "^20.0.0",