keyboard: allow applying keyboard layout per window

Fixes #1076

It can be enabled with a config like

~/.config/labwc/rc.xml:
<keyboard layoutScope="window">

~/.config/labwc/environment:
XKB_DEFAULT_LAYOUT=de,us
XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,grp_led:scroll

With a configuration like this each window should now remember
the active keyboard layout when switching between windows.

By default, the keyboard layout keeps being a global state.
This commit is contained in:
Consolatis 2023-09-07 16:41:47 +02:00 committed by Johan Malm
parent f1c2664ad1
commit 984aeb0b0b
9 changed files with 66 additions and 3 deletions

View file

@ -735,6 +735,12 @@ entry(xmlNode *node, char *nodename, char *content)
rc.repeat_delay = atoi(content);
} else if (!strcasecmp(nodename, "numlock.keyboard")) {
set_bool(content, &rc.kb_numlock_enable);
} else if (!strcasecmp(nodename, "layoutScope.keyboard")) {
/*
* This can be changed to an enum later on
* if we decide to also support "application".
*/
rc.kb_layout_per_window = !strcasecmp(content, "window");
} else if (!strcasecmp(nodename, "screenEdgeStrength.resistance")) {
rc.screen_edge_strength = atoi(content);
} else if (!strcasecmp(nodename, "range.snapping")) {
@ -953,6 +959,7 @@ rcxml_init(void)
rc.repeat_rate = 25;
rc.repeat_delay = 600;
rc.kb_numlock_enable = true;
rc.kb_layout_per_window = false;
rc.screen_edge_strength = 20;
rc.snap_edge_range = 1;

View file

@ -84,6 +84,7 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
}
}
}
wlr_seat_set_keyboard(seat->seat, wlr_keyboard);
wlr_seat_keyboard_notify_modifiers(seat->seat, &wlr_keyboard->modifiers);
}
@ -485,7 +486,6 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
struct seat *seat = keyboard->base.seat;
struct wlr_keyboard_key_event *event = data;
struct wlr_seat *wlr_seat = seat->seat;
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
idle_manager_notify_activity(seat->seat);
/* any new press/release cancels current keybind repeat */
@ -497,7 +497,7 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
start_keybind_repeat(seat->server, keyboard, event);
}
} else {
wlr_seat_set_keyboard(wlr_seat, wlr_keyboard);
wlr_seat_set_keyboard(wlr_seat, keyboard->wlr_keyboard);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
event->keycode, event->state);
}
@ -530,6 +530,41 @@ keyboard_set_numlock(struct wlr_keyboard *keyboard)
keyboard->modifiers.latched, locked, keyboard->modifiers.group);
}
void
keyboard_update_layout(struct seat *seat, xkb_layout_index_t layout)
{
assert(seat);
struct input *input;
struct keyboard *keyboard;
struct wlr_keyboard *kb = NULL;
/* We are not using wlr_seat_get_keyboard() here because it might be a virtual one */
wl_list_for_each(input, &seat->inputs, link) {
if (input->wlr_input_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
continue;
}
keyboard = (struct keyboard *)input;
if (keyboard->is_virtual) {
continue;
}
kb = keyboard->wlr_keyboard;
break;
}
if (!kb) {
wlr_log(WLR_INFO, "Restoring kb layout failed: no physical keyboard found");
return;
}
if (kb->modifiers.group == layout) {
return;
}
/* By updating a member of the keyboard group, all members of the group will get updated */
wlr_log(WLR_DEBUG, "Updating group layout to %u", layout);
wlr_keyboard_notify_modifiers(kb, kb->modifiers.depressed,
kb->modifiers.latched, kb->modifiers.locked, layout);
}
void
keyboard_init(struct seat *seat)
{

View file

@ -6,6 +6,7 @@
#include "common/match.h"
#include "common/mem.h"
#include "common/scene-helpers.h"
#include "input/keyboard.h"
#include "labwc.h"
#include "menu/menu.h"
#include "regions.h"
@ -266,6 +267,17 @@ view_set_activated(struct view *view, bool activated)
wlr_foreign_toplevel_handle_v1_set_activated(
view->toplevel.handle, activated);
}
if (rc.kb_layout_per_window) {
if (!activated) {
/* Store configured keyboard layout per view */
view->keyboard_layout =
view->server->seat.keyboard_group->keyboard.modifiers.group;
} else {
/* Switch to previously stored keyboard layout */
keyboard_update_layout(&view->server->seat, view->keyboard_layout);
}
}
}
void