mirror of
https://github.com/swaywm/sway.git
synced 2024-11-23 00:11:28 +00:00
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.
This commit is contained in:
parent
ca8f177e14
commit
e33dfbfa75
|
@ -38,6 +38,11 @@ struct sway_keyboard {
|
||||||
struct sway_shortcut_state state_keysyms_raw;
|
struct sway_shortcut_state state_keysyms_raw;
|
||||||
struct sway_shortcut_state state_keycodes;
|
struct sway_shortcut_state state_keycodes;
|
||||||
struct sway_binding *held_binding;
|
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,
|
struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
|
||||||
|
|
|
@ -264,6 +264,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify and execute active pressed binding
|
// Identify and execute active pressed binding
|
||||||
|
struct sway_binding *next_repeat_binding = NULL;
|
||||||
if (event->state == WLR_KEY_PRESSED) {
|
if (event->state == WLR_KEY_PRESSED) {
|
||||||
struct sway_binding *binding_pressed = NULL;
|
struct sway_binding *binding_pressed = NULL;
|
||||||
get_active_binding(&keyboard->state_keycodes,
|
get_active_binding(&keyboard->state_keycodes,
|
||||||
|
@ -279,6 +280,21 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
|
||||||
if (binding_pressed) {
|
if (binding_pressed) {
|
||||||
seat_execute_command(seat, binding_pressed);
|
seat_execute_command(seat, binding_pressed);
|
||||||
handled = true;
|
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();
|
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,
|
static void handle_keyboard_modifiers(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct sway_keyboard *keyboard =
|
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_key.link);
|
||||||
wl_list_init(&keyboard->keyboard_modifiers.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;
|
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_key.link);
|
||||||
wl_list_remove(&keyboard->keyboard_modifiers.link);
|
wl_list_remove(&keyboard->keyboard_modifiers.link);
|
||||||
|
wl_event_source_remove(keyboard->key_repeat_source);
|
||||||
free(keyboard);
|
free(keyboard);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue