/* * 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 p; 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; p = 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: /* 1 pressed (first step) */ if (rev->detail == 1) p = 1; /* 1 + 3 pressed (second step) */ if (p > 0 && rev->detail == 3) p = 2; break; case XI_RawButtonRelease: /* 1 pressed + 3 pressed + 3 released (third step) */ if (p == 2 && rev->detail == 3) { p = 3; if (vfork() == 0) { execlp("dwim", "dwim", NULL); err(1, "execlp"); } } /* 1 released (reset) */ if (p == 3 && rev->detail == 1) p = 0; break; } XFreeEventData(dpy, cookie); } }