mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-09-10 21:24:55 +00:00
178 lines
6.1 KiB
Diff
178 lines
6.1 KiB
Diff
commit dc72dae11b1ae4d76b70881e8c5bd62055234e60
|
|
Author: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
|
Date: Sun Apr 7 22:03:49 2024 +0200
|
|
|
|
Add per client keyboard layout and status bar info
|
|
|
|
diff --git a/config.def.h b/config.def.h
|
|
index 8f498d2..484e522 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-kblayout";
|
|
+static const char *kblayout_cmd[] = {"pkill", "-RTMIN+1", "someblocks", NULL};
|
|
|
|
/* tagging - TAGCOUNT must be no greater than 31 */
|
|
#define TAGCOUNT (9)
|
|
diff --git a/dwl.c b/dwl.c
|
|
index bf763df..c8da00e 100644
|
|
--- a/dwl.c
|
|
+++ b/dwl.c
|
|
@@ -139,6 +139,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 {
|
|
@@ -286,6 +287,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 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);
|
|
@@ -405,6 +407,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);
|
|
@@ -795,6 +799,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);
|
|
}
|
|
|
|
void
|
|
@@ -951,6 +957,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;
|
|
@@ -973,6 +980,7 @@ createnotify(struct wl_listener *listener, void *data)
|
|
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
|
c->surface.xdg = xdg_surface;
|
|
c->bw = borderpx;
|
|
+ c->kblayout_idx = kb ? kb->modifiers.group : 0;
|
|
|
|
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
|
@@ -1236,10 +1244,26 @@ 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;
|
|
+ xkb_mod_mask_t mdepr, mlatc, mlock;
|
|
+ xkb_layout_index_t ldepr, llatc, llock;
|
|
+ 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;
|
|
@@ -1292,6 +1316,20 @@ 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);
|
|
+ mdepr = xkb_state_serialize_mods(device->keyboard->xkb_state, XKB_STATE_MODS_DEPRESSED);
|
|
+ mlatc = xkb_state_serialize_mods(device->keyboard->xkb_state, XKB_STATE_MODS_LATCHED);
|
|
+ mlock = xkb_state_serialize_mods(device->keyboard->xkb_state, XKB_STATE_MODS_LOCKED);
|
|
+ ldepr = xkb_state_serialize_layout(device->keyboard->xkb_state, XKB_STATE_LAYOUT_DEPRESSED);
|
|
+ llatc = xkb_state_serialize_layout(device->keyboard->xkb_state, XKB_STATE_LAYOUT_LATCHED);
|
|
+ llock = c ? c->kblayout_idx : 0;
|
|
+ xkb_state_update_mask(device->keyboard->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);
|
|
@@ -1302,7 +1340,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);
|
|
@@ -1427,6 +1465,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)
|
|
{
|
|
@@ -1504,6 +1572,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
|