aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfrsfnrrg <frsfnrrg@users.noreply.github.com>2018-07-29 16:25:43 -0400
committerfrsfnrrg <frsfnrrg@users.noreply.github.com>2018-07-29 19:15:02 -0400
commite33dfbfa758fb899c276135d06f25359ceee0002 (patch)
tree2ac9007d59e001f16c92dd43cb9e961fd043257f
parentca8f177e143de81af3c050e6dc01b7ecebaeea34 (diff)
downloadsway-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.
-rw-r--r--include/sway/input/keyboard.h5
-rw-r--r--sway/input/keyboard.c38
2 files changed, 43 insertions, 0 deletions
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h
index 6713398e..660cdc9c 100644
--- a/include/sway/input/keyboard.h
+++ b/include/sway/input/keyboard.h
@@ -38,6 +38,11 @@ struct sway_keyboard {
struct sway_shortcut_state state_keysyms_raw;
struct sway_shortcut_state state_keycodes;
struct sway_binding *held_binding;
+
+ struct wl_event_source *key_repeat_source;
+ struct sway_binding *repeat_binding;
+ int key_repeat_initial_delay; // first key repeat event delay, in ms
+ int key_repeat_step_delay; // subsequent repeat delay, in ms
};
struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
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);
}