1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/*
* 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 <err.h>
#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 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);
}
}
|