/* copyright 2004: Helge Jensen */ /* make libidle.h export functions */ #define LIBIDLE_DLL __declspec(dllexport) #include #include #include #include #include "libidle.h" struct libidle { time_t last; HHOOK key_hook; HHOOK mouse_hook; HANDLE map_handle; POINT pt; long refcount; }; static long dll_refcount = 0; static HINSTANCE instance = NULL; static struct libidle* _track = NULL; static struct libidle* tracker() { if ( _track == NULL ) { HANDLE map_handle; int created = 1; /* try alloc shared mem */ map_handle = CreateFileMapping( INVALID_HANDLE_VALUE, /* use pagingfile */ NULL, /* no security */ PAGE_READWRITE, /* page-protection */ 0, /* size: high 32bit */ sizeof(*_track), /* size: low 32bit */ "libidle_libidle" /* name */ ); /* from win32 specs: The initial contents of the pages in the file mapping object are zero. */ /* was already alloced? */ if ( GetLastError() == ERROR_ALREADY_EXISTS ) created = 0; else if ( map_handle == NULL ) /* failed allocation */ return (struct libidle*)-1; /* memory-map */ _track = (struct libidle*) MapViewOfFile( map_handle, /* map this file */ FILE_MAP_WRITE, /* R/W */ 0, /* offset, high 32bit */ 0, /* offset, low 32bit */ sizeof(*_track) /* size */ ); /* NOTE: win32 docs says we can CloseHandle(map_handle) now, but that's not true! if we do that the _track will not be flushed to shared-mem (at least on windows XP) */ if ( _track == NULL ) /* memmap failed */ return (struct libidle*)-2; _track->map_handle = map_handle; } return _track; } static void libidle_event(void) { time(&(tracker()->last)); /* update timestamp */ } /* dllexport according to win32 specs */ __declspec(dllexport) LRESULT CALLBACK libidle_keyboard(int code, WPARAM wParam, LPARAM lParam) { if ( code == HC_ACTION ) libidle_event(); return CallNextHookEx(tracker()->key_hook, code, wParam, lParam); } /* dllexport according to win32 specs */ __declspec(dllexport) LRESULT CALLBACK libidle_mouse(int code, WPARAM wParam, LPARAM lParam) { struct libidle *track = tracker(); if ( code == HC_ACTION ) { /* sometimes windows generate mouse_actions without the mouse moving! */ const MOUSEHOOKSTRUCT* mouse = (const MOUSEHOOKSTRUCT*) lParam; int moved = 0; if ( track->pt.x != mouse->pt.x ) { track->pt.x = mouse->pt.x; moved = 1; } if ( track->pt.y != mouse->pt.y ) { track->pt.y = mouse->pt.y; moved = 1; } if (moved) libidle_event(); } return CallNextHookEx(track->mouse_hook, code, wParam, lParam); } double libidle_time(struct libidle* track) { /* who needs more than 1sec precision? */ time_t now; (void)track; time(&now); return difftime(now, tracker()->last); } struct libidle* libidle_init() { struct libidle *track = tracker(); if ( track == NULL ) return NULL; if ( track == (struct libidle *) -1 ) return NULL; if ( track == (struct libidle *) -2 ) return NULL; InterlockedIncrement(&track->refcount); InterlockedIncrement(&dll_refcount); track->key_hook = SetWindowsHookEx(WH_KEYBOARD, libidle_keyboard, instance, 0); if ( track->key_hook == NULL ) { libidle_exit(track); return NULL; } track->mouse_hook = SetWindowsHookEx(WH_MOUSE, libidle_mouse, instance, 0); if ( track->mouse_hook == NULL ) { libidle_exit(track); return NULL; } libidle_event(); return NULL; } void libidle_exit(struct libidle* data) { struct libidle *track = tracker(); int unhook = 0; int unmap = 0; (void)data; if ( track->refcount <= 0 || InterlockedDecrement(&track->refcount) <= 0 ) { track->refcount = 0; unhook = 1; } if ( dll_refcount <= 0 || InterlockedDecrement(&dll_refcount) <= 0 ) { dll_refcount = 0; unmap = 1; } if ( unhook ) { if ( track->key_hook ) UnhookWindowsHookEx(track->key_hook); if ( track->mouse_hook ) UnhookWindowsHookEx(track->mouse_hook); } if ( unmap ) { if ( track->map_handle ) CloseHandle(track->map_handle); UnmapViewOfFile(_track); _track = NULL; } } BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { (void)lpReserved; if ( dwReason == DLL_PROCESS_ATTACH ) instance = hInstance; return TRUE; } /* Local Variables: */ /* mode: C */ /* c-file-style: "stroustrup" */ /* End: */