diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gsr-global-hotkeys/keyboard_event.c | 50 | ||||
-rw-r--r-- | tools/gsr-global-hotkeys/keyboard_event.h | 1 |
2 files changed, 43 insertions, 8 deletions
diff --git a/tools/gsr-global-hotkeys/keyboard_event.c b/tools/gsr-global-hotkeys/keyboard_event.c index c2bd75a..e5221dc 100644 --- a/tools/gsr-global-hotkeys/keyboard_event.c +++ b/tools/gsr-global-hotkeys/keyboard_event.c @@ -120,14 +120,13 @@ static void keyboard_event_process_key_state_change(keyboard_event *self, const /* Return true if a global hotkey is assigned to the key combination */ static bool keyboard_event_on_key_pressed(keyboard_event *self, const struct input_event *event, uint32_t modifiers) { - if(event->value != KEYBOARD_BUTTON_PRESSED) - return false; - bool global_hotkey_match = false; for(int i = 0; i < self->num_global_hotkeys; ++i) { if(event->code == self->global_hotkeys[i].key && modifiers == self->global_hotkeys[i].modifiers) { - puts(self->global_hotkeys[i].action); - fflush(stdout); + if(event->value == KEYBOARD_BUTTON_PRESSED) { + puts(self->global_hotkeys[i].action); + fflush(stdout); + } global_hotkey_match = true; } } @@ -155,6 +154,28 @@ static uint32_t keycode_to_modifier_bit(uint32_t keycode) { return 0; } +/* Returns true if the state changed */ +static bool keyboard_event_set_key_presses_grabbed(const struct input_event *event, event_extra_data *extra_data) { + if(event->type != EV_KEY) + return false; + + if(!extra_data->key_presses_grabbed || event->code >= KEY_STATES_SIZE * 8) + return false; + + const unsigned int byte_index = event->code / 8; + const unsigned char bit_index = event->code % 8; + unsigned char key_byte_state = extra_data->key_presses_grabbed[byte_index]; + const bool prev_key_pressed = (key_byte_state & (1 << bit_index)) != KEY_RELEASE; + extra_data->key_presses_grabbed[byte_index] = set_bit(key_byte_state, bit_index, event->value >= 1); + + if(event->value == KEY_PRESS) + return !prev_key_pressed; + else if(event->value == KEY_RELEASE || event->value == KEY_REPEAT) + return prev_key_pressed; + + return false; +} + static void keyboard_event_process_input_event_data(keyboard_event *self, event_extra_data *extra_data, int fd) { struct input_event event; if(read(fd, &event, sizeof(event)) != sizeof(event)) { @@ -176,8 +197,13 @@ static void keyboard_event_process_input_event_data(keyboard_event *self, event_ keyboard_event_process_key_state_change(self, &event, extra_data, fd); const uint32_t modifier_bit = keycode_to_modifier_bit(event.code); if(modifier_bit == 0) { - if(keyboard_event_on_key_pressed(self, &event, self->modifier_button_states)) - return; + if(keyboard_event_on_key_pressed(self, &event, self->modifier_button_states)) { + if(keyboard_event_set_key_presses_grabbed(&event, extra_data)) + return; + } else if(event.value == KEY_RELEASE) { + if(keyboard_event_set_key_presses_grabbed(&event, extra_data)) + return; + } } else { self->modifier_button_states = set_bit(self->modifier_button_states, modifier_bit, event.value >= 1); } @@ -305,7 +331,8 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons const bool supports_wheel_events = key_bits[BTN_WHEEL/8] & (1 << (BTN_WHEEL % 8)); if(supports_key_events && (is_virtual_device || (!supports_joystick_events && !supports_wheel_events))) { unsigned char *key_states = calloc(1, KEY_STATES_SIZE); - if(key_states && self->num_event_polls < MAX_EVENT_POLLS) { + unsigned char *key_presses_grabbed = calloc(1, KEY_STATES_SIZE); + if(key_states && key_presses_grabbed && self->num_event_polls < MAX_EVENT_POLLS) { //fprintf(stderr, "%s (%s) supports key inputs\n", dev_input_filepath, device_name); self->event_polls[self->num_event_polls] = (struct pollfd) { .fd = fd, @@ -317,6 +344,7 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons .dev_input_id = dev_input_id, .grabbed = false, .key_states = key_states, + .key_presses_grabbed = key_presses_grabbed, .num_keys_pressed = 0 }; @@ -335,6 +363,8 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons return true; } else { fprintf(stderr, "Warning: the maximum number of keyboard devices have been registered. The newly added keyboard will be ignored\n"); + free(key_states); + free(key_presses_grabbed); } } } @@ -377,6 +407,7 @@ static void keyboard_event_remove_event(keyboard_event *self, int index) { ioctl(self->event_polls[index].fd, EVIOCGRAB, 0); close(self->event_polls[index].fd); free(self->event_extra_data[index].key_states); + free(self->event_extra_data[index].key_presses_grabbed); for(int i = index + 1; i < self->num_event_polls; ++i) { self->event_polls[i - 1] = self->event_polls[i]; @@ -481,6 +512,7 @@ bool keyboard_event_init(keyboard_event *self, bool exclusive_grab, keyboard_gra .dev_input_id = -1, .grabbed = false, .key_states = NULL, + .key_presses_grabbed = NULL, .num_keys_pressed = 0 }; @@ -498,6 +530,7 @@ bool keyboard_event_init(keyboard_event *self, bool exclusive_grab, keyboard_gra .dev_input_id = -1, .grabbed = false, .key_states = NULL, + .key_presses_grabbed = NULL, .num_keys_pressed = 0 }; @@ -536,6 +569,7 @@ void keyboard_event_deinit(keyboard_event *self) { ioctl(self->event_polls[i].fd, EVIOCGRAB, 0); close(self->event_polls[i].fd); free(self->event_extra_data[i].key_states); + free(self->event_extra_data[i].key_presses_grabbed); } self->num_event_polls = 0; diff --git a/tools/gsr-global-hotkeys/keyboard_event.h b/tools/gsr-global-hotkeys/keyboard_event.h index a86b3dd..720aaa1 100644 --- a/tools/gsr-global-hotkeys/keyboard_event.h +++ b/tools/gsr-global-hotkeys/keyboard_event.h @@ -40,6 +40,7 @@ typedef struct { int dev_input_id; bool grabbed; unsigned char *key_states; + unsigned char *key_presses_grabbed; int num_keys_pressed; } event_extra_data; |