seat_cmd_keyboard_grouping: change keymap to smart

This removes `seat <seat> keyboard_grouping keymap` and replaces it with
`seat <seat> keyboard_grouping smart`. The smart keyboard grouping will
group based on both the keymap and repeat info. The reasoning for this
is that deciding what the repeat info should be for a group is either
arbitrary or non-deterministic when multiple keyboards in the group have
repeat info configured (unless somehow exposed to the user in a
reproducible uniquely identifiable fashion).
This commit is contained in:
Brian Ashworth 2019-12-15 01:33:33 -05:00 committed by Drew DeVault
parent 2b51c5b294
commit 452a615bb8
5 changed files with 45 additions and 28 deletions

View file

@ -177,9 +177,9 @@ enum seat_config_allow_constrain {
};
enum seat_keyboard_grouping {
KEYBOARD_GROUP_DEFAULT, // the default is currently keymap
KEYBOARD_GROUP_DEFAULT, // the default is currently smart
KEYBOARD_GROUP_NONE,
KEYBOARD_GROUP_KEYMAP
KEYBOARD_GROUP_SMART // keymap and repeat info
};
enum sway_input_idle_source {

View file

@ -54,6 +54,9 @@ struct sway_keyboard {
struct xkb_keymap *keymap;
xkb_layout_index_t effective_layout;
int32_t repeat_rate;
int32_t repeat_delay;
struct wl_listener keyboard_key;
struct wl_listener keyboard_modifiers;

View file

@ -15,11 +15,11 @@ struct cmd_results *seat_cmd_keyboard_grouping(int argc, char **argv) {
struct seat_config *seat_config = config->handler_context.seat_config;
if (strcmp(argv[0], "none") == 0) {
seat_config->keyboard_grouping = KEYBOARD_GROUP_NONE;
} else if (strcmp(argv[0], "keymap") == 0) {
seat_config->keyboard_grouping = KEYBOARD_GROUP_KEYMAP;
} else if (strcmp(argv[0], "smart") == 0) {
seat_config->keyboard_grouping = KEYBOARD_GROUP_SMART;
} else {
return cmd_results_new(CMD_INVALID,
"Expected syntax `keyboard_grouping none|keymap`");
"Expected syntax `keyboard_grouping none|smart`");
}
return cmd_results_new(CMD_SUCCESS, NULL);

View file

@ -659,6 +659,11 @@ static bool keymaps_match(struct xkb_keymap *km1, struct xkb_keymap *km2) {
return result;
}
static bool repeat_info_match(struct sway_keyboard *a, struct wlr_keyboard *b) {
return a->repeat_rate == b->repeat_info.rate &&
a->repeat_delay == b->repeat_info.delay;
}
static void destroy_empty_wlr_keyboard_group(void *data) {
wlr_keyboard_group_destroy(data);
}
@ -711,9 +716,10 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) {
sway_keyboard_group_remove(keyboard);
break;
case KEYBOARD_GROUP_DEFAULT: /* fallthrough */
case KEYBOARD_GROUP_KEYMAP:;
case KEYBOARD_GROUP_SMART:;
struct wlr_keyboard_group *group = wlr_keyboard->group;
if (!keymaps_match(keyboard->keymap, group->keyboard.keymap)) {
if (!keymaps_match(keyboard->keymap, group->keyboard.keymap) ||
!repeat_info_match(keyboard, &group->keyboard)) {
sway_keyboard_group_remove(keyboard);
}
break;
@ -741,9 +747,10 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
// Nothing to do. This shouldn't even be reached
return;
case KEYBOARD_GROUP_DEFAULT: /* fallthrough */
case KEYBOARD_GROUP_KEYMAP:;
case KEYBOARD_GROUP_SMART:;
struct wlr_keyboard_group *wlr_group = group->wlr_group;
if (keymaps_match(keyboard->keymap, wlr_group->keyboard.keymap)) {
if (keymaps_match(keyboard->keymap, wlr_group->keyboard.keymap) &&
repeat_info_match(keyboard, &wlr_group->keyboard)) {
sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p",
device->identifier, wlr_group);
wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard);
@ -767,6 +774,8 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
}
sway_group->wlr_group->data = sway_group;
wlr_keyboard_set_keymap(&sway_group->wlr_group->keyboard, keyboard->keymap);
wlr_keyboard_set_repeat_info(&sway_group->wlr_group->keyboard,
keyboard->repeat_rate, keyboard->repeat_delay);
sway_log(SWAY_DEBUG, "Created keyboard group %p", sway_group->wlr_group);
sway_group->seat_device = calloc(1, sizeof(struct sway_seat_device));
@ -836,14 +845,30 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
keyboard->keymap ? !keymaps_match(keyboard->keymap, keymap) : true;
bool effective_layout_changed = keyboard->effective_layout != 0;
if (keymap_changed || config->reloading) {
int repeat_rate = 25;
if (input_config && input_config->repeat_rate != INT_MIN) {
repeat_rate = input_config->repeat_rate;
}
int repeat_delay = 600;
if (input_config && input_config->repeat_delay != INT_MIN) {
repeat_delay = input_config->repeat_delay;
}
bool repeat_info_changed = keyboard->repeat_rate != repeat_rate ||
keyboard->repeat_delay != repeat_delay;
if (keymap_changed || repeat_info_changed || config->reloading) {
xkb_keymap_unref(keyboard->keymap);
keyboard->keymap = keymap;
keyboard->effective_layout = 0;
keyboard->repeat_rate = repeat_rate;
keyboard->repeat_delay = repeat_delay;
sway_keyboard_group_remove_invalid(keyboard);
wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap);
wlr_keyboard_set_repeat_info(wlr_device->keyboard,
keyboard->repeat_rate, keyboard->repeat_delay);
if (!wlr_device->keyboard->group) {
sway_keyboard_group_add(keyboard);
@ -890,17 +915,6 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
}
}
int repeat_rate = 25;
if (input_config && input_config->repeat_rate != INT_MIN) {
repeat_rate = input_config->repeat_rate;
}
int repeat_delay = 600;
if (input_config && input_config->repeat_delay != INT_MIN) {
repeat_delay = input_config->repeat_delay;
}
wlr_keyboard_set_repeat_info(wlr_device->keyboard, repeat_rate,
repeat_delay);
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
wlr_seat_set_keyboard(seat, wlr_device);

View file

@ -230,15 +230,15 @@ correct seat.
"keyboard", "pointer", "touchpad", "touch", "tablet pad", "tablet tool",
and "switch". The default behavior is to wake from idle on any event.
*seat* <name> keyboard_grouping none|keymap
*seat* <name> keyboard_grouping none|smart
Set how the keyboards in the seat are grouped together. Currently, there
are two options. _none_ will disable all keyboard grouping. This will make
it so each keyboard device has its own isolated state. _keymap_ will
group the keyboards in the seat by their keymap. This is useful for when
the keyboard appears as multiple separate input devices. In this mode,
the effective layout and repeat info are also synced between the keyboards
in the group. The default is _keymap_. To restore the behavior of older
versions of sway, use _none_.
it so each keyboard device has its own isolated state. _smart_ will
group the keyboards in the seat by their keymap and repeat info. This is
useful for when the keyboard appears as multiple separate input devices.
In this mode, the effective layout is synced between the keyboards in the
group. The default is _smart_. To restore the behavior of older versions
of sway, use _none_.
*seat* <name> pointer_constraint enable|disable|escape
Enables or disables the ability for clients to capture the cursor (enabled