simen-keyboard-listener 1.1.17 → 1.1.19

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
@@ -145,6 +145,21 @@ interface IGlobalKeyEvent {
145
145
  }
146
146
  ```
147
147
 
148
+ ### Context APIs (macOS & Windows)
149
+
150
+ 这些 API 在 macOS 和 Windows 上都可用:
151
+
152
+ - `getSelectedTextSmart(): string | null` - 获取选中文本(必要时模拟 Cmd+C / Ctrl+C)
153
+ - `getContextJSON(): string | null` - 获取完整上下文(JSON)
154
+ - `getFrontmostAppInfo(): IAppInfo | null` - 获取前台应用信息
155
+ - `getFocusedElementInfo(): IElementInfo | null` - 获取焦点元素信息
156
+ - `getFocusedTextInfo(): ITextInfo | null` - 获取文本信息(选中/输入框等)
157
+ - `getFocusedDOMInfo(): IDOMInfo | null` - 获取浏览器 DOM 信息(仅浏览器应用)
158
+
159
+ **平台差异:**
160
+ - macOS: 使用 Accessibility API,需要辅助功能权限
161
+ - Windows: 使用 UI Automation API,无需特殊权限
162
+
148
163
  ## Supported Keys
149
164
 
150
165
  - **Modifiers**: FN (macOS), SHIFT, CTRL, ALT, META (Cmd/Win)
package/dist/index.d.mts CHANGED
@@ -853,6 +853,47 @@ interface IGlobalKeyEvent {
853
853
  type IGlobalKeyDownMap = Record<string, boolean>;
854
854
  type IGlobalKeyListener = (event: IGlobalKeyEvent, isDown: IGlobalKeyDownMap) => void;
855
855
  type IPermissionLostListener = () => void;
856
+ /**
857
+ * Frontmost app info - lightweight app context
858
+ */
859
+ interface IFrontmostInfo {
860
+ readonly app: {
861
+ readonly name: string;
862
+ readonly bundleId: string;
863
+ readonly pid: number;
864
+ readonly appType: 'browser' | 'wechat' | 'editor' | 'terminal' | 'other';
865
+ };
866
+ readonly window: {
867
+ readonly title: string | null;
868
+ readonly url: string | null;
869
+ };
870
+ }
871
+ /**
872
+ * Unified page context info - the main context API structure
873
+ */
874
+ interface IPageContextInfo {
875
+ readonly app: {
876
+ readonly name: string;
877
+ readonly bundleId: string;
878
+ readonly appType: 'browser' | 'wechat' | 'editor' | 'terminal' | 'other';
879
+ };
880
+ readonly window: {
881
+ readonly title: string | null;
882
+ readonly url: string | null;
883
+ };
884
+ readonly focusedElement: {
885
+ readonly role: string;
886
+ readonly isEditable: boolean;
887
+ readonly value: string | null;
888
+ readonly placeholder: string | null;
889
+ readonly label: string | null;
890
+ };
891
+ readonly selectedText: string | null;
892
+ readonly cursor: {
893
+ readonly position: number | null;
894
+ readonly line: number | null;
895
+ } | null;
896
+ }
856
897
  interface IGlobalKeyboardListener {
857
898
  addListener(listener: IGlobalKeyListener): void;
858
899
  removeListener(listener: IGlobalKeyListener): void;
@@ -882,17 +923,32 @@ declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
882
923
  * Call this before starting the listener to provide better UX when permission is missing.
883
924
  */
884
925
  declare function checkKeyboardPermission(): boolean;
885
- declare function getFocusedInputValue(): string | null;
886
- declare function getFocusedInputSelectedText(): string | null;
887
926
  /**
888
- * 获取完整上下文信息(JSON 格式)
889
- * 包含:应用信息、焦点元素、选中文本、DOM 信息等
890
- * @returns JSON 字符串或 null
927
+ * Check if the currently focused element is editable
928
+ * @returns true if focused element is editable, false otherwise
929
+ */
930
+ declare function isEditable(): boolean;
931
+ /**
932
+ * Get the value of the currently focused input element
933
+ * @returns input value string or null
891
934
  */
892
- declare function getContextJSON(): string | null;
935
+ declare function getFocusedValue(): string | null;
936
+ /**
937
+ * Get frontmost app info (lightweight)
938
+ * Includes: app info, window title/url
939
+ * @returns frontmost info or null
940
+ */
941
+ declare function getFrontmostInfo(): IFrontmostInfo | null;
942
+ /**
943
+ * Get unified page context info
944
+ * Includes: app info, window info, focused element, selected text, cursor position
945
+ * @returns page context or null
946
+ */
947
+ declare function getPageContext(): IPageContextInfo | null;
893
948
  /**
894
949
  * 智能获取选中文本
895
- * 优先用 Accessibility API,失败则用模拟 Cmd+C(支持微信等)
950
+ * - macOS: 优先用 Accessibility API,失败则用模拟 Cmd+C
951
+ * - Windows: 优先用 UI Automation,失败则用模拟 Ctrl+C
896
952
  * @returns 选中文本或 null
897
953
  */
898
954
  declare function getSelectedTextSmart(): string | null;
@@ -911,5 +967,28 @@ declare function getSelectedTextSmart(): string | null;
911
967
  * @param block true = block all system hotkeys, false = allow normal behavior
912
968
  */
913
969
  declare function setBlockSystemHotkeys(block: boolean): void;
970
+ /**
971
+ * Set the list of shortcut combinations that should block fn key (keyCode 179) events.
972
+ * This is used to prevent macOS emoji panel from appearing when using fn-based shortcuts.
973
+ *
974
+ * When enabled, the native event tap will return NULL for keyCode 179 events that match
975
+ * the blocked shortcuts, effectively preventing the emoji panel from opening.
976
+ *
977
+ * macOS only - no-op on other platforms.
978
+ *
979
+ * @param shortcuts Array of shortcut strings to block. Format: modifiers joined by "+",
980
+ * in order: ctrl, alt, shift, cmd, fn
981
+ *
982
+ * @example
983
+ * // Block single fn key press (prevents emoji panel)
984
+ * setBlockedShortcuts(['fn']);
985
+ *
986
+ * // Block fn and shift+fn combinations
987
+ * setBlockedShortcuts(['fn', 'shift+fn']);
988
+ *
989
+ * // Clear all blocked shortcuts (restore normal behavior)
990
+ * setBlockedShortcuts([]);
991
+ */
992
+ declare function setBlockedShortcuts(shortcuts: string[]): void;
914
993
 
915
- export { type IAgentContext$1 as IAgentContext, type IAgentContextOptions$1 as IAgentContextOptions, type IClipboardContent$1 as IClipboardContent, type IDesktopItem$1 as IDesktopItem, type IExecuteOptions$1 as IExecuteOptions, type IExecuteResult$1 as IExecuteResult, type IFileContent$1 as IFileContent, type IFileMetadata$1 as IFileMetadata, type IFinderContext, type IFinderItem, type IFinderSelection, type IFinderWindow, type IFinderWindowInfo, type IFinderWindowItem, type IFrontmostApp$1 as IFrontmostApp, type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, type IReadFileOptions$1 as IReadFileOptions, type IRecentFile$1 as IRecentFile, type IRunningApp$1 as IRunningApp, type ISelectedItem$1 as ISelectedItem, type ISystemContext$1 as ISystemContext, checkKeyboardPermission, createGlobalKeyboardListener, escapeForAppleScript, executeAndParse$1 as executeAndParse, executeAppleScript, executeAppleScriptLines, executeMultilineAndParse$1 as executeMultilineAndParse, getAgentContext$1 as getAgentContext, getClipboardContent$1 as getClipboardContent, getClipboardText$1 as getClipboardText, getContextJSON, getDesktopItems, getDesktopPath, getFileMetadata, getFilesMetadata, getFinderContext, getFinderCurrentFolder, getFinderSelection, getFinderWindows, getFocusedInputSelectedText, getFocusedInputValue, getFrontmostApp$1 as getFrontmostApp, getFrontmostFromRunning, getGlobalKeyboardListener, getRecentDocuments, getRecentFiles, getRunningApps, getSelectedTextSmart, getSystemContext$1 as getSystemContext, isAppRunning, isOsascriptAvailable, index as powershell, readFileContent, readMultipleFiles, setBlockSystemHotkeys };
994
+ export { type IAgentContext$1 as IAgentContext, type IAgentContextOptions$1 as IAgentContextOptions, type IClipboardContent$1 as IClipboardContent, type IDesktopItem$1 as IDesktopItem, type IExecuteOptions$1 as IExecuteOptions, type IExecuteResult$1 as IExecuteResult, type IFileContent$1 as IFileContent, type IFileMetadata$1 as IFileMetadata, type IFinderContext, type IFinderItem, type IFinderSelection, type IFinderWindow, type IFinderWindowInfo, type IFinderWindowItem, type IFrontmostApp$1 as IFrontmostApp, type IFrontmostInfo, type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPageContextInfo, type IPermissionLostListener, type IReadFileOptions$1 as IReadFileOptions, type IRecentFile$1 as IRecentFile, type IRunningApp$1 as IRunningApp, type ISelectedItem$1 as ISelectedItem, type ISystemContext$1 as ISystemContext, checkKeyboardPermission, createGlobalKeyboardListener, escapeForAppleScript, executeAndParse$1 as executeAndParse, executeAppleScript, executeAppleScriptLines, executeMultilineAndParse$1 as executeMultilineAndParse, getAgentContext$1 as getAgentContext, getClipboardContent$1 as getClipboardContent, getClipboardText$1 as getClipboardText, getDesktopItems, getDesktopPath, getFileMetadata, getFilesMetadata, getFinderContext, getFinderCurrentFolder, getFinderSelection, getFinderWindows, getFocusedValue, getFrontmostApp$1 as getFrontmostApp, getFrontmostFromRunning, getFrontmostInfo, getGlobalKeyboardListener, getPageContext, getRecentDocuments, getRecentFiles, getRunningApps, getSelectedTextSmart, getSystemContext$1 as getSystemContext, isAppRunning, isEditable, isOsascriptAvailable, index as powershell, readFileContent, readMultipleFiles, setBlockSystemHotkeys, setBlockedShortcuts };
package/dist/index.d.ts CHANGED
@@ -853,6 +853,47 @@ interface IGlobalKeyEvent {
853
853
  type IGlobalKeyDownMap = Record<string, boolean>;
854
854
  type IGlobalKeyListener = (event: IGlobalKeyEvent, isDown: IGlobalKeyDownMap) => void;
855
855
  type IPermissionLostListener = () => void;
856
+ /**
857
+ * Frontmost app info - lightweight app context
858
+ */
859
+ interface IFrontmostInfo {
860
+ readonly app: {
861
+ readonly name: string;
862
+ readonly bundleId: string;
863
+ readonly pid: number;
864
+ readonly appType: 'browser' | 'wechat' | 'editor' | 'terminal' | 'other';
865
+ };
866
+ readonly window: {
867
+ readonly title: string | null;
868
+ readonly url: string | null;
869
+ };
870
+ }
871
+ /**
872
+ * Unified page context info - the main context API structure
873
+ */
874
+ interface IPageContextInfo {
875
+ readonly app: {
876
+ readonly name: string;
877
+ readonly bundleId: string;
878
+ readonly appType: 'browser' | 'wechat' | 'editor' | 'terminal' | 'other';
879
+ };
880
+ readonly window: {
881
+ readonly title: string | null;
882
+ readonly url: string | null;
883
+ };
884
+ readonly focusedElement: {
885
+ readonly role: string;
886
+ readonly isEditable: boolean;
887
+ readonly value: string | null;
888
+ readonly placeholder: string | null;
889
+ readonly label: string | null;
890
+ };
891
+ readonly selectedText: string | null;
892
+ readonly cursor: {
893
+ readonly position: number | null;
894
+ readonly line: number | null;
895
+ } | null;
896
+ }
856
897
  interface IGlobalKeyboardListener {
857
898
  addListener(listener: IGlobalKeyListener): void;
858
899
  removeListener(listener: IGlobalKeyListener): void;
@@ -882,17 +923,32 @@ declare function createGlobalKeyboardListener(): IGlobalKeyboardListener;
882
923
  * Call this before starting the listener to provide better UX when permission is missing.
883
924
  */
884
925
  declare function checkKeyboardPermission(): boolean;
885
- declare function getFocusedInputValue(): string | null;
886
- declare function getFocusedInputSelectedText(): string | null;
887
926
  /**
888
- * 获取完整上下文信息(JSON 格式)
889
- * 包含:应用信息、焦点元素、选中文本、DOM 信息等
890
- * @returns JSON 字符串或 null
927
+ * Check if the currently focused element is editable
928
+ * @returns true if focused element is editable, false otherwise
929
+ */
930
+ declare function isEditable(): boolean;
931
+ /**
932
+ * Get the value of the currently focused input element
933
+ * @returns input value string or null
891
934
  */
892
- declare function getContextJSON(): string | null;
935
+ declare function getFocusedValue(): string | null;
936
+ /**
937
+ * Get frontmost app info (lightweight)
938
+ * Includes: app info, window title/url
939
+ * @returns frontmost info or null
940
+ */
941
+ declare function getFrontmostInfo(): IFrontmostInfo | null;
942
+ /**
943
+ * Get unified page context info
944
+ * Includes: app info, window info, focused element, selected text, cursor position
945
+ * @returns page context or null
946
+ */
947
+ declare function getPageContext(): IPageContextInfo | null;
893
948
  /**
894
949
  * 智能获取选中文本
895
- * 优先用 Accessibility API,失败则用模拟 Cmd+C(支持微信等)
950
+ * - macOS: 优先用 Accessibility API,失败则用模拟 Cmd+C
951
+ * - Windows: 优先用 UI Automation,失败则用模拟 Ctrl+C
896
952
  * @returns 选中文本或 null
897
953
  */
898
954
  declare function getSelectedTextSmart(): string | null;
@@ -911,5 +967,28 @@ declare function getSelectedTextSmart(): string | null;
911
967
  * @param block true = block all system hotkeys, false = allow normal behavior
912
968
  */
913
969
  declare function setBlockSystemHotkeys(block: boolean): void;
970
+ /**
971
+ * Set the list of shortcut combinations that should block fn key (keyCode 179) events.
972
+ * This is used to prevent macOS emoji panel from appearing when using fn-based shortcuts.
973
+ *
974
+ * When enabled, the native event tap will return NULL for keyCode 179 events that match
975
+ * the blocked shortcuts, effectively preventing the emoji panel from opening.
976
+ *
977
+ * macOS only - no-op on other platforms.
978
+ *
979
+ * @param shortcuts Array of shortcut strings to block. Format: modifiers joined by "+",
980
+ * in order: ctrl, alt, shift, cmd, fn
981
+ *
982
+ * @example
983
+ * // Block single fn key press (prevents emoji panel)
984
+ * setBlockedShortcuts(['fn']);
985
+ *
986
+ * // Block fn and shift+fn combinations
987
+ * setBlockedShortcuts(['fn', 'shift+fn']);
988
+ *
989
+ * // Clear all blocked shortcuts (restore normal behavior)
990
+ * setBlockedShortcuts([]);
991
+ */
992
+ declare function setBlockedShortcuts(shortcuts: string[]): void;
914
993
 
915
- export { type IAgentContext$1 as IAgentContext, type IAgentContextOptions$1 as IAgentContextOptions, type IClipboardContent$1 as IClipboardContent, type IDesktopItem$1 as IDesktopItem, type IExecuteOptions$1 as IExecuteOptions, type IExecuteResult$1 as IExecuteResult, type IFileContent$1 as IFileContent, type IFileMetadata$1 as IFileMetadata, type IFinderContext, type IFinderItem, type IFinderSelection, type IFinderWindow, type IFinderWindowInfo, type IFinderWindowItem, type IFrontmostApp$1 as IFrontmostApp, type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPermissionLostListener, type IReadFileOptions$1 as IReadFileOptions, type IRecentFile$1 as IRecentFile, type IRunningApp$1 as IRunningApp, type ISelectedItem$1 as ISelectedItem, type ISystemContext$1 as ISystemContext, checkKeyboardPermission, createGlobalKeyboardListener, escapeForAppleScript, executeAndParse$1 as executeAndParse, executeAppleScript, executeAppleScriptLines, executeMultilineAndParse$1 as executeMultilineAndParse, getAgentContext$1 as getAgentContext, getClipboardContent$1 as getClipboardContent, getClipboardText$1 as getClipboardText, getContextJSON, getDesktopItems, getDesktopPath, getFileMetadata, getFilesMetadata, getFinderContext, getFinderCurrentFolder, getFinderSelection, getFinderWindows, getFocusedInputSelectedText, getFocusedInputValue, getFrontmostApp$1 as getFrontmostApp, getFrontmostFromRunning, getGlobalKeyboardListener, getRecentDocuments, getRecentFiles, getRunningApps, getSelectedTextSmart, getSystemContext$1 as getSystemContext, isAppRunning, isOsascriptAvailable, index as powershell, readFileContent, readMultipleFiles, setBlockSystemHotkeys };
994
+ export { type IAgentContext$1 as IAgentContext, type IAgentContextOptions$1 as IAgentContextOptions, type IClipboardContent$1 as IClipboardContent, type IDesktopItem$1 as IDesktopItem, type IExecuteOptions$1 as IExecuteOptions, type IExecuteResult$1 as IExecuteResult, type IFileContent$1 as IFileContent, type IFileMetadata$1 as IFileMetadata, type IFinderContext, type IFinderItem, type IFinderSelection, type IFinderWindow, type IFinderWindowInfo, type IFinderWindowItem, type IFrontmostApp$1 as IFrontmostApp, type IFrontmostInfo, type IGlobalKeyDownMap, type IGlobalKeyEvent, type IGlobalKeyListener, type IGlobalKeyState, type IGlobalKeyboardListener, type IPageContextInfo, type IPermissionLostListener, type IReadFileOptions$1 as IReadFileOptions, type IRecentFile$1 as IRecentFile, type IRunningApp$1 as IRunningApp, type ISelectedItem$1 as ISelectedItem, type ISystemContext$1 as ISystemContext, checkKeyboardPermission, createGlobalKeyboardListener, escapeForAppleScript, executeAndParse$1 as executeAndParse, executeAppleScript, executeAppleScriptLines, executeMultilineAndParse$1 as executeMultilineAndParse, getAgentContext$1 as getAgentContext, getClipboardContent$1 as getClipboardContent, getClipboardText$1 as getClipboardText, getDesktopItems, getDesktopPath, getFileMetadata, getFilesMetadata, getFinderContext, getFinderCurrentFolder, getFinderSelection, getFinderWindows, getFocusedValue, getFrontmostApp$1 as getFrontmostApp, getFrontmostFromRunning, getFrontmostInfo, getGlobalKeyboardListener, getPageContext, getRecentDocuments, getRecentFiles, getRunningApps, getSelectedTextSmart, getSystemContext$1 as getSystemContext, isAppRunning, isEditable, isOsascriptAvailable, index as powershell, readFileContent, readMultipleFiles, setBlockSystemHotkeys, setBlockedShortcuts };
package/dist/index.js CHANGED
@@ -40,7 +40,6 @@ __export(index_exports, {
40
40
  getAgentContext: () => getAgentContext,
41
41
  getClipboardContent: () => getClipboardContent,
42
42
  getClipboardText: () => getClipboardText,
43
- getContextJSON: () => getContextJSON,
44
43
  getDesktopItems: () => getDesktopItems,
45
44
  getDesktopPath: () => getDesktopPath,
46
45
  getFileMetadata: () => getFileMetadata,
@@ -49,22 +48,25 @@ __export(index_exports, {
49
48
  getFinderCurrentFolder: () => getFinderCurrentFolder,
50
49
  getFinderSelection: () => getFinderSelection,
51
50
  getFinderWindows: () => getFinderWindows,
52
- getFocusedInputSelectedText: () => getFocusedInputSelectedText,
53
- getFocusedInputValue: () => getFocusedInputValue,
51
+ getFocusedValue: () => getFocusedValue,
54
52
  getFrontmostApp: () => getFrontmostApp,
55
53
  getFrontmostFromRunning: () => getFrontmostFromRunning,
54
+ getFrontmostInfo: () => getFrontmostInfo,
56
55
  getGlobalKeyboardListener: () => getGlobalKeyboardListener,
56
+ getPageContext: () => getPageContext,
57
57
  getRecentDocuments: () => getRecentDocuments,
58
58
  getRecentFiles: () => getRecentFiles,
59
59
  getRunningApps: () => getRunningApps,
60
60
  getSelectedTextSmart: () => getSelectedTextSmart,
61
61
  getSystemContext: () => getSystemContext,
62
62
  isAppRunning: () => isAppRunning,
63
+ isEditable: () => isEditable,
63
64
  isOsascriptAvailable: () => isOsascriptAvailable,
64
65
  powershell: () => powershell_exports,
65
66
  readFileContent: () => readFileContent,
66
67
  readMultipleFiles: () => readMultipleFiles,
67
- setBlockSystemHotkeys: () => setBlockSystemHotkeys
68
+ setBlockSystemHotkeys: () => setBlockSystemHotkeys,
69
+ setBlockedShortcuts: () => setBlockedShortcuts
68
70
  });
69
71
  module.exports = __toCommonJS(index_exports);
70
72
  var path = __toESM(require("path"));
@@ -2288,6 +2290,14 @@ async function getSystemContext2(options) {
2288
2290
 
2289
2291
  // src/index.ts
2290
2292
  var import_meta = {};
2293
+ function tryParseJSON(json) {
2294
+ if (!json) return null;
2295
+ try {
2296
+ return JSON.parse(json);
2297
+ } catch {
2298
+ return null;
2299
+ }
2300
+ }
2291
2301
  var IS_MACOS2 = process.platform === "darwin";
2292
2302
  var IS_WINDOWS2 = process.platform === "win32";
2293
2303
  var PLATFORM_PACKAGES = {
@@ -2325,8 +2335,7 @@ function getNativeAddon() {
2325
2335
  try {
2326
2336
  const candidate = localRequire(packageName);
2327
2337
  const hasCoreFunctions = candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function";
2328
- const hasMacOSFunctions = IS_MACOS2 ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
2329
- if (hasCoreFunctions && hasMacOSFunctions) {
2338
+ if (hasCoreFunctions) {
2330
2339
  nativeAddon = candidate;
2331
2340
  return nativeAddon;
2332
2341
  }
@@ -2488,48 +2497,50 @@ function ensureAccessibilityPermission(addon) {
2488
2497
  openMacAccessibilitySettings();
2489
2498
  return false;
2490
2499
  }
2491
- function getFocusedInputValue() {
2492
- if (!IS_MACOS2) {
2493
- return null;
2494
- }
2500
+ function isEditable() {
2501
+ if (!IS_MACOS2 && !IS_WINDOWS2) return false;
2495
2502
  const addon = getNativeAddon();
2496
- if (!ensureAccessibilityPermission(addon)) {
2497
- return null;
2498
- }
2503
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return false;
2499
2504
  try {
2500
- return addon.getFocusedInputValue();
2505
+ return addon.isEditable?.() ?? false;
2501
2506
  } catch {
2502
- return null;
2507
+ return false;
2503
2508
  }
2504
2509
  }
2505
- function getFocusedInputSelectedText() {
2506
- if (!IS_MACOS2) {
2507
- return null;
2508
- }
2510
+ function getFocusedValue() {
2511
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2509
2512
  const addon = getNativeAddon();
2510
- if (!ensureAccessibilityPermission(addon)) {
2513
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2514
+ try {
2515
+ return addon.getFocusedValue?.() ?? null;
2516
+ } catch {
2511
2517
  return null;
2512
2518
  }
2519
+ }
2520
+ function getFrontmostInfo() {
2521
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2522
+ const addon = getNativeAddon();
2523
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2513
2524
  try {
2514
- return addon.getFocusedInputSelectedText();
2525
+ return tryParseJSON(addon.getFrontmostInfoJSON?.() ?? null);
2515
2526
  } catch {
2516
2527
  return null;
2517
2528
  }
2518
2529
  }
2519
- function getContextJSON() {
2520
- if (!IS_MACOS2) return null;
2530
+ function getPageContext() {
2531
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2521
2532
  const addon = getNativeAddon();
2522
- if (!ensureAccessibilityPermission(addon)) return null;
2533
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2523
2534
  try {
2524
- return addon.getContextJSON?.() ?? null;
2535
+ return tryParseJSON(addon.getPageContextJSON?.() ?? null);
2525
2536
  } catch {
2526
2537
  return null;
2527
2538
  }
2528
2539
  }
2529
2540
  function getSelectedTextSmart() {
2530
- if (!IS_MACOS2) return null;
2541
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2531
2542
  const addon = getNativeAddon();
2532
- if (!ensureAccessibilityPermission(addon)) return null;
2543
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2533
2544
  try {
2534
2545
  return addon.getSelectedTextSmart?.() ?? null;
2535
2546
  } catch {
@@ -2546,6 +2557,16 @@ function setBlockSystemHotkeys(block) {
2546
2557
  } catch {
2547
2558
  }
2548
2559
  }
2560
+ function setBlockedShortcuts(shortcuts) {
2561
+ if (!IS_MACOS2) {
2562
+ return;
2563
+ }
2564
+ try {
2565
+ const addon = getNativeAddon();
2566
+ addon.setBlockedShortcuts?.(shortcuts);
2567
+ } catch {
2568
+ }
2569
+ }
2549
2570
  // Annotate the CommonJS export names for ESM import in node:
2550
2571
  0 && (module.exports = {
2551
2572
  checkKeyboardPermission,
@@ -2558,7 +2579,6 @@ function setBlockSystemHotkeys(block) {
2558
2579
  getAgentContext,
2559
2580
  getClipboardContent,
2560
2581
  getClipboardText,
2561
- getContextJSON,
2562
2582
  getDesktopItems,
2563
2583
  getDesktopPath,
2564
2584
  getFileMetadata,
@@ -2567,20 +2587,23 @@ function setBlockSystemHotkeys(block) {
2567
2587
  getFinderCurrentFolder,
2568
2588
  getFinderSelection,
2569
2589
  getFinderWindows,
2570
- getFocusedInputSelectedText,
2571
- getFocusedInputValue,
2590
+ getFocusedValue,
2572
2591
  getFrontmostApp,
2573
2592
  getFrontmostFromRunning,
2593
+ getFrontmostInfo,
2574
2594
  getGlobalKeyboardListener,
2595
+ getPageContext,
2575
2596
  getRecentDocuments,
2576
2597
  getRecentFiles,
2577
2598
  getRunningApps,
2578
2599
  getSelectedTextSmart,
2579
2600
  getSystemContext,
2580
2601
  isAppRunning,
2602
+ isEditable,
2581
2603
  isOsascriptAvailable,
2582
2604
  powershell,
2583
2605
  readFileContent,
2584
2606
  readMultipleFiles,
2585
- setBlockSystemHotkeys
2607
+ setBlockSystemHotkeys,
2608
+ setBlockedShortcuts
2586
2609
  });
package/dist/index.mjs CHANGED
@@ -2231,6 +2231,14 @@ async function getSystemContext2(options) {
2231
2231
  }
2232
2232
 
2233
2233
  // src/index.ts
2234
+ function tryParseJSON(json) {
2235
+ if (!json) return null;
2236
+ try {
2237
+ return JSON.parse(json);
2238
+ } catch {
2239
+ return null;
2240
+ }
2241
+ }
2234
2242
  var IS_MACOS2 = process.platform === "darwin";
2235
2243
  var IS_WINDOWS2 = process.platform === "win32";
2236
2244
  var PLATFORM_PACKAGES = {
@@ -2268,8 +2276,7 @@ function getNativeAddon() {
2268
2276
  try {
2269
2277
  const candidate = localRequire(packageName);
2270
2278
  const hasCoreFunctions = candidate && typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.isRunning === "function" && typeof candidate.checkPermission === "function";
2271
- const hasMacOSFunctions = IS_MACOS2 ? typeof candidate.getFocusedInputValue === "function" && typeof candidate.getFocusedInputSelectedText === "function" : true;
2272
- if (hasCoreFunctions && hasMacOSFunctions) {
2279
+ if (hasCoreFunctions) {
2273
2280
  nativeAddon = candidate;
2274
2281
  return nativeAddon;
2275
2282
  }
@@ -2431,48 +2438,50 @@ function ensureAccessibilityPermission(addon) {
2431
2438
  openMacAccessibilitySettings();
2432
2439
  return false;
2433
2440
  }
2434
- function getFocusedInputValue() {
2435
- if (!IS_MACOS2) {
2436
- return null;
2437
- }
2441
+ function isEditable() {
2442
+ if (!IS_MACOS2 && !IS_WINDOWS2) return false;
2438
2443
  const addon = getNativeAddon();
2439
- if (!ensureAccessibilityPermission(addon)) {
2440
- return null;
2441
- }
2444
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return false;
2442
2445
  try {
2443
- return addon.getFocusedInputValue();
2446
+ return addon.isEditable?.() ?? false;
2444
2447
  } catch {
2445
- return null;
2448
+ return false;
2446
2449
  }
2447
2450
  }
2448
- function getFocusedInputSelectedText() {
2449
- if (!IS_MACOS2) {
2450
- return null;
2451
- }
2451
+ function getFocusedValue() {
2452
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2452
2453
  const addon = getNativeAddon();
2453
- if (!ensureAccessibilityPermission(addon)) {
2454
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2455
+ try {
2456
+ return addon.getFocusedValue?.() ?? null;
2457
+ } catch {
2454
2458
  return null;
2455
2459
  }
2460
+ }
2461
+ function getFrontmostInfo() {
2462
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2463
+ const addon = getNativeAddon();
2464
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2456
2465
  try {
2457
- return addon.getFocusedInputSelectedText();
2466
+ return tryParseJSON(addon.getFrontmostInfoJSON?.() ?? null);
2458
2467
  } catch {
2459
2468
  return null;
2460
2469
  }
2461
2470
  }
2462
- function getContextJSON() {
2463
- if (!IS_MACOS2) return null;
2471
+ function getPageContext() {
2472
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2464
2473
  const addon = getNativeAddon();
2465
- if (!ensureAccessibilityPermission(addon)) return null;
2474
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2466
2475
  try {
2467
- return addon.getContextJSON?.() ?? null;
2476
+ return tryParseJSON(addon.getPageContextJSON?.() ?? null);
2468
2477
  } catch {
2469
2478
  return null;
2470
2479
  }
2471
2480
  }
2472
2481
  function getSelectedTextSmart() {
2473
- if (!IS_MACOS2) return null;
2482
+ if (!IS_MACOS2 && !IS_WINDOWS2) return null;
2474
2483
  const addon = getNativeAddon();
2475
- if (!ensureAccessibilityPermission(addon)) return null;
2484
+ if (IS_MACOS2 && !ensureAccessibilityPermission(addon)) return null;
2476
2485
  try {
2477
2486
  return addon.getSelectedTextSmart?.() ?? null;
2478
2487
  } catch {
@@ -2489,6 +2498,16 @@ function setBlockSystemHotkeys(block) {
2489
2498
  } catch {
2490
2499
  }
2491
2500
  }
2501
+ function setBlockedShortcuts(shortcuts) {
2502
+ if (!IS_MACOS2) {
2503
+ return;
2504
+ }
2505
+ try {
2506
+ const addon = getNativeAddon();
2507
+ addon.setBlockedShortcuts?.(shortcuts);
2508
+ } catch {
2509
+ }
2510
+ }
2492
2511
  export {
2493
2512
  checkKeyboardPermission,
2494
2513
  createGlobalKeyboardListener,
@@ -2500,7 +2519,6 @@ export {
2500
2519
  getAgentContext,
2501
2520
  getClipboardContent,
2502
2521
  getClipboardText,
2503
- getContextJSON,
2504
2522
  getDesktopItems,
2505
2523
  getDesktopPath,
2506
2524
  getFileMetadata,
@@ -2509,20 +2527,23 @@ export {
2509
2527
  getFinderCurrentFolder,
2510
2528
  getFinderSelection,
2511
2529
  getFinderWindows,
2512
- getFocusedInputSelectedText,
2513
- getFocusedInputValue,
2530
+ getFocusedValue,
2514
2531
  getFrontmostApp,
2515
2532
  getFrontmostFromRunning,
2533
+ getFrontmostInfo,
2516
2534
  getGlobalKeyboardListener,
2535
+ getPageContext,
2517
2536
  getRecentDocuments,
2518
2537
  getRecentFiles,
2519
2538
  getRunningApps,
2520
2539
  getSelectedTextSmart,
2521
2540
  getSystemContext,
2522
2541
  isAppRunning,
2542
+ isEditable,
2523
2543
  isOsascriptAvailable,
2524
2544
  powershell_exports as powershell,
2525
2545
  readFileContent,
2526
2546
  readMultipleFiles,
2527
- setBlockSystemHotkeys
2547
+ setBlockSystemHotkeys,
2548
+ setBlockedShortcuts
2528
2549
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simen-keyboard-listener",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "description": "Native global keyboard listener for macOS and Windows",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -16,7 +16,7 @@
16
16
  "dist"
17
17
  ],
18
18
  "scripts": {
19
- "build:swift": "cd src/native && swiftc -O -parse-as-library -c ContextHelper.swift -o ContextHelper.o",
19
+ "build:swift": "cd src/native && MACOSX_DEPLOYMENT_TARGET=11.0 swiftc -O -parse-as-library -c ContextHelper.swift -o ContextHelper.o",
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",
@@ -49,8 +49,8 @@
49
49
  "node-addon-api": "^8.0.0"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@simen-keyboard-listener/darwin-arm64": "1.1.17",
53
- "@simen-keyboard-listener/win32-x64": "1.1.17"
52
+ "@simen-keyboard-listener/darwin-arm64": "1.1.19",
53
+ "@simen-keyboard-listener/win32-x64": "1.1.19"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/node": "^20.0.0",