apply kblayout patch

This commit is contained in:
korei999 2023-11-29 22:00:52 +02:00
parent bd0503927b
commit 035bc3b1a1
2 changed files with 72 additions and 1 deletions

View file

@ -47,6 +47,12 @@ static const char kblayout_file[] = "/tmp/dwl-keymap";
static const char *kblayout_cmd[] = {"pkill", "-RTMIN+1", "someblocks", NULL};
static const int kblayout_perclient = 0;
/* keyboard layout change notification for status bar */
/* example using someblocks:
static const char kblayout_file[] = "/tmp/dwl-keymap";
static const char *kblayout_cmd[] = {"pkill", "-RTMIN+1", "someblocks", NULL};
*/
static const Rule rules[] = {
/* app_id title tags mask isfloating opacity monitor */
// { "firefox", NULL, 1 << 8, 0, -1, -1 },

67
dwl.c
View file

@ -133,6 +133,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 {
@ -159,6 +160,8 @@ typedef struct {
struct wl_listener modifiers;
struct wl_listener key;
struct wl_listener destroy;
xkb_layout_index_t layout_idx;
} Keyboard;
typedef struct {
@ -290,6 +293,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(Keyboard *kb, int update);
static int keybinding(uint32_t mods, xkb_keycode_t keycode);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
@ -409,6 +413,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);
@ -859,6 +865,8 @@ createkeyboard(struct wlr_keyboard *keyboard)
/* And add the keyboard to our list of keyboards */
wl_list_insert(&keyboards, &kb->link);
kblayoutnotify(kb, 1);
}
void
@ -1041,6 +1049,9 @@ createnotify(struct wl_listener *listener, void *data)
c = xdg_surface->data = ecalloc(1, sizeof(*c));
c->surface.xdg = xdg_surface;
c->bw = borderpx;
if (kblayout_perclient)
c->layout_idx = xkb_state_serialize_layout(
wlr_seat_get_keyboard(seat)->xkb_state, XKB_STATE_LAYOUT_EFFECTIVE);
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
@ -1432,6 +1443,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;
@ -1494,10 +1508,21 @@ 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);
/* Update keyboard layout */
if (kblayout_perclient) {
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->layout_idx;
xkb_state_update_mask(kb->xkb_state, mdepr, mlatc, mlock, ldepr, llatc, llock);
}
}
void
@ -1630,6 +1655,41 @@ inputdevice(struct wl_listener *listener, void *data)
wlr_seat_set_capabilities(seat, caps);
}
void
kblayoutnotify(Keyboard *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_keyboard->xkb_state,
XKB_STATE_LAYOUT_EFFECTIVE);
// Update client layout
if (kblayout_perclient && 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_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_keycode_t keycode)
{
@ -1665,6 +1725,8 @@ keypress(struct wl_listener *listener, void *data)
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
kblayoutnotify(kb, 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)
@ -1695,6 +1757,9 @@ keypressmod(struct wl_listener *listener, void *data)
/* This event is raised when a modifier key, such as shift or alt, is
* pressed. We simply communicate this to the client. */
Keyboard *kb = wl_container_of(listener, kb, modifiers);
kblayoutnotify(kb, 1);
/*
* A seat can only have one keyboard, but this is a limitation of the
* Wayland protocol - not wlroots. We assign all connected keyboards to the