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 record_main_loop(Display * display, double idle_time) { struct xrecord_callback_results cbres; XRecordContext context; XRecordClientSpec cspec = XRecordAllClients; Display *dpy_data; XRecordRange *range; int i; dpy_data = XOpenDisplay(NULL); /* we need an additional data connection. */ range = XRecordAllocRange(); range->device_events.first = KeyPress; range->device_events.last = KeyRelease; context = XRecordCreateContext(dpy_data, 0, &cspec, 1, &range, 1); XRecordEnableContextAsync(dpy_data, context, xrecord_callback, (XPointer) & cbres); cbres.modifiers = XGetModifierMapping(display); /* clear list of modifiers */ for (i = 0; i < MAX_MODIFIERS; ++i) cbres.pressed_modifiers[i] = 0; while (1) { int fd = ConnectionNumber(dpy_data); fd_set read_fds; int ret; int disable_event = 0; int modifier_event = 0; struct timeval timeout; FD_ZERO(&read_fds); FD_SET(fd, &read_fds); ret = select(fd + 1 /* =(max descriptor in read_fds) + 1 */ , &read_fds, NULL, NULL, pad_disabled ? &timeout : NULL /* timeout only required for enabling */ ); if (FD_ISSET(fd, &read_fds)) { cbres.key_event = 0; cbres.non_modifier_event = 0; XRecordProcessReplies(dpy_data); /* If there are any events left over, they are in error. Drain them * from the connection queue so we don't get stuck. */ while (XEventsQueued(dpy_data, QueuedAlready) > 0) { XEvent event; XNextEvent(dpy_data, &event); fprintf(stderr, "bad event received, major opcode %d\n", event.type); } if (!ignore_modifier_keys && cbres.key_event) { disable_event = 1; } if (cbres.non_modifier_event) { if (ignore_modifier_combos && is_modifier_pressed(&cbres)) { modifier_event = 1; } else { disable_event = 1; } } else if (ignore_modifier_keys) { modifier_event = 1; } } if (disable_event) { /* adjust the enable_time */ timeout.tv_sec = (int) idle_time; timeout.tv_usec = (idle_time - (double) timeout.tv_sec) * 1.e6; toggle_touchpad(False); } if (modifier_event && pad_disabled) { toggle_touchpad(True); } if (ret == 0 && pad_disabled) { /* timeout => enable event */ toggle_touchpad(True); } } /* end while(1) */ XFreeModifiermap(cbres.modifiers); }