-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
105 lines (94 loc) · 2.63 KB
/
main.c
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
104
105
#ifdef CLICK_DETECTOR_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#endif
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
Reference material:
https://askubuntu.com/a/1044153
https://github.com/irontec/node-mouse/blob/05475133d67665c5fd7938a1d8b85f085565cd14/mouse.js
https://stackoverflow.com/a/67631433
*/
void print_help(char** argv) {
printf(
"Usage: %s\n%s\n",
argv[0],
" Upon start, this program will run until a click is detected. When a "
"click is detected it'll dump the event data and exit successfully."
);
}
int main(int argc, char** argv) {
if (argc == 2) {
char* arg = argv[1];
assert(arg);
print_help(argv);
if (strncmp(arg, "--help", strlen(arg)) == 0) {
exit(0);
} else {
fprintf(stderr, "ERROR: Invalid argument %s\n", arg);
exit(EXIT_FAILURE);
}
}
#ifdef CLICK_DETECTOR_X11
Display* display = XOpenDisplay(0);
Window root_window = DefaultRootWindow(display);
#endif
/*
To read this device $USER needs to be root or needs to be added to the to
the `input` group.
*/
const char* event_device = "/dev/input/mice";
int event_fd = open(event_device, O_RDONLY);
if (event_fd == -1) {
perror("open(event_device, O_RDONLY)");
printf("Failed to open %s", event_device);
return EXIT_FAILURE;
}
int bytes_read = 0;
char ev[3];
while (true) {
bytes_read += read(event_fd, &ev, sizeof(ev) - bytes_read);
if (bytes_read == sizeof(ev)) {
bytes_read = 0;
printf("ev: b0 %d b1 %d b2 %d\n", ev[0], ev[1], ev[2]);
/*
https://github.com/irontec/node-mouse/blob/05475133d67665c5fd7938a1d8b85f085565cd14/mouse.js
and other sources in the wild demonstrate that clicks should be
detected by the bits of ev[0], but from practice we found out that was
leading to false positives from arbitrary cursor movement. So instead
we use a different heuristic: if an event was triggered while
(ev[1] == 0 && ev[2] == 0), which are used for movement-related deltas,
infer that no movement was registered for this event, which means it
was a click.
*/
if (ev[1] == 0 && ev[2] == 0) {
printf("got click, exiting\n%d %d %d", ev[0], ev[1], ev[2]);
break;
}
#ifdef CLICK_DETECTOR_X11
XEvent event;
XQueryPointer(
display,
root_window,
&event.xbutton.root,
&event.xbutton.subwindow,
&event.xbutton.x_root,
&event.xbutton.y_root,
&event.xbutton.x,
&event.xbutton.y,
&event.xbutton.state
);
printf("x=%d, y=%d\n", event.xmotion.x, event.xmotion.y);
#endif
}
}
close(event_fd);
}