From 44a2329d080d39bd0ed37fd57e0c0ef51ec477d1 Mon Sep 17 00:00:00 2001 From: rejedai Date: Fri, 15 Sep 2023 18:37:38 +0300 Subject: [PATCH 1/2] Added the ability to configure keys using Environment Variables --- README.md | 2 +- push-to-talk.cpp | 139 +++++++++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index a686415..ca70620 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This fixes the inability to use push to talk in Discord when running Wayland -**NOTE: by default the left Meta (Windows) key is used for push to talk. In order to use a different key, change values for `PTT_EV_KEY_CODE` and `PTT_XKEY_CODE` in file `push-to-talk.c`.** +**NOTE: by default the left Meta (Windows) key is used for push to talk. In order to use a different key, set `EV_KEY_CODE` and `XKEY_EVENT` environment variables.** ## Requirements diff --git a/push-to-talk.cpp b/push-to-talk.cpp index e287174..07c2899 100644 --- a/push-to-talk.cpp +++ b/push-to-talk.cpp @@ -1,13 +1,16 @@ #include #include #include + extern "C" { - #include +#include } + #include #include #include #include +#include /* See https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h */ #define PTT_EV_KEY_CODE KEY_LEFTMETA @@ -17,63 +20,83 @@ extern "C" { */ #define PTT_XKEY_EVENT "Super_L" -int main(int argc, char **argv) -{ - struct libevdev *dev = NULL; - xdo_t *xdo; - if (argc < 2) { - fprintf(stderr, "Usage: %s /dev/input/by-id/\n", argv[0]); - exit(0); - } - - int fd = open(argv[1], 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)); - - if (!libevdev_has_event_code(dev, EV_KEY, PTT_EV_KEY_CODE)) { - 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); - } - - 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 == PTT_EV_KEY_CODE && ev.value != 2) { - if (ev.value == 1) - xdo_send_keysequence_window_down(xdo, CURRENTWINDOW, PTT_XKEY_EVENT, 0); - else - xdo_send_keysequence_window_up(xdo, CURRENTWINDOW, PTT_XKEY_EVENT, 0); + +int get_ev_key_code() { + if (const char *ev_key_code_env = std::getenv("EV_KEY_CODE")) + return libevdev_event_code_from_name(EV_KEY, ev_key_code_env); + return PTT_EV_KEY_CODE; +} + +const char *get_xkey_event() { + if (const char *xkey_event_env = std::getenv("XKEY_EVENT")) + return xkey_event_env; + return PTT_XKEY_EVENT; +} + +int main(int argc, char **argv) { + struct libevdev *dev = NULL; + xdo_t *xdo; + if (argc < 2) { + fprintf(stderr, "Usage: %s /dev/input/by-id/\n", argv[0]); + exit(0); + } + + int fd = open(argv[1], 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)); + + + const int ptt_ev_key_code = get_ev_key_code(); + const char *ptt_xkey_event = get_xkey_event(); + + bool skip_event_check = false; + if (const char *env_skip_event_check = std::getenv("SKIP_EVENT_CHECK")) { + skip_event_check = strcmp(env_skip_event_check, "1") == 0 || strcmp(env_skip_event_check, "true") == 0; } - } while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN); - xdo_free(xdo); - libevdev_free(dev); - close(fd); + if (!skip_event_check && !libevdev_has_event_code(dev, EV_KEY, ptt_ev_key_code)) { + 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); + } - return 0; -} \ No newline at end of file + 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 == ptt_ev_key_code && ev.value != 2) { + if (ev.value == 1) + xdo_send_keysequence_window_down(xdo, CURRENTWINDOW, ptt_xkey_event, 0); + else + xdo_send_keysequence_window_up(xdo, CURRENTWINDOW, ptt_xkey_event, 0); + } + } while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN); + + xdo_free(xdo); + libevdev_free(dev); + close(fd); + + return 0; +} From 94367711368218223a4bae392f69cf587fcdba9d Mon Sep 17 00:00:00 2001 From: rejedai Date: Sun, 17 Sep 2023 12:37:32 +0300 Subject: [PATCH 2/2] Added additional information to README --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index ca70620..334cf2f 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,19 @@ sudo usermod -aG input ``` Then just log out and log in. A process named `push-to-talk` should be running (visible in any process monitor). +## Configure + +Supported options: + +| Environment variable | Description | +|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `EV_KEY_CODE` | Сode of the button that program expects to be pressed.

Full list:
https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h | +| `XKEY_EVENT` | Event to be sent to X11 apps.

Full list (Ignore leading **XKB_KEY_**):
https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h | +| `SKIP_EVENT_CHECK` | Skipping the evdev event existence check. Useful for cases when the mouse is used keyboard events. | + + + + # License MIT