From e1b268af98edeb09e570e8855ef64f0719cbafe2 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 4 Dec 2022 01:20:06 +0100 Subject: [PATCH] seat: Avoid sending redundant keymaps on reload When we reload the config, we reset every input device and re-apply configuration from the config file. This means that the keyboard keymap is updated at least once during config reload, more if the config file contains keyboard configuration. When they keyboard keymap changes and is updated through wlr_seat, the keymap ends up sent to every keyboard bound in every client, seemingly multiple times. On an x230 of mine with a keyboard layout set in the config file, I see 42 keymap events sent to foot on config reload. Reduce events from keyboard configurations by skipping all but the currently active keyboard for the seat, and by clearing the active keyboard during input manager device reset. After this change, I only see a single just-in-time keymap event. Fixes: https://github.com/swaywm/sway/issues/6654 --- sway/input/input-manager.c | 8 +++++++- sway/input/keyboard.c | 3 --- sway/input/seat.c | 11 +++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 634d8981..ea2cc038 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -593,6 +593,13 @@ void input_manager_reset_input(struct sway_input_device *input_device) { } void input_manager_reset_all_inputs(void) { + // Set the active keyboard to NULL to avoid spamming configuration updates + // for all keyboard devices. + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + wlr_seat_set_keyboard(seat->wlr_seat, NULL); + } + struct sway_input_device *input_device = NULL; wl_list_for_each(input_device, &server.input->devices, link) { input_manager_reset_input(input_device); @@ -601,7 +608,6 @@ void input_manager_reset_all_inputs(void) { // If there is at least one keyboard using the default keymap, repeat delay, // and repeat rate, then it is possible that there is a keyboard group that // need their keyboard disarmed. - struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { struct sway_keyboard_group *group; wl_list_for_each(group, &seat->keyboard_groups, link) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 2ac02b22..96d5b72d 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -1070,9 +1070,6 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { } } - struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; - wlr_seat_set_keyboard(seat, keyboard->wlr); - wl_list_remove(&keyboard->keyboard_key.link); wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key); keyboard->keyboard_key.notify = handle_keyboard_key; diff --git a/sway/input/seat.c b/sway/input/seat.c index 4919bed0..151303a9 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -823,8 +823,15 @@ static void seat_configure_keyboard(struct sway_seat *seat, sway_keyboard_create(seat, seat_device); } sway_keyboard_configure(seat_device->keyboard); - wlr_seat_set_keyboard(seat->wlr_seat, - wlr_keyboard_from_input_device(seat_device->input_device->wlr_device)); + + // We only need to update the current keyboard, as the rest will be updated + // as they are activated. + struct wlr_keyboard *wlr_keyboard = + wlr_keyboard_from_input_device(seat_device->input_device->wlr_device); + struct wlr_keyboard *current_keyboard = seat->wlr_seat->keyboard_state.keyboard; + if (wlr_keyboard != current_keyboard) { + return; + } // force notify reenter to pick up the new configuration. This reuses // the current focused surface to avoid breaking input grabs.