From 83923c1471d2d75c2872a5498258573ecfa05013 Mon Sep 17 00:00:00 2001 From: John Ankarstrom Date: Thu, 1 Jul 2021 18:40:44 +0200 Subject: Add xchord utility --- Makefile | 7 ++++- xchord.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 xchord.c diff --git a/Makefile b/Makefile index ab5f525..415b07f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ BINDIR ?= /usr/local/bin +CFLAGS = -I/usr/X11R7/include +LDFLAGS = -L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib -lXi + +xchord: xchord.c install: - ln -s $(PWD)/dwim $(BINDIR)/dwim + ln -sf $(PWD)/dwim $(BINDIR)/dwim + install xchord /usr/local/bin diff --git a/xchord.c b/xchord.c new file mode 100644 index 0000000..3ceef51 --- /dev/null +++ b/xchord.c @@ -0,0 +1,92 @@ +/* + * 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 + +#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 (;;) { + 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; + /* button 1 + 3 pressed */ + if (p1 && rev->detail == 3) system("dwim"); + break; + case XI_RawButtonRelease: + /* button 1 released */ + if (rev->detail == 1) p1 = 0; + break; + } + + XFreeEventData(dpy, cookie); + } +} -- cgit v1.2.3