dwl-patches/patches/kblayout/kblayout.patch
2024-09-30 21:10:51 +01:00

164 lines
5.2 KiB
Diff

diff -ruN dwl.orig/config.def.h dwl/config.def.h
--- dwl.orig/config.def.h 2024-07-25 07:36:08.235927317 +0100
+++ dwl/config.def.h 2024-07-25 07:46:56.286901928 +0100
@@ -13,6 +13,9 @@
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-kblayout";
+static const char *kblayout_cmd[] = {"pkill", "-RTMIN+1", "someblocks", NULL};
/* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9)
diff -ruN dwl.orig/dwl.c dwl/dwl.c
--- dwl.orig/dwl.c 2024-07-25 07:36:08.236927317 +0100
+++ dwl/dwl.c 2024-07-25 07:49:15.074896491 +0100
@@ -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 @@
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 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 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);
@@ -1056,11 +1061,13 @@
/* 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 +1346,24 @@
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 +1416,19 @@
}
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 +1439,7 @@
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 +1588,36 @@
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 +1695,8 @@
/* Send modifiers to the client. */
wlr_seat_keyboard_notify_modifiers(seat,
&group->wlr_group->keyboard.modifiers);
+
+ kblayout(group);
}
int