mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-09-08 12:14:50 +00:00

Eliminated wiki. Individual patches have a README.md explanation in their own subdirectory. Simplified submission of new patches and maintenance of existing patches. Instructions page (README.md autodisplayed) is now at https://codeberg.org/dwl/dwl-patches/
188 lines
6.2 KiB
Diff
188 lines
6.2 KiB
Diff
From a0c758953fe0cbb20ea74d0acfa3e44b8173d12d Mon Sep 17 00:00:00 2001
|
|
From: ForzCross <forzcross@gmail.com>
|
|
Date: Sun, 21 Jan 2024 15:52:31 +0300
|
|
Subject: [PATCH] Add per client keyboard layout and status bar info
|
|
|
|
---
|
|
config.def.h | 3 +++
|
|
dwl.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
2 files changed, 67 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/config.def.h b/config.def.h
|
|
index 9009517..81bb10d 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);
|
|
/* To conform 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 bf02a6d..17c8fa4 100644
|
|
--- a/dwl.c
|
|
+++ b/dwl.c
|
|
@@ -135,6 +135,7 @@ typedef struct {
|
|
uint32_t tags;
|
|
int isfloating, isurgent, isfullscreen;
|
|
uint32_t resize; /* configure serial of a pending resize */
|
|
+ xkb_layout_index_t layout_idx;
|
|
} Client;
|
|
|
|
typedef struct {
|
|
@@ -155,6 +156,7 @@ typedef struct {
|
|
|
|
struct wl_listener modifiers;
|
|
struct wl_listener key;
|
|
+ xkb_layout_index_t layout_idx;
|
|
} KeyboardGroup;
|
|
|
|
typedef struct {
|
|
@@ -273,6 +275,7 @@ static void fullscreennotify(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 kblayoutnotify(KeyboardGroup *kb, int update);
|
|
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);
|
|
@@ -385,6 +388,8 @@ static struct wlr_box sgeom;
|
|
static struct wl_list mons;
|
|
static Monitor *selmon;
|
|
|
|
+xkb_layout_index_t status_layout_idx = -1;
|
|
+
|
|
#ifdef XWAYLAND
|
|
static void activatex11(struct wl_listener *listener, void *data);
|
|
static void associatex11(struct wl_listener *listener, void *data);
|
|
@@ -772,6 +777,7 @@ createkeyboard(struct wlr_keyboard *keyboard)
|
|
|
|
/* Add the new keyboard to the group */
|
|
wlr_keyboard_group_add_keyboard(kb_group.wlr_group, keyboard);
|
|
+ kblayoutnotify(&kb_group, 1);
|
|
}
|
|
|
|
void
|
|
@@ -927,6 +933,7 @@ createnotify(struct wl_listener *listener, void *data)
|
|
struct wlr_xdg_surface *xdg_surface = data;
|
|
Client *c = NULL;
|
|
LayerSurface *l = NULL;
|
|
+ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
|
|
|
|
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
|
|
struct wlr_xdg_popup *popup = xdg_surface->popup;
|
|
@@ -949,6 +956,9 @@ createnotify(struct wl_listener *listener, void *data)
|
|
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
|
c->surface.xdg = xdg_surface;
|
|
c->bw = borderpx;
|
|
+ c->layout_idx = kb
|
|
+ ? xkb_state_serialize_layout(kb->xkb_state, XKB_STATE_LAYOUT_EFFECTIVE)
|
|
+ : 0;
|
|
|
|
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
|
@@ -1165,6 +1175,9 @@ focusclient(Client *c, int lift)
|
|
int unused_lx, unused_ly, old_client_type;
|
|
Client *old_c = NULL;
|
|
LayerSurface *old_l = NULL;
|
|
+ xkb_mod_mask_t mdepr, mlatc, mlock;
|
|
+ xkb_layout_index_t ldepr, llatc, llock;
|
|
+ struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
|
|
|
|
if (locked)
|
|
return;
|
|
@@ -1217,6 +1230,17 @@ focusclient(Client *c, int lift)
|
|
}
|
|
printstatus();
|
|
|
|
+ /* Update keyboard layout */
|
|
+ if (kb) {
|
|
+ mdepr = xkb_state_serialize_mods(kb->xkb_state, XKB_STATE_MODS_DEPRESSED);
|
|
+ mlatc = xkb_state_serialize_mods(kb->xkb_state, XKB_STATE_MODS_LATCHED);
|
|
+ mlock = xkb_state_serialize_mods(kb->xkb_state, XKB_STATE_MODS_LOCKED);
|
|
+ ldepr = xkb_state_serialize_layout(kb->xkb_state, XKB_STATE_LAYOUT_DEPRESSED);
|
|
+ llatc = xkb_state_serialize_layout(kb->xkb_state, XKB_STATE_LAYOUT_LATCHED);
|
|
+ llock = c ? c->layout_idx : 0;
|
|
+ xkb_state_update_mask(kb->xkb_state, mdepr, mlatc, mlock, ldepr, llatc, llock);
|
|
+ }
|
|
+
|
|
if (!c) {
|
|
/* With no client, all we have left is to clear focus */
|
|
wlr_seat_keyboard_notify_clear_focus(seat);
|
|
@@ -1227,7 +1251,7 @@ focusclient(Client *c, int lift)
|
|
motionnotify(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);
|
|
@@ -1352,6 +1376,41 @@ inputdevice(struct wl_listener *listener, void *data)
|
|
wlr_seat_set_capabilities(seat, caps);
|
|
}
|
|
|
|
+void
|
|
+kblayoutnotify(KeyboardGroup *kb, int update)
|
|
+{
|
|
+ FILE *f;
|
|
+ Client *c;
|
|
+ xkb_layout_index_t old = kb->layout_idx;
|
|
+
|
|
+ if (update) {
|
|
+ kb->layout_idx = xkb_state_serialize_layout(kb->wlr_group->keyboard.xkb_state,
|
|
+ XKB_STATE_LAYOUT_EFFECTIVE);
|
|
+
|
|
+ // Update client layout
|
|
+ if (kb->layout_idx != old && (c = focustop(selmon)))
|
|
+ c->layout_idx = kb->layout_idx;
|
|
+ }
|
|
+
|
|
+ // If layout did not change, do nothing
|
|
+ if (status_layout_idx == kb->layout_idx)
|
|
+ return;
|
|
+ status_layout_idx = kb->layout_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,
|
|
+ kb->layout_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)
|
|
{
|
|
@@ -1391,6 +1450,8 @@ keypress(struct wl_listener *listener, void *data)
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
+ kblayoutnotify(group, 0);
|
|
+
|
|
/* On _press_ if there is no active screen locker,
|
|
* attempt to process a compositor keybinding. */
|
|
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
|
@@ -1429,6 +1490,8 @@ keypressmod(struct wl_listener *listener, void *data)
|
|
/* Send modifiers to the client. */
|
|
wlr_seat_keyboard_notify_modifiers(seat,
|
|
&group->wlr_group->keyboard.modifiers);
|
|
+
|
|
+ kblayoutnotify(group, 1);
|
|
}
|
|
|
|
int
|
|
--
|
|
2.43.0
|
|
|