From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Thu, 7 Sep 2023 14:41:47 +0000 (+0200) Subject: keyboard: allow applying keyboard layout per window X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=984aeb0;p=proto%2Flabwc.git keyboard: allow applying keyboard layout per window Fixes #1076 It can be enabled with a config like ~/.config/labwc/rc.xml: ~/.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. --- diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index df23dd12..f258aa18 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -283,6 +283,10 @@ windows using the mouse. When recognizing a new keyboard enable or disable Num Lock. Default is on. +** [global|window] + Stores the keyboard layout either globally or per window and restores + it when switching back to the window. Default is global. + ** Define a *key* binding in the format *modifier-key*, where supported modifiers are: diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 973a9701..5b323371 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -142,6 +142,7 @@ --> on + global 25 600 diff --git a/include/config/rcxml.h b/include/config/rcxml.h index b3ef127f..ed87a91f 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -63,6 +63,7 @@ struct rcxml { int repeat_rate; int repeat_delay; bool kb_numlock_enable; + bool kb_layout_per_window; struct wl_list keybinds; /* struct keybind.link */ /* mouse */ diff --git a/include/input/keyboard.h b/include/input/keyboard.h index a1604f63..38d82b7a 100644 --- a/include/input/keyboard.h +++ b/include/input/keyboard.h @@ -3,6 +3,7 @@ #define LABWC_KEYBOARD_H #include +#include struct seat; struct keyboard; @@ -13,6 +14,7 @@ void keyboard_finish(struct seat *seat); void keyboard_setup_handlers(struct keyboard *keyboard); void keyboard_set_numlock(struct wlr_keyboard *keyboard); +void keyboard_update_layout(struct seat *seat, xkb_layout_index_t layout); void keyboard_cancel_keybind_repeat(struct keyboard *keyboard); bool keyboard_any_modifiers_pressed(struct wlr_keyboard *keyboard); diff --git a/include/labwc.h b/include/labwc.h index 5701e9bb..de2c972b 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -39,7 +39,6 @@ #include #include #include -#include #include "config/keybind.h" #include "config/rcxml.h" #include "input/cursor.h" diff --git a/include/view.h b/include/view.h index 344907a0..da6299d1 100644 --- a/include/view.h +++ b/include/view.h @@ -7,6 +7,7 @@ #include #include #include +#include #define LAB_MIN_VIEW_WIDTH 100 #define LAB_MIN_VIEW_HEIGHT 60 @@ -143,6 +144,7 @@ struct view { bool fullscreen; enum view_edge tiled; bool inhibits_keybinds; + xkb_layout_index_t keyboard_layout; /* Pointer to an output owned struct region, may be NULL */ struct region *tiled_region; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index b834ea5d..0308b637 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -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; diff --git a/src/input/keyboard.c b/src/input/keyboard.c index 87b41b56..b70ecf13 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -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) { diff --git a/src/view.c b/src/view.c index 060816da..73f699f0 100644 --- a/src/view.c +++ b/src/view.c @@ -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