-
Notifications
You must be signed in to change notification settings - Fork 12
/
push-to-talk.cpp
130 lines (112 loc) · 3.46 KB
/
push-to-talk.cpp
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <fcntl.h>
#include <libevdev/libevdev.h>
extern "C" {
#include <xdo.h>
}
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
struct libevdev *dev = NULL;
xdo_t *xdo;
bool verbose = false;
const char* keycode = "KEY_LEFTMETA";
const char *keyname = "Super_L";
int button = 0;
int opt;
while ((opt = getopt(argc, argv, "vk:n:")) != -1) {
switch (opt) {
case 'v':
verbose = true;
break;
case 'k':
keycode = optarg;
break;
case 'n':
if (optarg && strlen(optarg) >= 5 && !strncmp(optarg, "MOUSE", 5)) {
button = strtol((optarg + 5), NULL, 10);
if (errno) {
perror("strtol");
exit(EXIT_FAILURE);
}
}
/*
* Full list (Ignore leading XKB_KEY_):
* https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h
*/
keyname = optarg;
break;
default:
fprintf(stderr, "Usage: %s [-v] [-k keycode] [-n keyname] /dev/input/by-id/<device-name>\n", argv[0]);
exit(EXIT_FAILURE);
}
}
if (optind >= argc) {
fprintf(stderr, "Usage: %s [-v] [-k keycode] [-n keyname] /dev/input/by-id/<device-name>\n", argv[0]);
exit(EXIT_FAILURE);
}
int fd = open(argv[optind], O_RDONLY);
if (fd < 0) {
perror("Failed to open device");
if (getuid() != 0)
fprintf(stderr, "Fix permissions to %s or run as root\n", argv[1]);
exit(1);
}
int rc = libevdev_new_from_fd(fd, &dev);
if (rc < 0)
{
fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
exit(1);
}
fprintf(stderr, "Input device name: \"%s\"\n", libevdev_get_name(dev));
fprintf(stderr, "Input device ID: bus %#x vendor %#x product %#x\n",
libevdev_get_id_bustype(dev),
libevdev_get_id_vendor(dev),
libevdev_get_id_product(dev));
int ev_keycode = libevdev_event_code_from_name(EV_KEY, keycode);
if (ev_keycode < 0) {
fprintf(stderr, "Key code not found\n");
fprintf(stderr, "see https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h\n");
exit(1);
}
if (!libevdev_has_event_code(dev, EV_KEY, ev_keycode)) {
fprintf(stderr, "This device is not capable of sending this key code\n");
exit(1);
}
xdo = xdo_new(NULL);
if (xdo == NULL) {
fprintf(stderr, "Failed to initialize xdo lib\n");
exit(1);
}
if (verbose) {
fprintf(stderr, "Listening for code %s, sending %s\n", libevdev_event_code_get_name(EV_KEY, ev_keycode), keyname);
}
do {
struct input_event ev;
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
if (rc != LIBEVDEV_READ_STATUS_SUCCESS)
continue;
if (ev.type == EV_KEY && ev.code == ev_keycode && ev.value != 2) {
if (verbose)
fprintf(stderr, "key %s\n", ev.value ? "up" : "down");
if (ev.value == 1) {
if (!button)
xdo_send_keysequence_window_down(xdo, CURRENTWINDOW, keyname, 0);
else
xdo_mouse_down(xdo, CURRENTWINDOW, button);
} else {
if (!button)
xdo_send_keysequence_window_up(xdo, CURRENTWINDOW, keyname, 0);
else
xdo_mouse_up(xdo, CURRENTWINDOW, button);
}
}
} while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN);
xdo_free(xdo);
libevdev_free(dev);
close(fd);
return 0;
}