@@ -2,7 +2,6 @@ import { app, ipcMain, Menu, Tray, BrowserWindow, shell, dialog, desktopCapturer
22import serve from 'electron-serve'
33import { createWindow } from './helpers'
44const path = require ( 'node:path' )
5- const { GlobalKeyboardListener } = require ( "node-global-key-listener" )
65const fs = require ( 'fs' )
76const iconPath = path . join ( __dirname , 'logo.png' )
87const trayIconPath = path . join ( __dirname , 'traylogo.png' )
@@ -48,11 +47,13 @@ if (process.defaultApp) {
4847 app . setAsDefaultProtocolClient ( 'myapp' )
4948}
5049
51- const v = new GlobalKeyboardListener ( )
5250let mainWindow
5351let tray = null
54- let keyboardListener = null
5552let isTracking = null
53+ let activityInterval = null
54+
55+ // A second counts as "active" when the OS reports input within this many seconds.
56+ const ACTIVE_IDLE_THRESHOLD_SEC = 2
5657
5758if ( isProd ) {
5859 serve ( { directory : 'app' } )
@@ -302,39 +303,53 @@ if (!gotTheLock) {
302303 } )
303304}
304305
305- const setupKeyboardListener = ( ) => {
306- if ( ! verifyAccessibilityPermission ( ) ) {
307- mainWindow . webContents . send ( 'permission:denied' , { type : 'keyboard' } )
308- return false
309- }
310-
311- keyboardListener = function ( e , down ) {
312- if ( e . state == 'UP' && isTracking ) {
313- mainWindow . webContents . send ( 'keyboard:click' , { key : 'keyboard' , e : e . name } )
306+ // Activity sampling WITHOUT a global input hook (a hook is what antivirus flags
307+ // as a keylogger — the bug that quarantined the old node-global-key-listener
308+ // binary). Each second we read two built-in, hook-free signals:
309+ // - powerMonitor.getSystemIdleTime(): seconds since the last input (kbd OR mouse)
310+ // - screen.getCursorScreenPoint(): the current mouse cursor position
311+ // If the cursor moved this second it's MOUSE activity; if there was input but the
312+ // cursor did not move (typing) it's KEYBOARD activity. Limitation: a mouse click
313+ // that doesn't move the cursor is counted as keyboard — acceptable, since exact
314+ // click counts would require the AV-flagged global hook. No native binary, no
315+ // accessibility permission.
316+ let lastCursorPoint = null
317+ const startActivitySampling = ( ) => {
318+ if ( activityInterval ) return
319+ lastCursorPoint = null
320+ activityInterval = setInterval ( ( ) => {
321+ if ( ! isTracking || ! mainWindow || mainWindow . isDestroyed ( ) ) return
322+ const idleSeconds = powerMonitor . getSystemIdleTime ( )
323+ const cursor = screen . getCursorScreenPoint ( )
324+ const mouseMoved = lastCursorPoint !== null && ( cursor . x !== lastCursorPoint . x || cursor . y !== lastCursorPoint . y )
325+ lastCursorPoint = cursor
326+ if ( mouseMoved ) {
327+ mainWindow . webContents . send ( 'activity:tick' , { type : 'mouse' } )
328+ } else if ( idleSeconds <= ACTIVE_IDLE_THRESHOLD_SEC ) {
329+ mainWindow . webContents . send ( 'activity:tick' , { type : 'keyboard' } )
314330 }
315- }
316- v . addListener ( keyboardListener )
317- return true
331+ } , 1000 )
318332}
319333
320- // Function to remove keyboard listener
321- const removeKeyboardListener = ( ) => {
322- if ( keyboardListener ) {
323- v . removeListener ( keyboardListener )
324- keyboardListener = null
334+ // Stop the activity sampler.
335+ const stopActivitySampling = ( ) => {
336+ if ( activityInterval ) {
337+ clearInterval ( activityInterval )
338+ activityInterval = null
325339 }
340+ lastCursorPoint = null
326341}
327342
328343// Add IPC listeners for start and stop events
329344ipcMain . on ( 'start-listen-event' , ( ) => {
330- isTracking = setupKeyboardListener ( )
331- // Inform renderer process if setup was successful
332- mainWindow . webContents . send ( 'tracking:status' , { active : isTracking } )
345+ isTracking = true
346+ startActivitySampling ( )
347+ mainWindow . webContents . send ( 'tracking:status' , { active : true } )
333348} )
334349
335350ipcMain . on ( 'stop-listen-event' , ( ) => {
336351 isTracking = false
337- removeKeyboardListener ( )
352+ stopActivitySampling ( )
338353 mainWindow . webContents . send ( 'tracking:status' , { active : false } )
339354} )
340355
0 commit comments