A comprehensive native Node.js addon for monitoring trackpad gestures, mouse events, and keyboard input on macOS. Perfect for Electron applications that need to capture global input events.
- 🎯 Trackpad Gestures: Swipe, pinch, rotate with finger count detection
- 🖱️ Mouse Events: Click, move, drag, scroll with button detection
- ⌨️ Keyboard Events: Key press/release, modifier keys, repeat detection
- 🔒 Separate Event Emitters: Individual callbacks for different event types
- 🚀 High Performance: Native C++/Objective-C implementation
- 📱 Electron Ready: Easy integration with Electron applications
- 🎛️ Configurable: Enable/disable specific event types
- 🔐 Security: Proper accessibility permission handling
- macOS 10.15 or later
- Node.js 12.0.0 or later
- Accessibility permissions granted
npm install macos-input-monitor
const { inputMonitor } = require('macos-input-monitor');
// Check and request accessibility permissions
if (!inputMonitor.checkAccess()) {
inputMonitor.requestAccess();
}
// Set up event listeners
inputMonitor.on('gesture', (data) => {
console.log(`Gesture: ${data.type} ${data.direction}`);
});
inputMonitor.on('mousedown', (data) => {
console.log(`Mouse down: ${data.button} at (${data.x}, ${data.y})`);
});
inputMonitor.on('keydown', (data) => {
console.log(`Key pressed: ${data.key}`);
});
// Start monitoring
inputMonitor.start();
// Stop monitoring when done
process.on('SIGINT', () => {
inputMonitor.stop();
process.exit(0);
});
Start monitoring input events.
inputMonitor.start({
enableGestures: true, // Monitor trackpad gestures
enableMouse: true, // Monitor mouse events
enableKeyboard: true // Monitor keyboard events
});
Stop monitoring input events.
Check if accessibility permissions are granted.
Request accessibility permissions (shows system dialog).
inputMonitor.on('gesture', (data) => {
// data.type: 'swipe' | 'pinch' | 'rotate'
// data.direction: 'left' | 'right' | 'up' | 'down' | 'in' | 'out' | 'clockwise' | 'counterclockwise'
// data.fingerCount: number of fingers detected
// data.deltaX, data.deltaY: movement deltas
// data.magnification: pinch scale factor
// data.rotation: rotation angle
});
inputMonitor.on('mousedown', (data) => {
// data.button: 'left' | 'right' | 'middle' | 'button4' | 'button5'
// data.clickType: 'single' | 'double' | 'triple'
// data.x, data.y: cursor position
});
inputMonitor.on('mouseup', (data) => {
// Same structure as mousedown
});
inputMonitor.on('mousemove', (data) => {
// data.type: 'mousemove' | 'mousedrag'
// data.direction: 'left' | 'right' | 'up' | 'down'
// data.deltaX, data.deltaY: movement deltas
// data.isDrag: boolean for drag operations
});
inputMonitor.on('scroll', (data) => {
// data.button: 'trackpad' | 'wheel'
// data.direction: scroll direction
// data.deltaX, data.deltaY: scroll deltas
});
inputMonitor.on('keydown', (data) => {
// data.key: 'A' | 'Enter' | 'Shift' | 'ArrowUp' | etc.
// data.keyCode: raw key code
// data.modifiers: 'Control+Shift' | 'Meta+Alt' | etc.
// data.isRepeat: boolean for key repeat
});
inputMonitor.on('keyup', (data) => {
// Same structure as keydown
});
inputMonitor.on('modifier', (data) => {
// data.key: 'Control' | 'Shift' | 'Meta' | 'Alt' | etc.
// data.isPressed: boolean for press/release state
});
const { MacOSInputMonitor } = require('macos-input-monitor');
const monitor = new MacOSInputMonitor();
monitor.on('gesture', handleGesture);
monitor.start();
// In your main process
const { app, BrowserWindow } = require('electron');
const { inputMonitor } = require('macos-input-monitor');
app.whenReady().then(() => {
// Request permissions on app start
if (!inputMonitor.checkAccess()) {
inputMonitor.requestAccess();
return;
}
// Set up global gesture handling
inputMonitor.on('gesture', (data) => {
if (data.type === 'swipe' && data.direction === 'left') {
// Handle back navigation
BrowserWindow.getFocusedWindow()?.webContents.goBack();
}
});
inputMonitor.start({ enableGestures: true });
});
app.on('before-quit', () => {
inputMonitor.stop();
});
try {
inputMonitor.start();
} catch (error) {
if (error.message.includes('Accessibility permissions')) {
console.log('Please grant accessibility permissions');
inputMonitor.requestAccess();
} else if (error.message.includes('already active')) {
console.log('Monitoring is already running');
}
}
# Install dependencies
npm install
# Build native addon
npm run build
# Run tests
npm test
- Go to System Preferences > Security & Privacy > Privacy
- Select Accessibility from the left sidebar
- Click the lock icon and enter your password
- Add your application to the list or check the existing entry
-
"Failed to load native addon": Run
npm run build
to compile the native module - "Accessibility permissions not granted": Follow the permissions setup above
- "This package only works on macOS": This package is macOS-specific
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
MIT License - see LICENSE file for details.
- Initial release
- Trackpad gesture support (swipe, pinch, rotate)
- Mouse event monitoring (click, move, scroll)
- Keyboard event capture
- Separate event emitters for different input types
- TypeScript definitions included