// !!! FIXME: this is X11 specific. :( #include #if 1 #include #include #include #include #include #include #include #include "keyhook.h" static volatile int keyPressFlags = 0; static volatile int sawKeyCombo = 0; static void keyhookCallback(XPointer priv, XRecordInterceptData *data) { const xEvent *xev = (const xEvent *) data->data; if (data->category == XRecordFromServer) { if (xev->u.u.type == KeyPress) { const BYTE keycode = xev->u.u.detail; //printf("Pressed X11 keycode %u\n", (unsigned int) keycode); // !!! FIXME: don't hardcode these keycodes. if ((keycode == 64) && (keyPressFlags == 0)) keyPressFlags++; else if ((keycode == 133) && (keyPressFlags == 1)) keyPressFlags++; else if ((keycode == 51) && (keyPressFlags == 2)) { sawKeyCombo = 1; keyPressFlags = 0; } // else if else keyPressFlags = 0; } // if else if (xev->u.u.type == KeyRelease) { keyPressFlags = 0; } // else if } // if XRecordFreeData(data); } // keyhookCallback // every example I've seen needs two Display connections...one for the // keyhook, and one to control it. static Display *ctrldpy = NULL; static Display *datadpy = NULL; static XRecordContext xrc = 0; int initKeyHook(void) { int major = 0; int minor = 0; XRecordRange *xrr = NULL; XRecordClientSpec xrcs = XRecordAllClients; if (ctrldpy) return 0; // already initialized. ctrldpy = XOpenDisplay(NULL); if (!ctrldpy) goto failed; XSynchronize(ctrldpy, True); datadpy = XOpenDisplay(NULL); if (!datadpy) goto failed; else if (!XRecordQueryVersion(ctrldpy, &major, &minor)) goto failed; else if ((xrr = XRecordAllocRange()) == NULL) goto failed; memset(xrr, '\0', sizeof (*xrr)); xrr->device_events.first = KeyPress; xrr->device_events.last = KeyPress; if ((xrc = XRecordCreateContext(ctrldpy, 0, &xrcs, 1, &xrr, 1)) == 0) goto failed; else if (!XRecordEnableContextAsync(datadpy, xrc, keyhookCallback, NULL)) goto failed; XFree(xrr); xrr = NULL; return 1; failed: deinitKeyHook(); if (xrr) XFree(xrr); return 0; } // initKeyHook void deinitKeyHook(void) { if (ctrldpy) { if (xrc) { XRecordDisableContext(ctrldpy, xrc); XRecordFreeContext(ctrldpy, xrc); } // if XCloseDisplay(ctrldpy); } // if if (datadpy) XCloseDisplay(datadpy); ctrldpy = NULL; datadpy = NULL; xrc = 0; sawKeyCombo = 0; keyPressFlags = 0; } // deinitKeyHook int pumpKeyHook(void) { if (!datadpy) return 0; sawKeyCombo = 0; XRecordProcessReplies(datadpy); return sawKeyCombo; } // pumpKeyHook #else int initKeyHook(void) { return 1; } void deinitKeyHook(void) {} int pumpKeyHook(void) { static int x = 50; const int retval = (x == 50); if (++x > 50) x = 0; if (retval) printf("fire it!\n"); return retval; } #endif // end of keyhook.c ...