diff options
author | frsfnrrg <frsfnrrg@users.noreply.github.com> | 2018-07-29 16:25:43 -0400 |
---|---|---|
committer | frsfnrrg <frsfnrrg@users.noreply.github.com> | 2018-07-29 19:15:02 -0400 |
commit | e33dfbfa758fb899c276135d06f25359ceee0002 (patch) | |
tree | 2ac9007d59e001f16c92dd43cb9e961fd043257f /sway | |
parent | ca8f177e143de81af3c050e6dc01b7ecebaeea34 (diff) | |
download | sway-e33dfbfa758fb899c276135d06f25359ceee0002.tar.xz |
Implement key repeat for pressed key bindings
Each sway_keyboard is provided with a wayland timer event source.
When a valid keypress binding has been found, a callback to
handle_keyboard_repeat is set. Any key event will either clear
the callback or (if the new key event is a valid keypress binding)
delay the callback again.
Diffstat (limited to 'sway')
-rw-r--r-- | sway/input/keyboard.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 8dc8239c..be000fb9 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -264,6 +264,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { } // Identify and execute active pressed binding + struct sway_binding *next_repeat_binding = NULL; if (event->state == WLR_KEY_PRESSED) { struct sway_binding *binding_pressed = NULL; get_active_binding(&keyboard->state_keycodes, @@ -279,6 +280,21 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { if (binding_pressed) { seat_execute_command(seat, binding_pressed); handled = true; + next_repeat_binding = binding_pressed; + } + } + + // Set up (or clear) keyboard repeat for a pressed binding + if (next_repeat_binding) { + keyboard->repeat_binding = next_repeat_binding; + if (wl_event_source_timer_update(keyboard->key_repeat_source, + keyboard->key_repeat_initial_delay) < 0) { + wlr_log(WLR_DEBUG, "failed to set key repeat timer"); + } + } else if (keyboard->repeat_binding) { + keyboard->repeat_binding = NULL; + if (wl_event_source_timer_update(keyboard->key_repeat_source, 0) < 0) { + wlr_log(WLR_DEBUG, "failed to disarm key repeat timer"); } } @@ -303,6 +319,22 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { transaction_commit_dirty(); } +static int handle_keyboard_repeat(void *data) { + struct sway_keyboard *keyboard = (struct sway_keyboard *)data; + if (keyboard->repeat_binding) { + // We queue the next event first, as the command might cancel it + if (wl_event_source_timer_update(keyboard->key_repeat_source, + keyboard->key_repeat_step_delay) < 0) { + wlr_log(WLR_DEBUG, "failed to update key repeat timer"); + } + + seat_execute_command(keyboard->seat_device->sway_seat, + keyboard->repeat_binding); + transaction_commit_dirty(); + } + return 0; +} + static void handle_keyboard_modifiers(struct wl_listener *listener, void *data) { struct sway_keyboard *keyboard = @@ -328,6 +360,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, wl_list_init(&keyboard->keyboard_key.link); wl_list_init(&keyboard->keyboard_modifiers.link); + keyboard->key_repeat_source = wl_event_loop_add_timer(server.wl_event_loop, + handle_keyboard_repeat, keyboard); + keyboard->key_repeat_initial_delay = 660; + keyboard->key_repeat_step_delay = 40; + return keyboard; } @@ -441,5 +478,6 @@ void sway_keyboard_destroy(struct sway_keyboard *keyboard) { } wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_modifiers.link); + wl_event_source_remove(keyboard->key_repeat_source); free(keyboard); } |