]> git.mdlowis.com Git - proto/labwc.git/commitdiff
keyboard: allow applying keyboard layout per window
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Thu, 7 Sep 2023 14:41:47 +0000 (16:41 +0200)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sat, 4 Nov 2023 07:58:43 +0000 (07:58 +0000)
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.

docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
include/input/keyboard.h
include/labwc.h
include/view.h
src/config/rcxml.c
src/input/keyboard.c
src/view.c

index df23dd122c72d09806b700abe64902f4fafa8b64..f258aa18805ec7a5a5fcf97e56e2f5a1bcd6511b 100644 (file)
@@ -283,6 +283,10 @@ windows using the mouse.
        When recognizing a new keyboard enable or disable Num Lock.
        Default is on.
 
+*<keyboard layoutScope="">* [global|window]
+       Stores the keyboard layout either globally or per window and restores
+       it when switching back to the window. Default is global.
+
 *<keyboard><keybind key="" layoutDependent="">*
        Define a *key* binding in the format *modifier-key*, where supported
        modifiers are:
index 973a97011e0f447fb416b6dfdd840c8030496a4f..5b32337102c2144df7b136e741588dbb72fbbedc 100644 (file)
   -->
   <keyboard>
     <numlock>on</numlock>
+    <layoutScope>global</layoutScope>
     <repeatRate>25</repeatRate>
     <repeatDelay>600</repeatDelay>
     <keybind key="A-Tab">
index b3ef127fd6303a86d763091ec59626e086ac6b54..ed87a91f42ceb074b6992fe7040c0c4638d457b3 100644 (file)
@@ -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 */
index a1604f63970cf4e0b81ec96ab39e02e8f9be2743..38d82b7ad308877a5671e2c4a492ed8370c16a87 100644 (file)
@@ -3,6 +3,7 @@
 #define LABWC_KEYBOARD_H
 
 #include <stdbool.h>
+#include <xkbcommon/xkbcommon.h>
 
 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);
 
index 5701e9bbc62625cdc6ff262bc3eba256840cccf6..de2c972bac2dc0f6d3a045bf0cd4affbe2a54ea9 100644 (file)
@@ -39,7 +39,6 @@
 #include <wlr/types/wlr_virtual_pointer_v1.h>
 #include <wlr/types/wlr_virtual_keyboard_v1.h>
 #include <wlr/util/log.h>
-#include <xkbcommon/xkbcommon.h>
 #include "config/keybind.h"
 #include "config/rcxml.h"
 #include "input/cursor.h"
index 344907a08eb59086ad26781e543d7c081c4c2ab9..da6299d1ad1cda474505c99b776f00b341a19008 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdint.h>
 #include <wayland-util.h>
 #include <wlr/util/box.h>
+#include <xkbcommon/xkbcommon.h>
 
 #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;
index b834ea5d09616ce88920ccd457da3500a621b6d1..0308b6376fbcea7e028f02443b04999c49f92602 100644 (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;
index 87b41b56179cc88fd4cc7f6cbf10cadced624dd6..b70ecf13f6f78d19431b6bb6443e8fcc3d1943ba 100644 (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)
 {
index 060816da7eeeb42d626c4805e0ae0360d8fc75b6..73f699f0a904fddccd5f1796e1e4ad61a72d4273 100644 (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