From a933b4efed98f60c882afc2294cf2492b732164e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Mon, 3 Jan 2022 22:24:06 -0500 Subject: [PATCH] input: Fix next/prev layout switch for grouped devices Input devices in a seat can be grouped so that configuration changes on one device, like the active layout, are automatically propagated to the other devices. The current logic for xkb_switch_layout wasn't accounting for this, however. It was looping through all input devices and changing the layout for each one, causing grouped devices to have their layouts changed multiple times. This wasn't noticed when setting the layout to a fixed index, but caused the wrong layout to be selected when using the 'next' and 'prev' keywords. In order to fix this issue, loop over each seat and, if the input devices in the seat are grouped, change the layout only for the first device in the seat. --- sway/commands/input/xkb_switch_layout.c | 39 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/sway/commands/input/xkb_switch_layout.c b/sway/commands/input/xkb_switch_layout.c index d6548a681..fa1447671 100644 --- a/sway/commands/input/xkb_switch_layout.c +++ b/sway/commands/input/xkb_switch_layout.c @@ -3,6 +3,7 @@ #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" +#include "sway/input/seat.h" #include "log.h" static void switch_layout(struct wlr_keyboard *kbd, xkb_layout_index_t idx) { @@ -66,20 +67,30 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) { relative = 0; } - struct sway_input_device *dev; - wl_list_for_each(dev, &server.input->devices, link) { - if (strcmp(ic->identifier, "*") != 0 && - strcmp(ic->identifier, "type:keyboard") != 0 && - strcmp(ic->identifier, dev->identifier) != 0) { - continue; - } - if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { - continue; - } - if (relative) { - switch_layout_relative(dev->wlr_device->keyboard, relative); - } else { - switch_layout(dev->wlr_device->keyboard, layout); + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + struct sway_seat_device *seat_dev; + struct sway_input_device *dev; + wl_list_for_each(seat_dev, &seat->devices, link) { + dev = seat_dev->input_device; + if (strcmp(ic->identifier, "*") != 0 && + strcmp(ic->identifier, "type:keyboard") != 0 && + strcmp(ic->identifier, dev->identifier) != 0) { + continue; + } + if (dev->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { + continue; + } + if (relative) { + switch_layout_relative(dev->wlr_device->keyboard, relative); + } else { + switch_layout(dev->wlr_device->keyboard, layout); + } + // If input devices in this seat are grouped, skip the + // other devices since the layout change will already be + // propagated automatically. + if (dev->wlr_device->keyboard->group) + break; } }