/* * xchord -- run dwim on button 1 + 3 * * This is a simple program that runs dwim whenever the right * mouse button is pressed while the left mouse button is held. * * It does *not* block the button events. That means that both * clicks will be registered by other programs. This may be a * problem in programs that open a context menu on button 3. * * On NetBSD, xchord should be compiled with the following flags: * * CFLAGS = -I/usr/X11R7/include * LDFLAGS = -L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib -lXi * * xchord is written by John Ankarström . */ #include #include #include #include #include #include #include #define die(s, ...) do { \ fprintf(stderr, "%s: ", argv[0]); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ exit(s); \ } while (0) Display *dpy; Window rwin; int main(int argc, char *argv[]) { int p1; unsigned char mask[(XI_LASTEVENT+7)/8]; XEvent ev; XGenericEventCookie *cookie; XIEvent *xiev; XIEventMask evmasks[1]; XIRawEvent *rev; dpy = XOpenDisplay(NULL); if (!dpy) die(1, "could not open display"); rwin = DefaultRootWindow(dpy); /* select events */ memset(mask, 0, sizeof(mask)); XISetMask(mask, XI_RawButtonPress); XISetMask(mask, XI_RawButtonRelease); evmasks[0].deviceid = XIAllMasterDevices; evmasks[0].mask_len = sizeof(mask); evmasks[0].mask = mask; XISelectEvents(dpy, rwin, evmasks, 1); XFlush(dpy); cookie = &ev.xcookie; p1 = 0; /* watch for events */ for (;;) { XNextEvent(dpy, &ev); XPutBackEvent(dpy, &ev); if (!XCheckTypedEvent(dpy, GenericEvent, &ev)) continue; if (cookie->type != GenericEvent || !XGetEventData(dpy, cookie)) continue; xiev = (XIEvent*)cookie->data; rev = (XIRawEvent*)xiev; switch (cookie->evtype) { case XI_RawButtonPress: /* button 1 pressed */ if (rev->detail == 1) p1 = 1; break; case XI_RawButtonRelease: /* button 1 released */ if (rev->detail == 1) p1 = 0; /* button 1 pressed + 3 released */ if (p1 && rev->detail == 3 && vfork() == 0) { execlp("dwim", "dwim", NULL); err(1, "execlp"); } break; } XFreeEventData(dpy, cookie); } }