Adding xkb patch as per request #111

This commit is contained in:
bakkeby 2021-04-07 15:35:56 +02:00
parent 0c88a49e27
commit ac737f9dfc
8 changed files with 193 additions and 1 deletions

View File

@ -483,6 +483,9 @@ static const BarRule barrules[] = {
#elif BAR_STATUS_PATCH #elif BAR_STATUS_PATCH
{ 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, "status" }, { 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, "status" },
#endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH #endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH
#if XKB_PATCH
{ 0, 0, BAR_ALIGN_RIGHT, width_xkb, draw_xkb, click_xkb, "xkb" },
#endif // XKB_PATCH
#if BAR_FLEXWINTITLE_PATCH #if BAR_FLEXWINTITLE_PATCH
{ -1, 0, BAR_ALIGN_NONE, width_flexwintitle, draw_flexwintitle, click_flexwintitle, "flexwintitle" }, { -1, 0, BAR_ALIGN_NONE, width_flexwintitle, draw_flexwintitle, click_flexwintitle, "flexwintitle" },
#elif BAR_TABGROUPS_PATCH #elif BAR_TABGROUPS_PATCH
@ -660,6 +663,14 @@ static const Layout layouts[] = {
}; };
#endif // FLEXTILE_DELUXE_LAYOUT #endif // FLEXTILE_DELUXE_LAYOUT
#if XKB_PATCH
/* xkb frontend */
static const char *xkb_layouts[] = {
"en",
"ru",
};
#endif // XKB_PATCH
/* key definitions */ /* key definitions */
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#if COMBO_PATCH && SWAPTAGS_PATCH && TAGOTHERMONITOR_PATCH #if COMBO_PATCH && SWAPTAGS_PATCH && TAGOTHERMONITOR_PATCH

87
dwm.c
View File

@ -55,6 +55,10 @@
#include <pango/pango.h> #include <pango/pango.h>
#endif // BAR_PANGO_PATCH #endif // BAR_PANGO_PATCH
#if XKB_PATCH
#include <X11/XKBlib.h>
#endif // XKB_PATCH
#if SPAWNCMD_PATCH #if SPAWNCMD_PATCH
#include <assert.h> #include <assert.h>
#include <libgen.h> #include <libgen.h>
@ -217,6 +221,9 @@ enum {
ClkWinTitle, ClkWinTitle,
ClkClientWin, ClkClientWin,
ClkRootWin, ClkRootWin,
#if XKB_PATCH
ClkXKB,
#endif // XKB_PATCH
ClkLast ClkLast
}; /* clicks */ }; /* clicks */
@ -303,6 +310,16 @@ typedef struct {
const Arg arg; const Arg arg;
} Button; } Button;
#if XKB_PATCH
typedef struct XkbInfo XkbInfo;
struct XkbInfo {
XkbInfo *next;
XkbInfo *prev;
int group;
Window w;
};
#endif // XKB_PATCH
typedef struct Client Client; typedef struct Client Client;
struct Client { struct Client {
char name[256]; char name[256];
@ -367,6 +384,9 @@ struct Client {
#if IPC_PATCH #if IPC_PATCH
ClientState prevstate; ClientState prevstate;
#endif // IPC_PATCH #endif // IPC_PATCH
#if XKB_PATCH
XkbInfo *xkb;
#endif // XKB_PATCH
}; };
typedef struct { typedef struct {
@ -496,9 +516,16 @@ typedef struct {
const char *floatpos; const char *floatpos;
#endif // FLOATPOS_PATCH #endif // FLOATPOS_PATCH
int monitor; int monitor;
#if XKB_PATCH
int xkb_layout;
#endif // XKB_PATCH
} Rule; } Rule;
#if XKB_PATCH
#define RULE(...) { .monitor = -1, .xkb_layout = -1, ##__VA_ARGS__ },
#else
#define RULE(...) { .monitor = -1, ##__VA_ARGS__ }, #define RULE(...) { .monitor = -1, ##__VA_ARGS__ },
#endif // XKB_PATCH
/* Cross patch compatibility rule macro helper macros */ /* Cross patch compatibility rule macro helper macros */
#define FLOATING , .isfloating = 1 #define FLOATING , .isfloating = 1
@ -688,6 +715,9 @@ static char rawestext[1024];
#endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH #endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH
#endif // BAR_EXTRASTATUS_PATCH #endif // BAR_EXTRASTATUS_PATCH
#if XKB_PATCH
static int xkbEventType = 0;
#endif // XKB_PATCH
static int screen; static int screen;
static int sw, sh; /* X display screen geometry width, height */ static int sw, sh; /* X display screen geometry width, height */
static int bh; /* bar geometry */ static int bh; /* bar geometry */
@ -877,6 +907,10 @@ applyrules(Client *c)
} }
} }
#endif // SWITCHTAG_PATCH #endif // SWITCHTAG_PATCH
#if XKB_PATCH
if (r->xkb_layout > -1)
c->xkb->group = r->xkb_layout;
#endif // XKB_PATCH
#if ONLY_ONE_RULE_MATCH_PATCH #if ONLY_ONE_RULE_MATCH_PATCH
break; break;
#endif // ONLY_ONE_RULE_MATCH_PATCH #endif // ONLY_ONE_RULE_MATCH_PATCH
@ -2246,6 +2280,13 @@ manage(Window w, XWindowAttributes *wa)
c->cfact = 1.0; c->cfact = 1.0;
#endif // CFACTS_PATCH #endif // CFACTS_PATCH
updatetitle(c); updatetitle(c);
#if XKB_PATCH
/* Setting current xkb state must be before applyrules */
if (!(c->xkb = findxkb(c->win)))
c->xkb = createxkb(c->win);
#endif // XKB_PATCH
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon; c->mon = t->mon;
c->tags = t->tags; c->tags = t->tags;
@ -3018,9 +3059,20 @@ run(void)
XEvent ev; XEvent ev;
/* main event loop */ /* main event loop */
XSync(dpy, False); XSync(dpy, False);
while (running && !XNextEvent(dpy, &ev)) while (running && !XNextEvent(dpy, &ev)) {
#if XKB_PATCH
/* Unfortunately the xkbEventType is not constant hence it can't be part of the
* normal event handler below */
if (ev.type == xkbEventType) {
xkbeventnotify(&ev);
continue;
}
#endif // XKB_PATCH
if (handler[ev.type]) if (handler[ev.type])
handler[ev.type](&ev); /* call handler */ handler[ev.type](&ev); /* call handler */
}
} }
#endif // IPC_PATCH #endif // IPC_PATCH
@ -3198,6 +3250,9 @@ setfocus(Client *c)
XChangeProperty(dpy, root, netatom[NetActiveWindow], XChangeProperty(dpy, root, netatom[NetActiveWindow],
XA_WINDOW, 32, PropModeReplace, XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1); (unsigned char *) &(c->win), 1);
#if XKB_PATCH
XkbLockGroup(dpy, XkbUseCoreKbd, c->xkb->group);
#endif // XKB_PATCH
} }
#if BAR_SYSTRAY_PATCH #if BAR_SYSTRAY_PATCH
sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
@ -3381,6 +3436,9 @@ setup(void)
{ {
int i; int i;
XSetWindowAttributes wa; XSetWindowAttributes wa;
#if XKB_PATCH
XkbStateRec xkbstate;
#endif // XKB_PATCH
Atom utf8string; Atom utf8string;
/* clean up any zombies immediately */ /* clean up any zombies immediately */
@ -3553,6 +3611,17 @@ setup(void)
|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask); XSelectInput(dpy, root, wa.event_mask);
#if XKB_PATCH
/* get xkb extension info, events and current state */
if (!XkbQueryExtension(dpy, NULL, &xkbEventType, NULL, NULL, NULL))
fputs("warning: can not query xkb extension\n", stderr);
XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify,
XkbAllStateComponentsMask, XkbGroupStateMask);
XkbGetState(dpy, XkbUseCoreKbd, &xkbstate);
xkbGlobal.group = xkbstate.locked_group;
#endif // XKB_PATCH
grabkeys(); grabkeys();
focus(NULL); focus(NULL);
#if IPC_PATCH #if IPC_PATCH
@ -4034,6 +4103,9 @@ unmanage(Client *c, int destroyed)
unsigned int switchtag = c->switchtag; unsigned int switchtag = c->switchtag;
#endif // SWITCHTAG_PATCH #endif // SWITCHTAG_PATCH
XWindowChanges wc; XWindowChanges wc;
#if XKB_PATCH
XkbInfo *xkb;
#endif // XKB_PATCH
#if SWALLOW_PATCH #if SWALLOW_PATCH
if (c->swallowing) { if (c->swallowing) {
@ -4064,6 +4136,19 @@ unmanage(Client *c, int destroyed)
XSetErrorHandler(xerror); XSetErrorHandler(xerror);
XUngrabServer(dpy); XUngrabServer(dpy);
} }
#if XKB_PATCH
else {
xkb = findxkb(c->win);
if (xkb != NULL) {
if (xkb->prev)
xkb->prev->next = xkb->next;
if (xkb->next)
xkb->next->prev = xkb->prev;
free(xkb);
}
}
#endif // XKB_PATCH
free(c); free(c);
#if SWALLOW_PATCH #if SWALLOW_PATCH
if (s) if (s)

View File

@ -298,6 +298,9 @@
#if ZOOMSWAP_PATCH #if ZOOMSWAP_PATCH
#include "zoomswap.c" #include "zoomswap.c"
#endif #endif
#if XKB_PATCH
#include "xkb.c"
#endif
#if XRDB_PATCH && !BAR_VTCOLORS_PATCH #if XRDB_PATCH && !BAR_VTCOLORS_PATCH
#include "xrdb.c" #include "xrdb.c"
#endif #endif

View File

@ -294,6 +294,9 @@
#if ZOOMSWAP_PATCH #if ZOOMSWAP_PATCH
#include "zoomswap.h" #include "zoomswap.h"
#endif #endif
#if XKB_PATCH
#include "xkb.h"
#endif
#if XRDB_PATCH && !BAR_VTCOLORS_PATCH #if XRDB_PATCH && !BAR_VTCOLORS_PATCH
#include "xrdb.h" #include "xrdb.h"
#endif #endif

View File

@ -9,6 +9,15 @@ handlexevent(struct epoll_event *ev)
XEvent ev; XEvent ev;
while (running && XPending(dpy)) { while (running && XPending(dpy)) {
XNextEvent(dpy, &ev); XNextEvent(dpy, &ev);
#if XKB_PATCH
/* Unfortunately the xkbEventType is not constant hence it can't be part of the
* normal event handler below */
if (ev.type == xkbEventType) {
xkbeventnotify(&ev);
continue;
}
#endif // XKB_PATCH
if (handler[ev.type]) { if (handler[ev.type]) {
handler[ev.type](&ev); /* call handler */ handler[ev.type](&ev); /* call handler */
ipc_send_events(mons, &lastselmon, selmon); ipc_send_events(mons, &lastselmon, selmon);

67
patch/xkb.c Normal file
View File

@ -0,0 +1,67 @@
static XkbInfo xkbGlobal;
static XkbInfo *xkbSaved = NULL;
static XkbInfo *
createxkb(Window w)
{
XkbInfo *xkb;
xkb = malloc(sizeof *xkb);
if (xkb == NULL)
die("fatal: could not malloc() %u bytes\n", sizeof *xkb);
xkb->group = xkbGlobal.group;
xkb->w = w;
xkb->next = xkbSaved;
if (xkbSaved != NULL)
xkbSaved->prev = xkb;
xkb->prev = NULL;
xkbSaved = xkb;
return xkb;
}
XkbInfo *
findxkb(Window w)
{
XkbInfo *xkb;
for (xkb = xkbSaved; xkb != NULL; xkb = xkb->next)
if (xkb->w == w)
return xkb;
return NULL;
}
void
xkbeventnotify(XEvent *e)
{
XkbEvent *ev;
ev = (XkbEvent *) e;
switch (ev->any.xkb_type) {
case XkbStateNotify:
xkbGlobal.group = ev->state.locked_group;
if (selmon != NULL && selmon->sel != NULL)
selmon->sel->xkb->group = xkbGlobal.group;
drawbars();
break;
}
}
/* xkb bar module */
int
width_xkb(Bar *bar, BarArg *a)
{
return TEXTW(xkb_layouts[xkbGlobal.group]);
}
int
draw_xkb(Bar *bar, BarArg *a)
{
drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, xkb_layouts[xkbGlobal.group], 0, False);
return 1;
}
int
click_xkb(Bar *bar, Arg *arg, BarArg *a)
{
return ClkXKB;
}

7
patch/xkb.h Normal file
View File

@ -0,0 +1,7 @@
static XkbInfo *createxkb(Window w);
static XkbInfo *findxkb(Window w);
static void xkbeventnotify(XEvent *e);
static int width_xkb(Bar *bar, BarArg *a);
static int draw_xkb(Bar *bar, BarArg *a);
static int click_xkb(Bar *bar, Arg *arg, BarArg *a);

View File

@ -1105,6 +1105,13 @@
*/ */
#define WINVIEW_PATCH 0 #define WINVIEW_PATCH 0
/* Remember keyboard layout per client.
* It is recommended that you configure xkb before using this patch as described in
* https://www.x.org/archive/X11R7.5/doc/input/XKB-Config.html
* https://dwm.suckless.org/patches/xkb/
*/
#define XKB_PATCH 0
/* Allows dwm to read colors from xrdb (.Xresources) during runtime. Compatible with /* Allows dwm to read colors from xrdb (.Xresources) during runtime. Compatible with
* the float border color, awesomebar, urgentborder and titlecolor patches. * the float border color, awesomebar, urgentborder and titlecolor patches.
* https://dwm.suckless.org/patches/xrdb/ * https://dwm.suckless.org/patches/xrdb/