aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarstrom <john@ankarstrom.se>2021-07-01 18:40:44 +0200
committerJohn Ankarstrom <john@ankarstrom.se>2021-07-01 18:40:44 +0200
commit83923c1471d2d75c2872a5498258573ecfa05013 (patch)
tree14580b59c47e2806631f2b8f29ee686ce19764d5
parentcf19637336ad36f6e58519c2696742c079e6bbf8 (diff)
downloaddwim-83923c1471d2d75c2872a5498258573ecfa05013.tar.gz
Add xchord utility
-rw-r--r--Makefile7
-rw-r--r--xchord.c92
2 files changed, 98 insertions, 1 deletions
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 <john (at) ankarstrom.se>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/Xlib.h>
+
+#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);
+ }
+}