### Running TypeScript Examples Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Provides commands for installing dependencies, running, and compiling TypeScript examples using npm scripts. ```bash # Install TypeScript dependencies npm install # Run TypeScript example npm run typescript-example # Compile TypeScript example npm run typescript-compile ``` -------------------------------- ### Electron Main Process Event Forwarding Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Example for the Electron main process demonstrating how to set up iohook, start monitoring, and forward keyboard events to the webContents. ```javascript // Main process (main.js) const { app, BrowserWindow, ipcMain } = require('electron') const iohook = require('iohook-macos') function createWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false } }) // Set up event forwarding iohook.on('keyDown', (data) => { mainWindow.webContents.send('keyDown', data) }) iohook.startMonitoring() } app.whenReady().then(createWindow) ``` -------------------------------- ### Electron Main Process Setup Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Set up the Electron main process to integrate iohook-macos, forward events to the renderer, and start monitoring after window readiness. ```javascript const { app, BrowserWindow, ipcMain } = require('electron') const iohook = require('iohook-macos') function createWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false } }) // Forward events to renderer process iohook.on('keyDown', (data) => { mainWindow.webContents.send('globalKeyDown', data) }) iohook.on('leftMouseDown', (data) => { mainWindow.webContents.send('globalMouseClick', data) }) // Start monitoring after window is ready mainWindow.once('ready-to-show', () => { const permissions = iohook.checkAccessibilityPermissions() if (permissions.hasPermissions) { iohook.startMonitoring() } else { console.log('Please grant accessibility permissions') } }) return mainWindow } app.whenReady().then(createWindow) // Handle app cleanup app.on('window-all-closed', () => { iohook.stopMonitoring() if (process.platform !== 'darwin') { app.quit() } }) ``` -------------------------------- ### Basic Setup and Permissions Check Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Initializes the iohook-macos library, checks for necessary accessibility permissions, requests them if missing, and starts event monitoring. ```javascript const iohook = require('iohook-macos') // Check accessibility permissions first const permissions = iohook.checkAccessibilityPermissions() if (!permissions.hasPermissions) { console.log('Accessibility permissions required') iohook.requestAccessibilityPermissions() process.exit(1) } // Start monitoring iohook.startMonitoring() ``` -------------------------------- ### Basic Setup and Permissions Check (ESM) Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Initializes iohook-macos, checks for necessary accessibility permissions, requests them if missing, and starts event monitoring. Ensure permissions are granted before proceeding. ```javascript import iohook from 'iohook-macos' // Check accessibility permissions first const permissions = iohook.checkAccessibilityPermissions() if (!permissions.hasPermissions) { console.log('Accessibility permissions required') iohook.requestAccessibilityPermissions() process.exit(1) } // Start monitoring iohook.startMonitoring() ``` -------------------------------- ### Install and Setup iohook-macos with Type Safety Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.typescript.en.prompt.md Import necessary types and functions from 'iohook-macos'. Check for and request accessibility permissions if not granted. Start monitoring system events with type safety. ```typescript import * as iohook from 'iohook-macos' import type { EventData, AccessibilityPermissionsResult, EventFilterOptions, CGEventTypeString, CGEventTypeNumber } from 'iohook-macos' // Type-safe permission checking const permissions: AccessibilityPermissionsResult = iohook.checkAccessibilityPermissions() if (!permissions.hasPermissions) { console.log('Accessibility permissions required:', permissions.message) iohook.requestAccessibilityPermissions() process.exit(1) } // Start monitoring with type safety iohook.startMonitoring() ``` -------------------------------- ### Start Monitoring System Events Source: https://context7.com/hwanyong/iohook-macos/llms.txt Initiate system event monitoring by starting the native CGEventTap and polling the event queue. Registered listeners will then receive live system events. This call is a no-op if monitoring is already active. ```javascript const iohook = require('iohook-macos') const { hasPermissions } = iohook.checkAccessibilityPermissions() if (!hasPermissions) process.exit(1) iohook.on('keyDown', (event) => { console.log('Key down – keyCode:', event.keyCode, '| modifiers:', event.modifiers) // Output: Key down – keyCode: 0 | modifiers: { shift: false, control: false, option: false, command: true, capsLock: false, fn: false } }) iohook.on('leftMouseDown', (event) => { console.log(`Left click at (${event.x}, ${event.y}), pid: ${event.processId}`) // Output: Left click at (854, 612), pid: 1234 }) iohook.startMonitoring() console.log('Monitoring:', iohook.isMonitoring()) // true ``` -------------------------------- ### Robust Monitoring Setup with Error Handling Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Sets up event monitoring with error handling, including checking for accessibility permissions before starting. Includes a graceful shutdown mechanism for SIGINT signals. ```javascript // Robust monitoring setup function startMonitoringWithErrorHandling() { try { // Check permissions first const permissions = iohook.checkAccessibilityPermissions() if (!permissions.hasPermissions) { throw new Error('Accessibility permissions not granted') } // Start monitoring iohook.startMonitoring() console.log('Event monitoring started successfully') } catch (error) { console.error('Failed to start monitoring:', error.message) if (error.message.includes('permission')) { console.log('Please grant accessibility permissions in System Preferences') } return false } return true } // Graceful shutdown process.on('SIGINT', () => { console.log('Shutting down...') if (iohook.isMonitoring()) { iohook.stopMonitoring() } process.exit(0) }) ``` -------------------------------- ### Quick Start: JavaScript Event Hooking Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md This JavaScript snippet demonstrates how to check for and request accessibility permissions, set up event listeners for keyboard and mouse events, and start monitoring system events using iohook-macos. ```javascript const iohook = require('iohook-macos') // Check accessibility permissions const permissions = iohook.checkAccessibilityPermissions() if (!permissions.hasPermissions) { console.log('Please grant accessibility permissions') iohook.requestAccessibilityPermissions() process.exit(1) } // Set up event listeners iohook.on('keyDown', (event) => { console.log('Key pressed:', event.keyCode) }) iohook.on('leftMouseDown', (event) => { console.log('Mouse clicked at:', event.x, event.y) }) // Start monitoring iohook.startMonitoring() ``` -------------------------------- ### Install iohook-macos Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Install the iohook-macos library using npm. Ensure you have Node.js 14+ and macOS 10.15+. ```bash npm install iohook-macos ``` -------------------------------- ### Type-Safe Main Process Setup Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.typescript.en.prompt.md Sets up the main Electron process with type-safe event forwarding from iohook to the renderer process. Requires Electron and iohook-macos. ```typescript import { app, BrowserWindow, ipcMain, IpcMainEvent } from 'electron' import * as iohook from 'iohook-macos' import type { EventData } from 'iohook-macos' interface ElectronWindow extends BrowserWindow { sendEventToRenderer(eventName: string, data: EventData): void } function createWindow(): ElectronWindow { const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false } }) as ElectronWindow // Add type-safe method mainWindow.sendEventToRenderer = (eventName: string, data: EventData) => { mainWindow.webContents.send(eventName, data) } // Type-safe event forwarding iohook.on('keyDown', (data: EventData) => { mainWindow.sendEventToRenderer('globalKeyDown', data) }) iohook.on('leftMouseDown', (data: EventData) => { mainWindow.sendEventToRenderer('globalMouseClick', data) }) return mainWindow } // Type-safe IPC handlers pcMain.handle('checkPermissions', (): AccessibilityPermissionsResult => { return iohook.checkAccessibilityPermissions() }) pcMain.handle('startMonitoring', (): boolean => { try { iohook.startMonitoring() return true } catch (error) { console.error('Failed to start monitoring:', error) return false } }) ``` -------------------------------- ### Build Native Module from Source Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Commands for installing dependencies, rebuilding the native module, and specifically rebuilding for Electron when developing or building from source. ```bash # Install dependencies npm install # Rebuild native module npm run rebuild # For Electron npm run electron-rebuild ``` -------------------------------- ### startMonitoring() Source: https://context7.com/hwanyong/iohook-macos/llms.txt Starts the native CGEventTap and begins polling the internal event queue at the configured polling rate. After this call, all registered on() listeners will receive live system events. Calling startMonitoring() while already monitoring is a no-op. ```APIDOC ## startMonitoring() ### Description Starts the native CGEventTap and begins polling the internal event queue at the configured polling rate. After this call, all registered `on()` listeners will receive live system events. Calling `startMonitoring()` while already monitoring is a no-op. ### Example ```javascript const iohook = require('iohook-macos') const { hasPermissions } = iohook.checkAccessibilityPermissions() if (!hasPermissions) process.exit(1) iohook.on('keyDown', (event) => { console.log('Key down – keyCode:', event.keyCode, '| modifiers:', event.modifiers) // Output: Key down – keyCode: 0 | modifiers: { shift: false, control: false, option: false, command: true, capsLock: false, fn: false } }) iohook.on('leftMouseDown', (event) => { console.log(`Left click at (${event.x}, ${event.y}), pid: ${event.processId}`) // Output: Left click at (854, 612), pid: 1234 }) iohook.startMonitoring() console.log('Monitoring:', iohook.isMonitoring()) // true ``` ``` -------------------------------- ### TypeScript Usage Examples Source: https://context7.com/hwanyong/iohook-macos/llms.txt Demonstrates type-safe usage of iohook-macos with TypeScript, including permission checks, event filtering, and event listeners. ```APIDOC ## TypeScript Usage The package ships `index.d.ts` with full type declarations. Import the singleton with a default import and named type imports. ### Type-safe permission guard ```typescript import iohook from 'iohook-macos' import type { EventData, AccessibilityPermissionsResult, EventFilterOptions, EventNames, CGEventTypeNumber } from 'iohook-macos' // Type-safe permission guard const perm: AccessibilityPermissionsResult = iohook.checkAccessibilityPermissions() if (!perm.hasPermissions) { iohook.requestAccessibilityPermissions() process.exit(1) } ``` ### Type-safe configuration ```typescript // Type-safe configuration const filterOptions: EventFilterOptions = { filterByEventType: true, allowKeyboard: true, allowMouse: true, allowScroll: false, filterByCoordinates: true, minX: 0, maxX: 1920, minY: 0, maxY: 1080 } iohook.setEventFilter(filterOptions) iohook.setPollingRate(16) iohook.enablePerformanceMode() iohook.setMouseMoveThrottling(16) ``` ### String-typed event listeners ```typescript // String-typed event listeners iohook.on('keyDown', (data: EventData) => { console.log('Key down:', data.keyCode, '| cmd:', data.modifiers.command) }) ``` ### Integer-typed event listeners (CGEventType) ```typescript // Integer-typed event listeners (CGEventType) iohook.on(1 as CGEventTypeNumber, (data: EventData) => { console.log(`LMB at (${data.x}, ${data.y})`) }) ``` ### Access bidirectional type mappings ```typescript // Access bidirectional type mappings const typeName: string = iohook.CGEventTypes[10] // "keyDown" const typeCode: number = iohook.EventTypeToInt.scrollWheel // 22 ``` ### Periodic queue health check ```typescript iohook.startMonitoring() // Periodic queue health check setInterval(() => { const size: number = iohook.getQueueSize() if (size > 200) iohook.clearQueue() }, 2000) process.on('SIGINT', () => { iohook.stopMonitoring() process.exit(0) }) ``` ``` -------------------------------- ### Electron Main Process with ESM Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Sets up the main Electron process using ESM, imports iohook, and forwards keyboard events to the renderer process. It starts monitoring for events once the window is ready and checks for accessibility permissions. ```javascript // main.mjs import { app, BrowserWindow } from 'electron' import iohook from 'iohook-macos' const createWindow = () => { const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false } }) // Forward events to renderer iohook.on('keyDown', (data) => { mainWindow.webContents.send('globalKeyDown', data) }) // Start monitoring when ready mainWindow.once('ready-to-show', () => { const permissions = iohook.checkAccessibilityPermissions() if (permissions.hasPermissions) { iohook.startMonitoring() } }) } app.whenReady().then(createWindow) // Cleanup app.on('window-all-closed', () => { iohook.stopMonitoring() if (process.platform !== 'darwin') app.quit() }) ``` -------------------------------- ### Run Comprehensive Tests Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Commands to run different test suites for the iohook-macos project, including basic, comprehensive, Electron, and TypeScript examples. ```bash # Run basic test npm test # Run comprehensive test npm run test-comprehensive # Run Electron example npm run electron-test # Run TypeScript example npm run typescript-example ``` -------------------------------- ### Event Data Structure Example Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Illustrates the common properties found in event objects, including type, coordinates, timestamp, and process ID. ```javascript // Event object properties const eventData = { type: 10, // CGEventType number x: 123.45, // X coordinate (mouse events) y: 678.90, // Y coordinate (mouse events) timestamp: 1678886400000, // Event timestamp processId: 12345, // Source process ID keyCode: 36, // Key code (keyboard events) hasKeyCode: true // Whether keyCode is available } ``` -------------------------------- ### TypeScript Event Type Examples Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Illustrates how to register event listeners using both string-based (recommended) and number-based (CGEventType integers) event types in TypeScript. ```typescript // String-based (recommended for readability) iohook.on('keyDown', handler) iohook.on('leftMouseDown', handler) iohook.on('scrollWheel', handler) // Number-based (CGEventType integers) iohook.on(10, handler) // kCGEventKeyDown iohook.on(1, handler) // kCGEventLeftMouseDown iohook.on(22, handler) // kCGEventScrollWheel ``` -------------------------------- ### Ensure Accessibility Permissions Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Check and request accessibility permissions before starting monitoring. This function opens System Preferences if permissions are not granted. ```javascript // Check and request permissions function ensurePermissions() { const result = iohook.checkAccessibilityPermissions() if (!result.hasPermissions) { console.log('Status:', result.message) // Request accessibility permissions // This opens System Preferences > Privacy & Security > Accessibility const requestResult = iohook.requestAccessibilityPermissions() console.log('Request result:', requestResult.message) // Returns: { hasPermissions: false, message: "Opening System Preferences..." } console.log('Please grant accessibility permissions and restart the app') return false } return true } // Use before starting monitoring if (ensurePermissions()) { iohook.startMonitoring() } ``` -------------------------------- ### Check Platform and Permissions Support Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Checks if the current platform is macOS and if iohook-macos can be loaded, verifying accessibility permissions. If checks pass, it starts monitoring events. This pattern is useful for feature detection before initializing. ```javascript // feature-detection.mjs export const checkPlatformSupport = async () => { if (process.platform !== 'darwin') { throw new Error('iohook-macos only supports macOS') } try { const { default: iohook } = await import('iohook-macos') return iohook.checkAccessibilityPermissions() } catch (error) { throw new Error('Failed to load iohook-macos: ' + error.message) } } ``` ```javascript // main.mjs import { checkPlatformSupport } from './feature-detection.mjs' try { const permissions = await checkPlatformSupport() if (permissions.hasPermissions) { const { default: iohook } = await import('iohook-macos') iohook.startMonitoring() } } catch (error) { console.error('Platform check failed:', error.message) } ``` -------------------------------- ### Initialize Event Hook with Dynamic Import Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Demonstrates conditional loading of the iohook-macos module using dynamic import. It checks for accessibility permissions and starts monitoring if granted, otherwise logs an error. Requires Node.js 14+ for top-level await. ```javascript // main.mjs const initializeEventHook = async () => { try { // Dynamic import for conditional loading const { default: iohook } = await import('iohook-macos') const permissions = iohook.checkAccessibilityPermissions() if (permissions.hasPermissions) { iohook.startMonitoring() return iohook } else { throw new Error('Permissions required') } } catch (error) { console.error('Failed to initialize:', error.message) return null } } // Use top-level await (Node.js 14+) const iohook = await initializeEventHook() if (iohook) { console.log('Event monitoring started') } ``` -------------------------------- ### Subscribe to Keyboard and Mouse Events Source: https://context7.com/hwanyong/iohook-macos/llms.txt Register listeners for various keyboard and mouse events using string names or CGEventType integers. All events also trigger the generic 'event' channel. Ensure iohook is imported and monitoring is started. ```javascript const iohook = require('iohook-macos') // String-based (recommended for readability) iohook.on('keyDown', (e) => console.log('keyDown keyCode:', e.keyCode)) iohook.on('keyUp', (e) => console.log('keyUp keyCode:', e.keyCode)) iohook.on('leftMouseDown', (e) => console.log('LMB down at', e.x, e.y)) iohook.on('leftMouseUp', (e) => console.log('LMB up at', e.x, e.y)) iohook.on('rightMouseDown', (e) => console.log('RMB down at', e.x, e.y)) iohook.on('mouseMoved', (e) => console.log('moved to', e.x, e.y)) iohook.on('scrollWheel', (e) => console.log('scroll at', e.x, e.y)) iohook.on('flagsChanged', (e) => console.log('flags 0x' + e.flags.toString(16))) ``` ```javascript // CGEventType integer-based (same underlying event, dual-fired) iohook.on(1, (e) => console.log('[int] leftMouseDown:', e.x, e.y)) // kCGEventLeftMouseDown iohook.on(10, (e) => console.log('[int] keyDown:', e.keyCode)) // kCGEventKeyDown iohook.on(22, (e) => console.log('[int] scrollWheel')) // kCGEventScrollWheel ``` ```javascript // Generic catch-all channel iohook.on('event', (e) => { const name = iohook.CGEventTypes[e.type] || 'unknown' console.log(`[event] type=${e.type} (${name}) ts=${e.timestamp.toFixed(3)}`) }) ``` ```javascript iohook.startMonitoring() ``` -------------------------------- ### Package.json Configuration for ESM Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Configures the package.json file to enable module type as 'module' and sets up scripts for starting and developing the Electron application with ESM. ```json { "type": "module", "main": "main.mjs", "scripts": { "start": "electron main.mjs", "dev": "electron main.mjs --enable-logging" } } ``` -------------------------------- ### TypeScript Event Handling and Permissions Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Demonstrates type-safe checking of accessibility permissions and handling of keyboard and mouse events using iohook-macos. Includes examples for both string and number-based event types. ```typescript import * as iohook from 'iohook-macos' import type { EventData, AccessibilityPermissionsResult } from 'iohook-macos' // Type-safe permission checking const permissions: AccessibilityPermissionsResult = iohook.checkAccessibilityPermissions() // Type-safe event handling iohook.on('keyDown', (event: EventData) => { console.log('Key pressed:', event.keyCode) console.log('Event type:', event.type) // CGEventType number }) // Number-based event listeners (CGEventType) iohook.on(1, (event: EventData) => { // kCGEventLeftMouseDown console.log('Left mouse down at:', event.x, event.y) }) // Start monitoring with full type safety iohook.startMonitoring() ``` -------------------------------- ### isMonitoring() Source: https://context7.com/hwanyong/iohook-macos/llms.txt Returns a boolean indicating whether the monitoring session is currently active. Useful for guard clauses before starting or stopping. ```APIDOC ## isMonitoring() ### Description Returns a boolean indicating whether the monitoring session is currently active. Useful for guard clauses before starting or stopping. ### Returns - `boolean` - `true` if monitoring is active, `false` otherwise. ### Example ```javascript const iohook = require('iohook-macos') console.log(iohook.isMonitoring()) // false – not yet started iohook.startMonitoring() console.log(iohook.isMonitoring()) // true iohook.stopMonitoring() console.log(iohook.isMonitoring()) // false ``` ``` -------------------------------- ### Initialize IPC and Statistics Source: https://github.com/hwanyong/iohook-macos/blob/main/examples/electron/electron-test.html Sets up the `ipcRenderer` for communication with the main process and initializes a statistics object to track event counts and uptime. This code should be run in the renderer process. ```javascript const { ipcRenderer } = require('electron'); let stats = { total: 0, keyboard: 0, mouse: 0, scroll: 0, queueMax: 0, startTime: null }; let verboseLogging = true; ``` -------------------------------- ### Event Monitoring Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Set up listeners for various system events like key presses, mouse movements, and generic events. Also includes details on handling modifier keys and event filtering. ```APIDOC ## Event Monitoring ### Basic Event Handling ```javascript // Listen for specific events iohook.on('keyDown', (event) => { console.log(`Key ${event.keyCode} pressed`) }) iohook.on('mouseMoved', (event) => { console.log(`Mouse at (${event.x}, ${event.y})`) }) // Generic event listener iohook.on('event', (event) => { console.log(`Event type: ${event.type}`) }) ``` ### Modifier Keys All events include a `modifiers` object with parsed modifier key states. ```javascript // Easy access to modifier key states iohook.on('keyDown', (event) => { if (event.modifiers.shift && event.modifiers.command) { console.log('Shift + Command pressed') } if (event.modifiers.option) { console.log('Option key is pressed') } }) // Available modifier keys: // - `shift` // - `control` // - `option` // - `command` // - `capsLock` // - `fn` ``` ### Event Filtering ```javascript // Unified filter interface iohook.setEventFilter({ filterByProcessId: true, targetProcessId: 1234, excludeProcessId: false, filterByCoordinates: true, minX: 0, maxX: 1920, minY: 0, maxY: 1080, filterByEventType: true, allowKeyboard: true, allowMouse: true, allowScroll: false }) // Direct native methods for single filters iohook.setProcessFilter(1234, false) // Include only process 1234 iohook.setCoordinateFilter(0, 0, 1920, 1080) // Screen region iohook.setEventTypeFilter(true, true, false) // Keyboard, mouse, no scroll // Clear all filters iohook.clearFilters() ``` ``` -------------------------------- ### Listen for Keyboard and Mouse Events Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Sets up listeners for specific keyboard ('keyDown') and mouse ('mouseMoved') events, as well as a generic listener for all event types. ```javascript // Listen for specific events iohook.on('keyDown', (event) => { console.log(`Key ${event.keyCode} pressed`) }) iohook.on('mouseMoved', (event) => { console.log(`Mouse at (${event.x}, ${event.y})`) }) // Generic event listener iohook.on('event', (event) => { console.log(`Event type: ${event.type}`) }) ``` -------------------------------- ### Implement Global Shortcuts Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.commonjs.en.prompt.md Detect key combinations like Cmd+Shift+Space by tracking individual key down and up events and managing state variables. ```javascript // Implement Cmd+Shift+Space shortcut let cmdPressed = false let shiftPressed = false iohook.on('keyDown', (event) => { if (event.keyCode === 55) cmdPressed = true // Cmd key if (event.keyCode === 56) shiftPressed = true // Shift key if (event.keyCode === 49) { // Space key if (cmdPressed && shiftPressed) { console.log('Global shortcut triggered!') // Execute your action here } } }) iohook.on('keyUp', (event) => { if (event.keyCode === 55) cmdPressed = false if (event.keyCode === 56) shiftPressed = false }) ``` -------------------------------- ### Check if Monitoring is Active Source: https://context7.com/hwanyong/iohook-macos/llms.txt Determine if the system event monitoring session is currently active. This boolean return value is useful for conditional logic before starting or stopping monitoring. ```javascript const iohook = require('iohook-macos') console.log(iohook.isMonitoring()) // false – not yet started iohook.startMonitoring() console.log(iohook.isMonitoring()) // true iohook.stopMonitoring() console.log(iohook.isMonitoring()) // false ``` -------------------------------- ### Event Subscription with `on()` Source: https://context7.com/hwanyong/iohook-macos/llms.txt Registers a listener for a specific event type. Supports both string names (e.g., 'keyDown') and raw CGEventType integers. All events also fire the generic 'event' channel. Each listener receives a single EventData object. ```APIDOC ## `on(eventName, listener)` — Event Subscription Registers a listener for a specific event type. Accepts both string names (`'keyDown'`, `'leftMouseDown'`, etc.) and raw CGEventType integers (`10`, `1`, etc.). All events also fire the generic `'event'` channel. Each listener receives a single `EventData` object. ### Parameters #### Path Parameters - **eventName** (string | number) - Required - The name or integer code of the event to listen for. - **listener** (function) - Required - The callback function to execute when the event occurs. ### Request Example ```javascript const iohook = require('iohook-macos') // String-based (recommended for readability) iohook.on('keyDown', (e) => console.log('keyDown keyCode:', e.keyCode)) iohook.on('keyUp', (e) => console.log('keyUp keyCode:', e.keyCode)) iohook.on('leftMouseDown', (e) => console.log('LMB down at', e.x, e.y)) iohook.on('leftMouseUp', (e) => console.log('LMB up at', e.x, e.y)) iohook.on('rightMouseDown', (e) => console.log('RMB down at', e.x, e.y)) iohook.on('mouseMoved', (e) => console.log('moved to', e.x, e.y)) iohook.on('scrollWheel', (e) => console.log('scroll at', e.x, e.y)) iohook.on('flagsChanged', (e) => console.log('flags 0x' + e.flags.toString(16))) // CGEventType integer-based (same underlying event, dual-fired) iohook.on(1, (e) => console.log('[int] leftMouseDown:', e.x, e.y)) // kCGEventLeftMouseDown iohook.on(10, (e) => console.log('[int] keyDown:', e.keyCode)) // kCGEventKeyDown iohook.on(22, (e) => console.log('[int] scrollWheel')) // kCGEventScrollWheel // Generic catch-all channel iohook.on('event', (e) => { const name = iohook.CGEventTypes[e.type] || 'unknown' console.log(`[event] type=${e.type} (${name}) ts=${e.timestamp.toFixed(3)}`) }) iohook.startMonitoring() ``` ### Response This method does not return a value. It registers a listener. ``` -------------------------------- ### Performance Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Options to optimize performance and control logging. ```APIDOC ## enablePerformanceMode() ### Description Enables a mode optimized for higher performance, potentially reducing overhead. ### Method `enablePerformanceMode()` ### Returns `void` ``` ```APIDOC ## disablePerformanceMode() ### Description Disables performance optimization mode, reverting to default behavior. ### Method `disablePerformanceMode()` ### Returns `void` ``` ```APIDOC ## setMouseMoveThrottling(ms) ### Description Sets a throttling interval in milliseconds for mouse move events to reduce frequency. ### Method `setMouseMoveThrottling(ms: number)` ### Parameters - **ms** (number) - The throttling interval in milliseconds for mouse move events. ``` ```APIDOC ## setVerboseLogging(enable) ### Description Controls whether detailed verbose logging is enabled or disabled. ### Method `setVerboseLogging(enable: boolean)` ### Parameters - **enable** (boolean) - Set to `true` to enable verbose logging, `false` to disable. ``` -------------------------------- ### Type-Safe Error Management with EventMonitor Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.typescript.en.prompt.md Implement robust error handling for event monitoring using custom error types and a dedicated EventMonitor class. Ensures proper setup, permission checks, and graceful shutdown. ```typescript // Custom error types class PermissionError extends Error { constructor(message: string) { super(message) this.name = 'PermissionError' } } class MonitoringError extends Error { constructor(message: string) { super(message) this.name = 'MonitoringError' } } // Type-safe monitoring setup class EventMonitor { private isActive: boolean = false public async start(): Promise { try { await this.checkPermissions() this.startMonitoring() this.isActive = true console.log('Event monitoring started successfully') } catch (error) { this.handleError(error) } } private async checkPermissions(): Promise { const result: AccessibilityPermissionsResult = iohook.checkAccessibilityPermissions() if (!result.hasPermissions) { throw new PermissionError(`Accessibility permissions not granted: ${result.message}`) } } private startMonitoring(): void { try { iohook.startMonitoring() } catch (error) { throw new MonitoringError('Failed to start system event monitoring') } } private handleError(error: unknown): void { if (error instanceof PermissionError) { console.error('Permission error:', error.message) console.log('Please grant accessibility permissions in System Preferences') } else if (error instanceof MonitoringError) { console.error('Monitoring error:', error.message) } else if (error instanceof Error) { console.error('Unknown error:', error.message) } else { console.error('Unexpected error:', error) } } public stop(): void { if (this.isActive) { iohook.stopMonitoring() this.isActive = false console.log('Event monitoring stopped') } } public get isMonitoring(): boolean { return this.isActive && iohook.isMonitoring() } } // Usage with proper cleanup const monitor = new EventMonitor() process.on('SIGINT', () => { console.log('Shutting down...') monitor.stop() process.exit(0) }) monitor.start() ``` -------------------------------- ### Electron Main-Process Integration with iohook Source: https://context7.com/hwanyong/iohook-macos/llms.txt Integrates iohook into an Electron main process to monitor and forward input events to renderer windows. Ensures accessibility permissions are checked and requested, and configures performance settings. IPC handlers are provided to control monitoring and settings from the renderer. ```javascript const { app, BrowserWindow, ipcMain } = require('electron') const iohook = require('iohook-macos') let mainWindow app.whenReady().then(() => { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false } }) mainWindow.loadFile('index.html') // Permission guard const { hasPermissions } = iohook.checkAccessibilityPermissions() if (!hasPermissions) { iohook.requestAccessibilityPermissions() return } // Optimise for a GUI application iohook.enablePerformanceMode() iohook.setPollingRate(16) iohook.setMouseMoveThrottling(16) // Forward all input events to the renderer iohook.on('keyDown', (data) => mainWindow.webContents.send('iohook-event', data)) iohook.on('leftMouseDown', (data) => mainWindow.webContents.send('iohook-event', data)) iohook.on('mouseMoved', (data) => mainWindow.webContents.send('iohook-event', data)) iohook.on(22, (data) => mainWindow.webContents.send('iohook-event', data)) // scrollWheel iohook.startMonitoring() console.log('iohook monitoring started, queue size:', iohook.getQueueSize()) }) // IPC control surface exposed to the renderer ipcMain.on('set-polling-rate', (_, ms) => iohook.setPollingRate(ms)) ipcMain.on('enable-performance-mode', () => iohook.enablePerformanceMode()) ipcMain.on('disable-performance-mode',() => iohook.disablePerformanceMode()) ipcMain.on('get-queue-size', (event) => event.reply('queue-size', iohook.getQueueSize())) ipcMain.on('clear-queue', () => iohook.clearQueue()) ipcMain.on('stop-monitoring', () => iohook.stopMonitoring()) ipcMain.on('start-monitoring', () => iohook.startMonitoring()) app.on('window-all-closed', () => { iohook.stopMonitoring() if (process.platform !== 'darwin') app.quit() }) ``` -------------------------------- ### Set Event Type Filter (Keyboard Only) Source: https://context7.com/hwanyong/iohook-macos/llms.txt Enables keyboard events while disabling mouse and scroll events at the native level. Only selected event types will reach the JavaScript polling loop. Ensure monitoring is started after setting filters. ```javascript const iohook = require('iohook-macos') // Keyboard-only mode iohook.setEventTypeFilter(true, false, false) iohook.on('keyDown', (e) => console.log('Key:', e.keyCode)) iohook.on('mouseMoved', () => console.log('This will never fire')) iohook.startMonitoring() // Switch to mouse + scroll only (no rebuild needed) setTimeout(() => { iohook.clearFilters() iohook.setEventTypeFilter(false, true, true) }, 15000) ``` -------------------------------- ### requestAccessibilityPermissions() Source: https://context7.com/hwanyong/iohook-macos/llms.txt Opens the macOS System Preferences Security & Privacy → Accessibility panel so the user can manually add the application. Returns a result object with the current permission status after the dialog prompt. Must be called from the main process in Electron. ```APIDOC ## requestAccessibilityPermissions() ### Description Opens the macOS System Preferences Security & Privacy → Accessibility panel so the user can manually add the application. Returns a result object with the current permission status after the dialog prompt. Must be called from the main process in Electron. ### Returns - `{ hasPermissions: boolean, message: string }` - An object containing the current permission status and a message. ### Example ```javascript const iohook = require('iohook-macos') const check = iohook.checkAccessibilityPermissions() if (!check.hasPermissions) { console.log('Requesting permissions – system dialog will open...') const requestResult = iohook.requestAccessibilityPermissions() // { hasPermissions: false, message: "Please add this app in System Preferences > Accessibility" } console.log(requestResult.message) console.log('Re-run the application after granting access.') process.exit(0) } ``` ``` -------------------------------- ### Import Statements for iohook-macos (ESM) Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Demonstrates various ways to import iohook-macos functions and the default export using ESM syntax. Named imports are recommended for clarity. ```javascript import { startMonitoring, stopMonitoring, checkAccessibilityPermissions, setEventFilter, on as addListener } from 'iohook-macos' ``` ```javascript import iohook from 'iohook-macos' ``` ```javascript const { default: iohook } = await import('iohook-macos') ``` -------------------------------- ### TypeScript Usage with iohook-macos Source: https://context7.com/hwanyong/iohook-macos/llms.txt Demonstrates type-safe configuration and event handling in TypeScript. Includes checking and requesting accessibility permissions, setting event filters, and listening to typed events. Ensure the package ships with `index.d.ts` for full type declarations. ```typescript import iohook from 'iohook-macos' import type { EventData, AccessibilityPermissionsResult, EventFilterOptions, EventNames, CGEventTypeNumber } from 'iohook-macos' // Type-safe permission guard const perm: AccessibilityPermissionsResult = iohook.checkAccessibilityPermissions() if (!perm.hasPermissions) { iohook.requestAccessibilityPermissions() process.exit(1) } // Type-safe configuration const filterOptions: EventFilterOptions = { filterByEventType: true, allowKeyboard: true, allowMouse: true, allowScroll: false, filterByCoordinates: true, minX: 0, maxX: 1920, minY: 0, maxY: 1080 } iohook.setEventFilter(filterOptions) iohook.setPollingRate(16) iohook.enablePerformanceMode() iohook.setMouseMoveThrottling(16) // String-typed event listeners iohook.on('keyDown', (data: EventData) => { console.log('Key down:', data.keyCode, '| cmd:', data.modifiers.command) }) // Integer-typed event listeners (CGEventType) iohook.on(1 as CGEventTypeNumber, (data: EventData) => { console.log(`LMB at (${data.x}, ${data.y})`) }) // Access bidirectional type mappings const typeName: string = iohook.CGEventTypes[10] // "keyDown" const typeCode: number = iohook.EventTypeToInt.scrollWheel // 22 iohook.startMonitoring() // Periodic queue health check setInterval(() => { const size: number = iohook.getQueueSize() if (size > 200) iohook.clearQueue() }, 2000) process.on('SIGINT', () => { iohook.stopMonitoring() process.exit(0) }) ``` -------------------------------- ### Type-Safe Performance Configuration Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.typescript.en.prompt.md Set up performance modes and configure polling rates and mouse throttling with type safety. ```APIDOC ## Type-Safe Performance Configuration ### Description Configure performance settings like polling rate, mouse throttling, and enable performance mode using type-safe interfaces. ### Usage ```typescript interface PerformanceConfig { pollingRate: number mouseThrottling: number enablePerformance: boolean } const performanceConfig: PerformanceConfig = { pollingRate: 16, // 60fps mouseThrottling: 16, // 60fps enablePerformance: true } if (performanceConfig.enablePerformance) { iohook.enablePerformanceMode() } iohook.setPollingRate(performanceConfig.pollingRate) iohook.setMouseMoveThrottling(performanceConfig.mouseThrottling) function monitorQueue(): void { setInterval(() => { const queueSize: number = iohook.getQueueSize() if (queueSize > 100) { console.warn('Event queue getting large:', queueSize) } }, 1000) } monitorQueue() ``` ``` -------------------------------- ### Configure Event Filters Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Sets up various filters to control which events are monitored, including filtering by process ID, screen coordinates, and event types. Filters can be cleared using `iohook.clearFilters()`. ```javascript // Unified filter interface (recommended for complex filters) iohook.setEventFilter({ filterByProcessId: true, targetProcessId: 1234, excludeProcessId: false, // Include only this process filterByCoordinates: true, minX: 0, maxX: 1920, minY: 0, maxY: 1080, filterByEventType: true, allowKeyboard: true, allowMouse: true, allowScroll: false }) // Or use direct native methods for single filters iohook.setProcessFilter(1234, false) // Include only process 1234 iohook.setCoordinateFilter(0, 0, 1920, 1080) // Screen region iohook.setEventTypeFilter(true, true, false) // Keyboard, mouse, no scroll // Clear all filters iohook.clearFilters() ``` -------------------------------- ### Modular Global Shortcuts with ESM Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Implements a modular system for managing global keyboard shortcuts using ESM. It listens for key down and key up events to detect modifier keys and specific key combinations. ```javascript // shortcuts.mjs import iohook from 'iohook-macos' class ShortcutManager { constructor() { this.modifiers = { cmd: false, shift: false } this.setupListeners() } setupListeners() { iohook.on('keyDown', this.handleKeyDown.bind(this)) iohook.on('keyUp', this.handleKeyUp.bind(this)) } handleKeyDown(event) { if (event.keyCode === 55) this.modifiers.cmd = true if (event.keyCode === 56) this.modifiers.shift = true if (event.keyCode === 49 && this.modifiers.cmd && this.modifiers.shift) { this.onGlobalShortcut() } } handleKeyUp(event) { if (event.keyCode === 55) this.modifiers.cmd = false if (event.keyCode === 56) this.modifiers.shift = false } onGlobalShortcut() { console.log('Global shortcut triggered!') } } export default ShortcutManager // main.mjs import ShortcutManager from './shortcuts.mjs' const shortcuts = new ShortcutManager() ``` -------------------------------- ### Modular Performance Configuration (ESM) Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Configures iohook-macos for performance by enabling a performance mode, setting a polling rate for 60fps, and throttling mouse move events. Includes a function to monitor the event queue size. ```javascript // performance.mjs import iohook from 'iohook-macos' export const setupPerformanceMode = () => { iohook.enablePerformanceMode() iohook.setPollingRate(16) // 60fps iohook.setMouseMoveThrottling(16) } export const monitorQueue = () => { setInterval(() => { const queueSize = iohook.getQueueSize() if (queueSize > 100) { console.warn('Queue size:', queueSize) } }, 1000) } ``` ```javascript // main.mjs import { setupPerformanceMode, monitorQueue } from './performance.mjs' setupPerformanceMode() monitorQueue() ``` -------------------------------- ### Optimize Performance with Polling and Throttling Source: https://github.com/hwanyong/iohook-macos/blob/main/README.md Enables performance mode, sets an optimal polling rate (e.g., 60fps), and throttles high-frequency mouse events. Includes a monitor for queue size to detect potential bottlenecks. ```javascript // Enable performance mode iohook.enablePerformanceMode() // Set optimal polling rate (60fps) iohook.setPollingRate(16) // Throttle high-frequency mouse events iohook.setMouseMoveThrottling(16) // Monitor queue size setInterval(() => { const queueSize = iohook.getQueueSize() if (queueSize > 100) { console.warn('Queue getting large:', queueSize) } }, 1000) ``` -------------------------------- ### Event Listeners with iohook-macos (ESM) Source: https://github.com/hwanyong/iohook-macos/blob/main/docs/ai-usage-guide.esm.en.prompt.md Sets up listeners for keyboard, mouse, and generic system events using the 'on' method. The 'event' type captures all monitored events. ```javascript import iohook from 'iohook-macos' // Keyboard events iohook.on('keyDown', (event) => { console.log('Key pressed:', event.keyCode) }) // Mouse events iohook.on('leftMouseDown', (event) => { console.log('Left click at:', event.x, event.y) }) // Generic event listener iohook.on('event', (event) => { console.log('Event type:', event.type) }) ```