int main() { Display* display = XOpenDisplay(0); if (display == 0) { fprintf(stderr, "unable to open display\n"); exit(-1); } int major, minor; if (!XRecordQueryVersion(display, &major, &minor)) { fprintf(stderr, "xrecord extension not available\n"); } // Receive from ALL clients, including future clients. XRecordClientSpec clients = XRecordAllClients; XRecordRange* range = XRecordAllocRange(); if (range == 0) { fprintf(stderr, "unable to allocate XRecordRange\n"); exit(-1); } // Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and // MotionNotify events. memset(range, 0, sizeof(XRecordRange)); range->device_events.first = KeyPress; range->device_events.last = MotionNotify; // And create the XRECORD context. XRecordContext context = XRecordCreateContext (display, 0, &clients, 1, &range, 1); if (context == 0) { fprintf(stderr, "XRecordCreateContext failed\n"); exit(-1); } XFree(range); // what is that for? (copied from workrave sourcecode) XSync(display, True); Display* display_datalink = XOpenDisplay(0); if (display_datalink == 0) { fprintf(stderr, "unable to open second display\n"); exit(-1); } if (!XRecordEnableContext(display_datalink, context, &callback, (XPointer)0)) { fprintf(stderr, "XRecordEnableContext() failed\n"); exit(-1); } // Call above seems to block forever. fprintf(stderr, "Terminating. (huh?)\n"); // Who cares about cleanup, linux and xorg sure will do this for us. return 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
/* test if the xrecord extension is found */ Bool check_xrecord(Display * display) { Bool found; Status status; int major_opcode, minor_opcode, first_error; int version[2]; found = XQueryExtension(display, "RECORD", &major_opcode, &minor_opcode, &first_error); status = XRecordQueryVersion(display, version, version + 1); if (verbose && status) { printf("X RECORD extension version %d.%d\n", version[0], version[1]); } return found; }
int main (int argc, char **argv) { ctrl_disp = XOpenDisplay (NULL); data_disp = XOpenDisplay (NULL); if (!ctrl_disp || !data_disp) { fprintf (stderr, "Error to open local display!\n"); exit (1); } /* * we must set the ctrl_disp to sync mode, or, when we the enalbe * context in data_disp, there will be a fatal X error !!! */ XSynchronize(ctrl_disp,True); int major, minor; if (!XRecordQueryVersion (ctrl_disp, &major, &minor)) { fprintf (stderr, "RECORD extension not supported on this X server!\n"); exit (2); } printf ("RECORD extension for local server is version is %d.%d\n", major, minor); XRecordRange *rr; XRecordClientSpec rcs; XRecordContext rc; rr = XRecordAllocRange (); if (!rr) { fprintf (stderr, "Could not alloc record range object!\n"); exit (3); } rr->device_events.first = KeyPress; rr->device_events.last = MotionNotify; rcs = XRecordAllClients; rc = XRecordCreateContext (ctrl_disp, 0, &rcs, 1, &rr, 1); if (!rc) { fprintf (stderr, "Could not create a record context!\n"); exit (4); } if (!XRecordEnableContext (data_disp, rc, event_callback, NULL)) { fprintf (stderr, "Cound not enable the record context!\n"); exit (5); } while (stop != 1) { XRecordProcessReplies (data_disp); } XRecordDisableContext (ctrl_disp, rc); XRecordFreeContext (ctrl_disp, rc); XFree (rr); XCloseDisplay (data_disp); XCloseDisplay (ctrl_disp); return 0; }
void xrecord_thread (gpointer data) { int dummy; self_xcape = calloc (sizeof (XCape_t), 1); if ( !self_xcape ) { g_debug ("Got XCape memory failed!\n"); /*return FALSE;*/ g_thread_exit (NULL); } self_xcape->data_conn = XOpenDisplay (NULL); self_xcape->ctrl_conn = XOpenDisplay (NULL); if ( !self_xcape->data_conn || !self_xcape->ctrl_conn ) { g_debug ("Unable to connect to X11 display!\n"); /*return FALSE;*/ g_thread_exit (NULL); } if ( !XQueryExtension (self_xcape->ctrl_conn, "XTEST", &dummy, &dummy, &dummy) ) { g_debug ("Xtst extension missing!\n"); /*return FALSE;*/ g_thread_exit (NULL); } if ( !XRecordQueryVersion (self_xcape->ctrl_conn, &dummy, &dummy) ) { g_debug ("Failed to obtain xrecord version!\n"); /*return FALSE;*/ g_thread_exit (NULL); } if ( !XkbQueryExtension (self_xcape->ctrl_conn, &dummy, &dummy, &dummy, &dummy, &dummy)) { g_debug ("Failed to obtain xkb version!\n"); /*return FALSE;*/ g_thread_exit (NULL); } XRecordRange* rec_range = XRecordAllocRange (); rec_range->device_events.first = KeyPress; rec_range->device_events.last = ButtonRelease; XRecordClientSpec client_spec = XRecordAllClients; self_xcape->record_ctx = XRecordCreateContext (self_xcape->ctrl_conn, 0, &client_spec, 1, &rec_range, 1); if ( self_xcape->record_ctx == 0 ) { g_debug ("Failed to create xrecord context!\n"); /*return FALSE;*/ g_thread_exit (NULL); } /*XSync (self_xcape->ctrl_conn, FALSE);*/ XFlush (self_xcape->ctrl_conn); if ( !XRecordEnableContext (self_xcape->data_conn, self_xcape->record_ctx, intercept, (XPointer)self_xcape) ) { g_debug ("Failed to enable xrecord context!\n"); /*return FALSE;*/ g_thread_exit (NULL); } g_thread_exit (NULL); }
void grab_xrecord_init () { key_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_free); grab_info = g_new0 (XRecordGrabInfo, 1); if ( !grab_info ) { g_warning ("Alloc XRecordGrabInfo memory failed..."); grab_xrecord_finalize (); } grab_info->ctrl_disp = XOpenDisplay (NULL); grab_info->data_disp = XOpenDisplay (NULL); if ( !grab_info->ctrl_disp || !grab_info->data_disp ) { g_warning ("Unable to connect to X server..."); grab_xrecord_finalize (); } gint dummy; if ( !XQueryExtension (grab_info->ctrl_disp, "XTEST", &dummy, &dummy, &dummy) ) { g_warning ("XTest extension missing..."); grab_xrecord_finalize (); } if ( !XRecordQueryVersion (grab_info->ctrl_disp, &dummy, &dummy) ) { g_warning ("Failed to obtain xrecord version..."); grab_xrecord_finalize (); } grab_info->range = XRecordAllocRange (); if ( !grab_info->range ) { g_warning ("Alloc XRecordRange memory failed..."); grab_xrecord_finalize (); } grab_info->range->device_events.first = KeyPress; grab_info->range->device_events.last = ButtonRelease; XRecordClientSpec spec = XRecordAllClients; grab_info->context = XRecordCreateContext ( grab_info->data_disp, 0, &spec, 1, &grab_info->range, 1); if ( !grab_info->context ) { g_warning ("Unable to create context..."); grab_xrecord_finalize(); } XSynchronize (grab_info->ctrl_disp, TRUE); XFlush (grab_info->ctrl_disp); GThread *thrd = g_thread_new ("enable context", (GThreadFunc)enable_ctx_thread, NULL); if ( !thrd ) { g_warning ("Unable to create thread..."); grab_xrecord_finalize (); } g_thread_unref(thrd); }
GUIRecord():disp(NULL),xrr(NULL),udisp(NULL){ init_keysym(); disp = XOpenDisplay(NULL); display = disp; if (disp == NULL) { fprintf(stderr, "Unable to open display connection.\n"); exit(1); } XSynchronize(disp, False); udisp = XOpenDisplay(NULL); if (udisp == NULL) { fprintf(stderr, "Unable to open other display connection.\n"); exit(1); } // Ensure extension available int major = 0, minor = 0; if (!XRecordQueryVersion(disp, &major, &minor)) { fprintf(stderr, "The record extension is unavailable.\n"); exit(1); } xrr = XRecordAllocRange(); if (xrr == NULL) { fprintf(stderr, "Range allocation failed.\n"); exit(1); } xrr->device_events.first = KeyPress; xrr->device_events.last = MotionNotify; //xrr->device_events.last = FocusIn; xrr->delivered_events.first = FocusIn; //xrr->delivered_events.last = FocusOut; xrr->delivered_events.last = ConfigureNotify; //xrr->delivered_events.last = SelectionNotify; // INFO: use PropertyNotify when Copy // INFO: use SelectionRequest when Paste /* xrr->core_requests.first = EnterNotify; xrr->core_requests.last = FocusIn; xrr->core_replies.first = EnterNotify; xrr->core_replies.last = FocusIn; */ //XRecordClientSpec xrclient = XRecordAllClients; XRecordClientSpec xrclient = XRecordCurrentClients; xrctx = XRecordCreateContext(disp, 0, &xrclient, 1, &xrr, 1); if (!xrctx) { fprintf(stderr, "Unable to create context.\n"); exit(1); } // Clean out X events in progress //XFlush(disp); //XFlush(otherDisp); }
/************************************************************************ * Main function ***********************************************************************/ int main(int argc, char **argv) { XCape_t *self = malloc(sizeof(XCape_t)); int dummy, ch; static char default_mapping[] = "Num_Lock;Caps_Lock"; char *mapping = default_mapping; self->debug = False; while ((ch = getopt(argc, argv, "d")) != -1) { switch (ch) { case 'd': self->debug = True; break; default: fprintf(stdout, "Usage: %s [-d]\n", argv[0]); fprintf(stdout, "Runs as a daemon unless -d flag is set\n"); return EXIT_SUCCESS; } } self->data_conn = XOpenDisplay(NULL); self->ctrl_conn = XOpenDisplay(NULL); if (!self->data_conn || !self->ctrl_conn) { fprintf(stderr, "Unable to connect to X11 display. Is $DISPLAY set?\n"); exit(EXIT_FAILURE); } if (!XQueryExtension(self->ctrl_conn, "XTEST", &dummy, &dummy, &dummy)) { fprintf(stderr, "Xtst extension missing\n"); exit(EXIT_FAILURE); } if (!XRecordQueryVersion(self->ctrl_conn, &dummy, &dummy)) { fprintf(stderr, "Failed to obtain xrecord version\n"); exit(EXIT_FAILURE); } if (!XkbQueryExtension(self->ctrl_conn, &dummy, &dummy, &dummy, &dummy, &dummy)) { fprintf(stderr, "Failed to obtain xkb version\n"); exit(EXIT_FAILURE); } self->map = parse_mapping(self->ctrl_conn, mapping); if (self->map == NULL) exit(EXIT_FAILURE); if (self->debug != True) daemon(0, 0); sigemptyset(&self->sigset); sigaddset(&self->sigset, SIGINT); sigaddset(&self->sigset, SIGTERM); pthread_sigmask(SIG_BLOCK, &self->sigset, NULL); pthread_create(&self->sigwait_thread, NULL, sig_handler, self); XRecordRange *rec_range = XRecordAllocRange(); rec_range->device_events.first = KeyPress; rec_range->device_events.last = ButtonRelease; XRecordClientSpec client_spec = XRecordAllClients; self->record_ctx = XRecordCreateContext(self->ctrl_conn, 0, &client_spec, 1, &rec_range, 1); if (self->record_ctx == 0) { fprintf(stderr, "Failed to create xrecord context\n"); exit(EXIT_FAILURE); } XSync(self->ctrl_conn, False); if (!XRecordEnableContext(self->data_conn, self->record_ctx, intercept, (XPointer) self)) { fprintf(stderr, "Failed to enable xrecord context\n"); exit(EXIT_FAILURE); } if (!XRecordFreeContext(self->ctrl_conn, self->record_ctx)) { fprintf(stderr, "Failed to free xrecord context\n"); } XCloseDisplay(self->ctrl_conn); XCloseDisplay(self->data_conn); if (self->debug) fprintf(stdout, "main exiting\n"); return EXIT_SUCCESS; }