mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-05-06 06:50:44 +09:00
Prevent focused application from receiving global hotkey keys on wayland as well (massive hack)
This commit is contained in:
@@ -46,5 +46,4 @@ If you want to donate you can donate via bitcoin or monero.
|
|||||||
|
|
||||||
# Known issues
|
# Known issues
|
||||||
* Some games receive mouse input while the UI is open
|
* Some games receive mouse input while the UI is open
|
||||||
* Global hotkeys on Wayland can clash with keys used by other applications. This is primarly because Wayland compositors are missing support for global hotkey so this software uses a global hotkey system that works on all Wayland compositors.
|
|
||||||
* When the UI is open the wallpaper is shown instead of the game on Hyprland and Sway. This is an issue with Hyprland and Sway. It cant be fixed until the UI is redesigned to not be a fullscreen overlay.
|
* When the UI is open the wallpaper is shown instead of the game on Hyprland and Sway. This is an issue with Hyprland and Sway. It cant be fixed until the UI is redesigned to not be a fullscreen overlay.
|
||||||
|
|||||||
2
TODO
2
TODO
@@ -106,3 +106,5 @@ When support for window capture is enabled on x11 then make sure to not save the
|
|||||||
Support CJK.
|
Support CJK.
|
||||||
|
|
||||||
Move ui hover code from ::draw to ::on_event, to properly handle widget event stack.
|
Move ui hover code from ::draw to ::on_event, to properly handle widget event stack.
|
||||||
|
|
||||||
|
Save audio devices by name instead of id. This is more robust since audio id can change(?).
|
||||||
|
|||||||
22
src/main.cpp
22
src/main.cpp
@@ -203,17 +203,17 @@ int main(void) {
|
|||||||
auto overlay = std::make_unique<gsr::Overlay>(resources_path, std::move(gsr_info), std::move(capture_options), egl_funcs);
|
auto overlay = std::make_unique<gsr::Overlay>(resources_path, std::move(gsr_info), std::move(capture_options), egl_funcs);
|
||||||
//overlay.show();
|
//overlay.show();
|
||||||
|
|
||||||
std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = nullptr;
|
// std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = nullptr;
|
||||||
if(display_server == gsr::DisplayServer::X11) {
|
// if(display_server == gsr::DisplayServer::X11) {
|
||||||
global_hotkeys = register_x11_hotkeys(overlay.get());
|
// global_hotkeys = register_x11_hotkeys(overlay.get());
|
||||||
if(!global_hotkeys) {
|
// if(!global_hotkeys) {
|
||||||
fprintf(stderr, "Info: failed to register some x11 hotkeys because they are registered by another program. Will use linux hotkeys instead that can clash with keys used by other applications\n");
|
// fprintf(stderr, "Info: failed to register some x11 hotkeys because they are registered by another program. Will use linux hotkeys instead\n");
|
||||||
global_hotkeys = register_linux_hotkeys(overlay.get());
|
// global_hotkeys = register_linux_hotkeys(overlay.get());
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
fprintf(stderr, "Info: Global linux hotkeys are used which can clash with keys used by other applications. Use X11 instead if this is an issue for you\n");
|
// global_hotkeys = register_linux_hotkeys(overlay.get());
|
||||||
global_hotkeys = register_linux_hotkeys(overlay.get());
|
// }
|
||||||
}
|
std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = register_linux_hotkeys(overlay.get());
|
||||||
|
|
||||||
// TODO: Add hotkeys in Overlay when using x11 global hotkeys. The hotkeys in Overlay should duplicate each key that is used for x11 global hotkeys.
|
// TODO: Add hotkeys in Overlay when using x11 global hotkeys. The hotkeys in Overlay should duplicate each key that is used for x11 global hotkeys.
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ bool hotplug_event_init(hotplug_event *self) {
|
|||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return false; /* Not root user */
|
return false; /* Not root user */
|
||||||
|
|
||||||
if(bind(fd, (void *)&nls, sizeof(struct sockaddr_nl))) {
|
if(bind(fd, (void*)&nls, sizeof(struct sockaddr_nl))) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
|
|
||||||
/* LINUX */
|
/* LINUX */
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
|
||||||
|
#define GSR_UI_VIRTUAL_KEYBOARD_NAME "gsr-ui virtual keyboard"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We could get initial keyboard state with:
|
We could get initial keyboard state with:
|
||||||
@@ -21,7 +24,11 @@
|
|||||||
ioctl(fd, EVIOCGKEY(sizeof(key_states)), key_states), but ignore that for now
|
ioctl(fd, EVIOCGKEY(sizeof(key_states)), key_states), but ignore that for now
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void keyboard_event_process_input_event_data(keyboard_event *self, int fd, key_callback callback, void *userdata) {
|
static bool keyboard_event_has_exclusive_grab(const keyboard_event *self) {
|
||||||
|
return self->uinput_fd > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_event_process_input_event_data(keyboard_event *self, const event_extra_data *extra_data, int fd, key_callback callback, void *userdata) {
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
if(read(fd, &event, sizeof(event)) != sizeof(event)) {
|
if(read(fd, &event, sizeof(event)) != sizeof(event)) {
|
||||||
fprintf(stderr, "Error: failed to read input event data\n");
|
fprintf(stderr, "Error: failed to read input event data\n");
|
||||||
@@ -76,11 +83,19 @@ static void keyboard_event_process_input_event_data(keyboard_event *self, int fd
|
|||||||
if(meta_pressed)
|
if(meta_pressed)
|
||||||
modifiers |= KEYBOARD_MODKEY_SUPER;
|
modifiers |= KEYBOARD_MODKEY_SUPER;
|
||||||
|
|
||||||
callback(event.code, modifiers, event.value, userdata);
|
if(!callback(event.code, modifiers, event.value, userdata))
|
||||||
|
return;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(keyboard_event_has_exclusive_grab(self) && extra_data->grabbed) {
|
||||||
|
/* TODO: Error check? */
|
||||||
|
if(write(self->uinput_fd, &event, sizeof(event)) != sizeof(event))
|
||||||
|
fprintf(stderr, "Error: failed to write event data to virtual keyboard for exclusively grabbed device\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns -1 if invalid format. Expected |dev_input_filepath| to be in format /dev/input/eventN */
|
/* Returns -1 if invalid format. Expected |dev_input_filepath| to be in format /dev/input/eventN */
|
||||||
@@ -96,7 +111,7 @@ static int get_dev_input_id_from_filepath(const char *dev_input_filepath) {
|
|||||||
|
|
||||||
static bool keyboard_event_has_event_with_dev_input_fd(keyboard_event *self, int dev_input_id) {
|
static bool keyboard_event_has_event_with_dev_input_fd(keyboard_event *self, int dev_input_id) {
|
||||||
for(int i = 0; i < self->num_event_polls; ++i) {
|
for(int i = 0; i < self->num_event_polls; ++i) {
|
||||||
if(self->dev_input_ids[i] == dev_input_id)
|
if(self->event_extra_data[i].dev_input_id == dev_input_id)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -120,7 +135,7 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons
|
|||||||
|
|
||||||
unsigned long evbit = 0;
|
unsigned long evbit = 0;
|
||||||
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
|
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
|
||||||
if(evbit & (1 << EV_KEY)) {
|
if(strcmp(device_name, GSR_UI_VIRTUAL_KEYBOARD_NAME) != 0 && (evbit & (1 << EV_KEY))) {
|
||||||
unsigned char key_bits[KEY_MAX/8 + 1] = {0};
|
unsigned char key_bits[KEY_MAX/8 + 1] = {0};
|
||||||
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits);
|
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits);
|
||||||
|
|
||||||
@@ -129,13 +144,24 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons
|
|||||||
const bool supports_key_events = key_bits[key_test/8] & (1 << (key_test % 8));
|
const bool supports_key_events = key_bits[key_test/8] & (1 << (key_test % 8));
|
||||||
if(supports_key_events) {
|
if(supports_key_events) {
|
||||||
if(self->num_event_polls < MAX_EVENT_POLLS) {
|
if(self->num_event_polls < MAX_EVENT_POLLS) {
|
||||||
|
bool grabbed = false;
|
||||||
|
if(keyboard_event_has_exclusive_grab(self)) {
|
||||||
|
grabbed = ioctl(fd, EVIOCGRAB, 1) != -1;
|
||||||
|
if(!grabbed)
|
||||||
|
fprintf(stderr, "Warning: failed to exclusively grab device %s. The focused application may receive keys used for global hotkeys\n", device_name);
|
||||||
|
}
|
||||||
|
|
||||||
//fprintf(stderr, "%s (%s) supports key inputs\n", dev_input_filepath, device_name);
|
//fprintf(stderr, "%s (%s) supports key inputs\n", dev_input_filepath, device_name);
|
||||||
self->event_polls[self->num_event_polls] = (struct pollfd) {
|
self->event_polls[self->num_event_polls] = (struct pollfd) {
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
.revents = 0
|
.revents = 0
|
||||||
};
|
};
|
||||||
self->dev_input_ids[self->num_event_polls] = dev_input_id;
|
|
||||||
|
self->event_extra_data[self->num_event_polls] = (event_extra_data) {
|
||||||
|
.dev_input_id = dev_input_id,
|
||||||
|
.grabbed = grabbed
|
||||||
|
};
|
||||||
|
|
||||||
++self->num_event_polls;
|
++self->num_event_polls;
|
||||||
return true;
|
return true;
|
||||||
@@ -180,23 +206,79 @@ static void keyboard_event_remove_event(keyboard_event *self, int index) {
|
|||||||
close(self->event_polls[index].fd);
|
close(self->event_polls[index].fd);
|
||||||
for(int j = index + 1; j < self->num_event_polls; ++j) {
|
for(int j = index + 1; j < self->num_event_polls; ++j) {
|
||||||
self->event_polls[j - 1] = self->event_polls[j];
|
self->event_polls[j - 1] = self->event_polls[j];
|
||||||
self->dev_input_ids[j - 1] = self->dev_input_ids[j];
|
self->event_extra_data[j - 1] = self->event_extra_data[j];
|
||||||
}
|
}
|
||||||
--self->num_event_polls;
|
--self->num_event_polls;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error) {
|
/* Returns the fd to the uinput */
|
||||||
|
static int setup_virtual_keyboard_input(const char *name) {
|
||||||
|
/* TODO: O_NONBLOCK? */
|
||||||
|
int fd = open("/dev/uinput", O_WRONLY);
|
||||||
|
if(fd == -1) {
|
||||||
|
fd = open("/dev/input/uinput", O_WRONLY);
|
||||||
|
if(fd == -1) {
|
||||||
|
fprintf(stderr, "Warning: failed to setup virtual device for exclusive grab (failed to open /dev/uinput or /dev/input/uinput), error: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
success &= (ioctl(fd, UI_SET_EVBIT, EV_KEY) != -1);
|
||||||
|
for(int i = 1; i < KEY_MAX; ++i) {
|
||||||
|
success &= (ioctl(fd, UI_SET_KEYBIT, i) != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ui_version = 0;
|
||||||
|
success &= (ioctl(fd, UI_GET_VERSION, &ui_version) != -1);
|
||||||
|
|
||||||
|
if(ui_version >= 5) {
|
||||||
|
struct uinput_setup usetup;
|
||||||
|
memset(&usetup, 0, sizeof(usetup));
|
||||||
|
usetup.id.bustype = BUS_USB;
|
||||||
|
usetup.id.vendor = 0xdec0;
|
||||||
|
usetup.id.product = 0x5eba;
|
||||||
|
snprintf(usetup.name, sizeof(usetup.name), "%s", name);
|
||||||
|
success &= (ioctl(fd, UI_DEV_SETUP, &usetup) != -1);
|
||||||
|
} else {
|
||||||
|
struct uinput_user_dev uud;
|
||||||
|
memset(&uud, 0, sizeof(uud));
|
||||||
|
snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "%s", name);
|
||||||
|
if(write(fd, &uud, sizeof(uud)) != sizeof(uud))
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
success &= (ioctl(fd, UI_DEV_CREATE) != -1);
|
||||||
|
if(!success) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab) {
|
||||||
memset(self, 0, sizeof(*self));
|
memset(self, 0, sizeof(*self));
|
||||||
self->stdout_event_index = -1;
|
self->stdout_event_index = -1;
|
||||||
self->hotplug_event_index = -1;
|
self->hotplug_event_index = -1;
|
||||||
|
|
||||||
|
if(exclusive_grab) {
|
||||||
|
// TODO: If this fails, try /dev/input/uinput instead
|
||||||
|
self->uinput_fd = setup_virtual_keyboard_input(GSR_UI_VIRTUAL_KEYBOARD_NAME);
|
||||||
|
if(self->uinput_fd <= 0)
|
||||||
|
fprintf(stderr, "Warning: failed to setup virtual keyboard input for exclusive grab. The focused application will receive keys used for global hotkeys\n");
|
||||||
|
}
|
||||||
|
|
||||||
if(poll_stdout_error) {
|
if(poll_stdout_error) {
|
||||||
self->event_polls[self->num_event_polls] = (struct pollfd) {
|
self->event_polls[self->num_event_polls] = (struct pollfd) {
|
||||||
.fd = STDOUT_FILENO,
|
.fd = STDOUT_FILENO,
|
||||||
.events = 0,
|
.events = 0,
|
||||||
.revents = 0
|
.revents = 0
|
||||||
};
|
};
|
||||||
self->dev_input_ids[self->num_event_polls] = -1;
|
self->event_extra_data[self->num_event_polls] = (event_extra_data) {
|
||||||
|
.dev_input_id = -1,
|
||||||
|
.grabbed = false
|
||||||
|
};
|
||||||
|
|
||||||
self->stdout_event_index = self->num_event_polls;
|
self->stdout_event_index = self->num_event_polls;
|
||||||
++self->num_event_polls;
|
++self->num_event_polls;
|
||||||
@@ -208,7 +290,10 @@ bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error) {
|
|||||||
.events = POLLIN,
|
.events = POLLIN,
|
||||||
.revents = 0
|
.revents = 0
|
||||||
};
|
};
|
||||||
self->dev_input_ids[self->num_event_polls] = -1;
|
self->event_extra_data[self->num_event_polls] = (event_extra_data) {
|
||||||
|
.dev_input_id = -1,
|
||||||
|
.grabbed = false
|
||||||
|
};
|
||||||
|
|
||||||
self->hotplug_event_index = self->num_event_polls;
|
self->hotplug_event_index = self->num_event_polls;
|
||||||
++self->num_event_polls;
|
++self->num_event_polls;
|
||||||
@@ -228,6 +313,11 @@ bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_event_deinit(keyboard_event *self) {
|
void keyboard_event_deinit(keyboard_event *self) {
|
||||||
|
if(self->uinput_fd > 0) {
|
||||||
|
close(self->uinput_fd);
|
||||||
|
self->uinput_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < self->num_event_polls; ++i) {
|
for(int i = 0; i < self->num_event_polls; ++i) {
|
||||||
close(self->event_polls[i].fd);
|
close(self->event_polls[i].fd);
|
||||||
}
|
}
|
||||||
@@ -264,10 +354,10 @@ void keyboard_event_poll_events(keyboard_event *self, int timeout_milliseconds,
|
|||||||
/* Device is added to end of |event_polls| so it's ok to add while iterating it via index */
|
/* Device is added to end of |event_polls| so it's ok to add while iterating it via index */
|
||||||
hotplug_event_process_event_data(&self->hotplug_ev, self->event_polls[i].fd, on_device_added_callback, self);
|
hotplug_event_process_event_data(&self->hotplug_ev, self->event_polls[i].fd, on_device_added_callback, self);
|
||||||
else
|
else
|
||||||
keyboard_event_process_input_event_data(self, self->event_polls[i].fd, callback, userdata);
|
keyboard_event_process_input_event_data(self, &self->event_extra_data[i], self->event_polls[i].fd, callback, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyboard_event_stdout_has_failed(keyboard_event *self) {
|
bool keyboard_event_stdout_has_failed(const keyboard_event *self) {
|
||||||
return self->stdout_failed;
|
return self->stdout_failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,18 @@ typedef enum {
|
|||||||
} keyboard_button_state;
|
} keyboard_button_state;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct pollfd event_polls[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
int dev_input_id;
|
||||||
int dev_input_ids[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
bool grabbed;
|
||||||
|
} event_extra_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct pollfd event_polls[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
||||||
|
event_extra_data event_extra_data[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
||||||
int num_event_polls;
|
int num_event_polls;
|
||||||
|
|
||||||
int stdout_event_index;
|
int stdout_event_index;
|
||||||
int hotplug_event_index;
|
int hotplug_event_index;
|
||||||
|
int uinput_fd;
|
||||||
bool stdout_failed;
|
bool stdout_failed;
|
||||||
|
|
||||||
hotplug_event hotplug_ev;
|
hotplug_event hotplug_ev;
|
||||||
@@ -51,13 +57,14 @@ typedef struct {
|
|||||||
} keyboard_event;
|
} keyboard_event;
|
||||||
|
|
||||||
/* |key| is a KEY_ from linux/input-event-codes.h. |modifiers| is a bitmask of keyboard_modkeys. |press_status| is 0 for released, 1 for pressed and 2 for repeat */
|
/* |key| is a KEY_ from linux/input-event-codes.h. |modifiers| is a bitmask of keyboard_modkeys. |press_status| is 0 for released, 1 for pressed and 2 for repeat */
|
||||||
typedef void (*key_callback)(uint32_t key, uint32_t modifiers, int press_status, void *userdata);
|
/* Return true to allow other applications to receive the key input (when using exclusive grab) */
|
||||||
|
typedef bool (*key_callback)(uint32_t key, uint32_t modifiers, int press_status, void *userdata);
|
||||||
|
|
||||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error);
|
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab);
|
||||||
void keyboard_event_deinit(keyboard_event *self);
|
void keyboard_event_deinit(keyboard_event *self);
|
||||||
|
|
||||||
/* If |timeout_milliseconds| is -1 then wait until an event is received */
|
/* If |timeout_milliseconds| is -1 then wait until an event is received */
|
||||||
void keyboard_event_poll_events(keyboard_event *self, int timeout_milliseconds, key_callback callback, void *userdata);
|
void keyboard_event_poll_events(keyboard_event *self, int timeout_milliseconds, key_callback callback, void *userdata);
|
||||||
bool keyboard_event_stdout_has_failed(keyboard_event *self);
|
bool keyboard_event_stdout_has_failed(const keyboard_event *self);
|
||||||
|
|
||||||
#endif /* KEYBOARD_EVENT_H */
|
#endif /* KEYBOARD_EVENT_H */
|
||||||
|
|||||||
@@ -23,43 +23,46 @@ static global_hotkey global_hotkeys[NUM_GLOBAL_HOTKEYS] = {
|
|||||||
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT, .action = "replay_save" }
|
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT, .action = "replay_save" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void on_key_callback(uint32_t key, uint32_t modifiers, int press_status, void *userdata) {
|
static bool on_key_callback(uint32_t key, uint32_t modifiers, int press_status, void *userdata) {
|
||||||
(void)userdata;
|
(void)userdata;
|
||||||
if(press_status != 1) /* 1 == Pressed */
|
if(press_status != 1) /* 1 == Pressed */
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
for(int i = 0; i < NUM_GLOBAL_HOTKEYS; ++i) {
|
for(int i = 0; i < NUM_GLOBAL_HOTKEYS; ++i) {
|
||||||
if(key == global_hotkeys[i].key && modifiers == global_hotkeys[i].modifiers) {
|
if(key == global_hotkeys[i].key && modifiers == global_hotkeys[i].modifiers) {
|
||||||
puts(global_hotkeys[i].action);
|
puts(global_hotkeys[i].action);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
const uid_t user_id = getuid();
|
const uid_t user_id = getuid();
|
||||||
if(geteuid() != 0) {
|
if(geteuid() != 0) {
|
||||||
if(setuid(0) == -1) {
|
if(setuid(0) == -1) {
|
||||||
fprintf(stderr, "error: failed to change user to root\n");
|
fprintf(stderr, "Error: failed to change user to root\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard_event keyboard_ev;
|
keyboard_event keyboard_ev;
|
||||||
if(!keyboard_event_init(&keyboard_ev, true)) {
|
if(!keyboard_event_init(&keyboard_ev, true, true)) {
|
||||||
fprintf(stderr, "Error: failed to setup hotplugging and no keyboard input devices were found\n");
|
fprintf(stderr, "Error: failed to setup hotplugging and no keyboard input devices were found\n");
|
||||||
setuid(user_id);
|
setuid(user_id);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Info: global hotkeys setup, waiting for hotkeys to be pressed\n");
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
keyboard_event_poll_events(&keyboard_ev, -1, on_key_callback, NULL);
|
keyboard_event_poll_events(&keyboard_ev, -1, on_key_callback, NULL);
|
||||||
if(keyboard_event_stdout_has_failed(&keyboard_ev)) {
|
if(keyboard_event_stdout_has_failed(&keyboard_ev)) {
|
||||||
fprintf(stderr, "Info: stdout closed (parent process likely closed this process), exiting...\n");
|
fprintf(stderr, "Info: stdout closed (parent process likely closed this process), exiting...\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard_event_deinit(&keyboard_ev);
|
keyboard_event_deinit(&keyboard_ev);
|
||||||
|
|||||||
Reference in New Issue
Block a user