diff options
Diffstat (limited to 'tools/gsr-global-hotkeys/main.c')
-rw-r--r-- | tools/gsr-global-hotkeys/main.c | 115 |
1 files changed, 107 insertions, 8 deletions
diff --git a/tools/gsr-global-hotkeys/main.c b/tools/gsr-global-hotkeys/main.c index aeea660..b64d60f 100644 --- a/tools/gsr-global-hotkeys/main.c +++ b/tools/gsr-global-hotkeys/main.c @@ -3,9 +3,11 @@ /* C stdlib */ #include <stdio.h> #include <stdint.h> +#include <string.h> /* POSIX */ #include <unistd.h> +#include <dlfcn.h> typedef struct { uint32_t key; @@ -15,12 +17,12 @@ typedef struct { #define NUM_GLOBAL_HOTKEYS 6 static global_hotkey global_hotkeys[NUM_GLOBAL_HOTKEYS] = { - { .key = KEY_Z, .modifiers = KEYBOARD_MODKEY_ALT, .action = "show_hide" }, - { .key = KEY_F9, .modifiers = KEYBOARD_MODKEY_ALT, .action = "record" }, - { .key = KEY_F7, .modifiers = KEYBOARD_MODKEY_ALT, .action = "pause" }, - { .key = KEY_F8, .modifiers = KEYBOARD_MODKEY_ALT, .action = "stream" }, - { .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT | KEYBOARD_MODKEY_SHIFT, .action = "replay_start" }, - { .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT, .action = "replay_save" } + { .key = KEY_Z, .modifiers = KEYBOARD_MODKEY_LALT, .action = "show_hide" }, + { .key = KEY_F9, .modifiers = KEYBOARD_MODKEY_LALT, .action = "record" }, + { .key = KEY_F7, .modifiers = KEYBOARD_MODKEY_LALT, .action = "pause" }, + { .key = KEY_F8, .modifiers = KEYBOARD_MODKEY_LALT, .action = "stream" }, + { .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_LALT | KEYBOARD_MODKEY_SHIFT, .action = "replay_start" }, + { .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_LALT, .action = "replay_save" } }; static bool on_key_callback(uint32_t key, uint32_t modifiers, int press_status, void *userdata) { @@ -37,7 +39,104 @@ static bool on_key_callback(uint32_t key, uint32_t modifiers, int press_status, return true; } -int main(void) { +static void usage(void) { + fprintf(stderr, "usage: gsr-global-hotkeys [--all|--virtual]\n"); + fprintf(stderr, "OPTIONS:\n"); + fprintf(stderr, " --all Grab all devices.\n"); + fprintf(stderr, " --virtual Grab all virtual devices only.\n"); +} + +typedef void* (*XOpenDisplay_FUNC)(const char*); +typedef int (*XErrorHandler_FUNC)(void *display, void* error_event); +typedef XErrorHandler_FUNC (*XSetErrorHandler_FUNC)(XErrorHandler_FUNC handler); + +static int x_ignore_error(void *display, void *ee) { + (void)display; + (void)ee; + return 0; +} + +static x11_context setup_x11_context(void) { + x11_context x_context = {0}; + XSetErrorHandler_FUNC XSetErrorHandler = NULL; + + void *x11_lib = dlopen("libX11.so.6", RTLD_LAZY); + if(!x11_lib) { + fprintf(stderr, "Warning: dlopen libX11.so.6 failed\n"); + return x_context; + } + + XOpenDisplay_FUNC XOpenDisplay = dlsym(x11_lib, "XOpenDisplay"); + if(!XOpenDisplay) { + fprintf(stderr, "Warning: dlsym XOpenDisplay failed\n"); + goto fail; + } + + x_context.XKeycodeToKeysym = dlsym(x11_lib, "XKeycodeToKeysym"); + if(!x_context.XKeycodeToKeysym) { + fprintf(stderr, "Warning: dlsym XKeycodeToKeysym failed\n"); + goto fail; + } + + x_context.XPending = dlsym(x11_lib, "XPending"); + if(!x_context.XPending) { + fprintf(stderr, "Warning: dlsym XPending failed\n"); + goto fail; + } + + x_context.XNextEvent = dlsym(x11_lib, "XNextEvent"); + if(!x_context.XNextEvent) { + fprintf(stderr, "Warning: dlsym XNextEvent failed\n"); + goto fail; + } + + x_context.XRefreshKeyboardMapping = dlsym(x11_lib, "XRefreshKeyboardMapping"); + if(!x_context.XRefreshKeyboardMapping) { + fprintf(stderr, "Warning: dlsym XRefreshKeyboardMapping failed\n"); + goto fail; + } + + x_context.display = XOpenDisplay(NULL); + if(!x_context.display) { + fprintf(stderr, "Warning: XOpenDisplay failed\n"); + goto fail; + } + + XSetErrorHandler = dlsym(x11_lib, "XSetErrorHandler"); + if(XSetErrorHandler) + XSetErrorHandler(x_ignore_error); + else + fprintf(stderr, "Warning: dlsym XSetErrorHandler failed\n"); + + return x_context; + + fail: + memset(&x_context, 0, sizeof(x_context)); + dlclose(x11_lib); + return x_context; +} + +int main(int argc, char **argv) { + keyboard_grab_type grab_type = KEYBOARD_GRAB_TYPE_ALL; + if(argc == 2) { + const char *grab_type_arg = argv[1]; + if(strcmp(grab_type_arg, "--all") == 0) { + grab_type = KEYBOARD_GRAB_TYPE_ALL; + } else if(strcmp(grab_type_arg, "--virtual") == 0) { + grab_type = KEYBOARD_GRAB_TYPE_VIRTUAL; + } else { + fprintf(stderr, "Error: expected --all or --virtual, got %s\n", grab_type_arg); + usage(); + return 1; + } + } else if(argc != 1) { + fprintf(stderr, "Error: expected 0 or 1 arguments, got %d argument(s)\n", argc); + usage(); + return 1; + } + + x11_context x_context = setup_x11_context(); + const uid_t user_id = getuid(); if(geteuid() != 0) { if(setuid(0) == -1) { @@ -47,7 +146,7 @@ int main(void) { } keyboard_event keyboard_ev; - if(!keyboard_event_init(&keyboard_ev, true, true)) { + if(!keyboard_event_init(&keyboard_ev, true, true, grab_type, x_context)) { fprintf(stderr, "Error: failed to setup hotplugging and no keyboard input devices were found\n"); setuid(user_id); return 1; |