summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/kblayout/kblayout.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dwl-patches/patches/kblayout/kblayout.patch')
-rw-r--r--dwl-patches/patches/kblayout/kblayout.patch187
1 files changed, 187 insertions, 0 deletions
diff --git a/dwl-patches/patches/kblayout/kblayout.patch b/dwl-patches/patches/kblayout/kblayout.patch
new file mode 100644
index 0000000..707a4fc
--- /dev/null
+++ b/dwl-patches/patches/kblayout/kblayout.patch
@@ -0,0 +1,187 @@
+From ad18a8b8e9de138c3d89246ac0e25c0467ff5971 Mon Sep 17 00:00:00 2001
+From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
+Date: Fri, 11 Oct 2024 10:50:14 +0200
+Subject: [PATCH] Add per client keyboard layout and status bar info
+
+---
+ config.def.h | 3 +++
+ dwl.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 72 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index 22d2171..862c104 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -13,6 +13,9 @@ static const float focuscolor[] = COLOR(0x005577ff);
+ static const float urgentcolor[] = COLOR(0xff0000ff);
+ /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
+ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
++/* keyboard layout change notification for status bar */
++static const char kblayout_file[] = "/tmp/dwl-keymap";
++static const char *kblayout_cmd[] = {"pkill", "-RTMIN+3", "someblocks", NULL};
+
+ /* tagging - TAGCOUNT must be no greater than 31 */
+ #define TAGCOUNT (9)
+diff --git a/dwl.c b/dwl.c
+index a2711f6..95ca3d3 100644
+--- a/dwl.c
++++ b/dwl.c
+@@ -14,6 +14,7 @@
+ #include <wayland-server-core.h>
+ #include <wlr/backend.h>
+ #include <wlr/backend/libinput.h>
++#include <wlr/interfaces/wlr_keyboard.h>
+ #include <wlr/render/allocator.h>
+ #include <wlr/render/wlr_renderer.h>
+ #include <wlr/types/wlr_alpha_modifier_v1.h>
+@@ -141,6 +142,7 @@ typedef struct {
+ uint32_t tags;
+ int isfloating, isurgent, isfullscreen;
+ uint32_t resize; /* configure serial of a pending resize */
++ unsigned int kblayout_idx;
+ } Client;
+
+ typedef struct {
+@@ -294,6 +296,7 @@ static void gpureset(struct wl_listener *listener, void *data);
+ static void handlesig(int signo);
+ static void incnmaster(const Arg *arg);
+ static void inputdevice(struct wl_listener *listener, void *data);
++static void kblayout(KeyboardGroup *kb);
+ static int keybinding(uint32_t mods, xkb_keysym_t sym);
+ static void keypress(struct wl_listener *listener, void *data);
+ static void keypressmod(struct wl_listener *listener, void *data);
+@@ -413,6 +416,8 @@ static struct wlr_box sgeom;
+ static struct wl_list mons;
+ static Monitor *selmon;
+
++static unsigned int kblayout_idx = -1;
++
+ #ifdef XWAYLAND
+ static void activatex11(struct wl_listener *listener, void *data);
+ static void associatex11(struct wl_listener *listener, void *data);
+@@ -879,6 +884,8 @@ createkeyboard(struct wlr_keyboard *keyboard)
+
+ /* Add the new keyboard to the group */
+ wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard);
++
++ kblayout(kb_group);
+ }
+
+ KeyboardGroup *
+@@ -1056,11 +1063,13 @@ createnotify(struct wl_listener *listener, void *data)
+ /* This event is raised when a client creates a new toplevel (application window). */
+ struct wlr_xdg_toplevel *toplevel = data;
+ Client *c = NULL;
++ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
+
+ /* Allocate a Client for this surface */
+ c = toplevel->base->data = ecalloc(1, sizeof(*c));
+ c->surface.xdg = toplevel->base;
+ c->bw = borderpx;
++ c->kblayout_idx = kb ? kb->modifiers.group : 0;
+
+ LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
+ LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
+@@ -1339,10 +1348,24 @@ dirtomon(enum wlr_direction dir)
+ void
+ focusclient(Client *c, int lift)
+ {
++ /* Copied from wlroots/types/wlr_keyboard_group.c */
++ struct keyboard_group_device {
++ struct wlr_keyboard *keyboard;
++ struct wl_listener key;
++ struct wl_listener modifiers;
++ struct wl_listener keymap;
++ struct wl_listener repeat_info;
++ struct wl_listener destroy;
++ struct wl_list link; // wlr_keyboard_group.devices
++ };
++
+ struct wlr_surface *old = seat->keyboard_state.focused_surface;
+ int unused_lx, unused_ly, old_client_type;
+ Client *old_c = NULL;
+ LayerSurface *old_l = NULL;
++ struct keyboard_group_device *device;
++ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
++ struct wlr_keyboard_group *group = kb ? wlr_keyboard_group_from_wlr_keyboard(kb) : NULL;
+
+ if (locked)
+ return;
+@@ -1395,6 +1418,19 @@ focusclient(Client *c, int lift)
+ }
+ printstatus();
+
++ /* Update keyboard layout */
++ if (group) {
++ // Update the first real device, because kb or group->kb is not a real
++ // keyboard and its effective layout gets overwritten
++ device = wl_container_of(group->devices.next, device, link);
++ wlr_keyboard_notify_modifiers(device->keyboard,
++ device->keyboard->modifiers.depressed,
++ device->keyboard->modifiers.latched,
++ device->keyboard->modifiers.locked,
++ c ? c->kblayout_idx : 0
++ );
++ }
++
+ if (!c) {
+ /* With no client, all we have left is to clear focus */
+ wlr_seat_keyboard_notify_clear_focus(seat);
+@@ -1405,7 +1441,7 @@ focusclient(Client *c, int lift)
+ motionnotify(0, NULL, 0, 0, 0, 0);
+
+ /* Have a client, so focus its top-level wlr_surface */
+- client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat));
++ client_notify_enter(client_surface(c), kb);
+
+ /* Activate the new client */
+ client_activate_surface(client_surface(c), 1);
+@@ -1554,6 +1590,36 @@ inputdevice(struct wl_listener *listener, void *data)
+ wlr_seat_set_capabilities(seat, caps);
+ }
+
++void
++kblayout(KeyboardGroup *kb)
++{
++ FILE *f;
++ Client *c;
++ unsigned int idx = kb->wlr_group->keyboard.modifiers.group;
++
++ // If layout did not change, do nothing
++ if (kblayout_idx == idx)
++ return;
++ kblayout_idx = idx;
++
++ // Update client layout
++ if ((c = focustop(selmon)))
++ c->kblayout_idx = kblayout_idx;
++
++ // Save current layout to kblayout_file
++ if (*kblayout_file && (f = fopen(kblayout_file, "w"))) {
++ fputs(xkb_keymap_layout_get_name(kb->wlr_group->keyboard.keymap,
++ idx), f);
++ fclose(f);
++ }
++
++ // Run kblayout_cmd
++ if (kblayout_cmd[0] && fork() == 0) {
++ execvp(kblayout_cmd[0], (char *const *)kblayout_cmd);
++ die("dwl: execvp %s failed:", kblayout_cmd[0]);
++ }
++}
++
+ int
+ keybinding(uint32_t mods, xkb_keysym_t sym)
+ {
+@@ -1631,6 +1697,8 @@ keypressmod(struct wl_listener *listener, void *data)
+ /* Send modifiers to the client. */
+ wlr_seat_keyboard_notify_modifiers(seat,
+ &group->wlr_group->keyboard.modifiers);
++
++ kblayout(group);
+ }
+
+ int
+--
+2.46.2
+