commit 63b4c950ec21c895a48d805912bfd09930d5c806
parent a9b201c1ce529bf1931909b83ba773963cc1087d
Author: Shvedov Yury <shved@lvk.cs.msu.su>
Date: Sat, 15 Feb 2014 14:30:15 +0400
add xkb patch
Diffstat:
2 files changed, 296 insertions(+), 0 deletions(-)
diff --git a/dwm.suckless.org/patches/dwm-6.1-xkb.diff b/dwm.suckless.org/patches/dwm-6.1-xkb.diff
@@ -0,0 +1,272 @@
+Author: Yury Shvedov <shved@lvk.cs.msu.su>
+URL: http://dwm.suckless.org/patches/xkb
+Implements a xxkb-like behaviour.
+
+diff --git a/config.def.h b/config.def.h
+index 875885b..2dd24c6 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -31,6 +31,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
+ static const int nmaster = 1; /* number of clients in master area */
+ static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
+
++/* xkb frontend */
++static const Bool showxkb = True; /* False means no xkb layout text */
++static const char *xkb_layouts [] = {
++ "en",
++ "ru",
++};
++
+ static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+diff --git a/dwm.c b/dwm.c
+index 1bbb4b3..35bd4d7 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -36,6 +36,7 @@
+ #include <X11/Xlib.h>
+ #include <X11/Xproto.h>
+ #include <X11/Xutil.h>
++#include <X11/XKBlib.h>
+ #ifdef XINERAMA
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+@@ -83,6 +84,7 @@ typedef struct {
+
+ typedef struct Monitor Monitor;
+ typedef struct Client Client;
++typedef struct XkbInfo XkbInfo;
+ struct Client {
+ char name[256];
+ float mina, maxa;
+@@ -96,6 +98,13 @@ struct Client {
+ Client *snext;
+ Monitor *mon;
+ Window win;
++ XkbInfo *xkb;
++};
++struct XkbInfo {
++ XkbInfo *next;
++ XkbInfo *prev;
++ int group;
++ Window w;
+ };
+
+ typedef struct {
+@@ -165,6 +174,7 @@ static void drawbar(Monitor *m);
+ static void drawbars(void);
+ static void enternotify(XEvent *e);
+ static void expose(XEvent *e);
++static XkbInfo *findxkb(Window w);
+ static void focus(Client *c);
+ static void focusin(XEvent *e);
+ static void focusmon(const Arg *arg);
+@@ -231,6 +241,7 @@ static Monitor *wintomon(Window w);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
++static void xkbeventnotify(XEvent *e);
+ static void zoom(const Arg *arg);
+
+ /* variables */
+@@ -241,6 +252,7 @@ static int sw, sh; /* X display screen geometry width, height */
+ static int bh, blw = 0; /* bar geometry */
+ static int (*xerrorxlib)(Display *, XErrorEvent *);
+ static unsigned int numlockmask = 0;
++static int xkbEventType = 0;
+ static void (*handler[LASTEvent]) (XEvent *) = {
+ [ButtonPress] = buttonpress,
+ [ClientMessage] = clientmessage,
+@@ -266,6 +278,8 @@ static Drw *drw;
+ static Fnt *fnt;
+ static Monitor *mons, *selmon;
+ static Window root;
++static XkbInfo xkbGlobal;
++static XkbInfo *xkbSaved = NULL;
+
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+@@ -693,6 +707,7 @@ dirtomon(int dir) {
+ void
+ drawbar(Monitor *m) {
+ int x, xx, w;
++ int ww = 0;
+ unsigned int i, occ = 0, urg = 0;
+ Client *c;
+
+@@ -718,14 +733,23 @@ drawbar(Monitor *m) {
+ if(m == selmon) { /* status is only drawn on selected monitor */
+ w = TEXTW(stext);
+ x = m->ww - w;
++ if (showxkb) {
++ ww = TEXTW(xkb_layouts[xkbGlobal.group]);
++ x -= ww;
++ }
+ if(x < xx) {
+ x = xx;
+ w = m->ww - xx;
+ }
+ drw_text(drw, x, 0, w, bh, stext, 0);
++ if (showxkb) {
++ drw_setscheme(drw, &scheme[SchemeNorm]);
++ drw_text(drw, x+w, 0, ww, bh, xkb_layouts[xkbGlobal.group], 0);
++ }
+ }
+ else
+ x = m->ww;
++
+ if((w = x - xx) > bh) {
+ x = xx;
+ if(m->sel) {
+@@ -777,6 +801,18 @@ expose(XEvent *e) {
+ drawbar(m);
+ }
+
++XkbInfo *
++findxkb(Window w)
++{
++ XkbInfo *xkb;
++ for (xkb = xkbSaved; xkb != NULL; xkb=xkb->next) {
++ if (xkb->w == w) {
++ return xkb;
++ }
++ }
++ return NULL;
++}
++
+ void
+ focus(Client *c) {
+ if(!c || !ISVISIBLE(c))
+@@ -1008,6 +1044,7 @@ manage(Window w, XWindowAttributes *wa) {
+ Client *c, *t = NULL;
+ Window trans = None;
+ XWindowChanges wc;
++ XkbInfo *xkb;
+
+ if(!(c = calloc(1, sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+@@ -1038,6 +1075,24 @@ manage(Window w, XWindowAttributes *wa) {
+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ c->bw = borderpx;
+
++ /* Set current xkb state */
++ xkb = findxkb(c->win);
++ if (xkb == NULL) {
++ xkb = malloc(sizeof *xkb);
++ if (xkb == NULL) {
++ die("fatal: could not malloc() %u bytes\n", sizeof *xkb);
++ }
++ xkb->group = xkbGlobal.group;
++ xkb->w = c->win;
++ xkb->next = xkbSaved;
++ if (xkbSaved != NULL) {
++ xkbSaved->prev = xkb;
++ }
++ xkb->prev = NULL;
++ xkbSaved = xkb;
++ }
++ c->xkb = xkb;
++
+ wc.border_width = c->bw;
+ XConfigureWindow(dpy, w, CWBorderWidth, &wc);
+ XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb);
+@@ -1344,8 +1399,14 @@ run(void) {
+ /* main event loop */
+ XSync(dpy, False);
+ while(running && !XNextEvent(dpy, &ev))
++ {
++ if(ev.type == xkbEventType) {
++ xkbeventnotify(&ev);
++ continue;
++ }
+ if(handler[ev.type])
+ handler[ev.type](&ev); /* call handler */
++ }
+ }
+
+ void
+@@ -1428,6 +1489,7 @@ setfocus(Client *c) {
+ XChangeProperty(dpy, root, netatom[NetActiveWindow],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &(c->win), 1);
++ XkbLockGroup(dpy, XkbUseCoreKbd, c->xkb->group);
+ }
+ sendevent(c, wmatom[WMTakeFocus]);
+ }
+@@ -1490,6 +1552,7 @@ setmfact(const Arg *arg) {
+ void
+ setup(void) {
+ XSetWindowAttributes wa;
++ XkbStateRec xkbstate;
+
+ /* clean up any zombies immediately */
+ sigchld(0);
+@@ -1541,6 +1604,16 @@ setup(void) {
+ |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
+ XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
+ XSelectInput(dpy, root, wa.event_mask);
++
++ /* 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;
++
+ grabkeys();
+ focus(NULL);
+ }
+@@ -1687,6 +1760,7 @@ void
+ unmanage(Client *c, Bool destroyed) {
+ Monitor *m = c->mon;
+ XWindowChanges wc;
++ XkbInfo *xkb;
+
+ /* The server grab construct avoids race conditions. */
+ detach(c);
+@@ -1702,6 +1776,18 @@ unmanage(Client *c, Bool destroyed) {
+ XSetErrorHandler(xerror);
+ XUngrabServer(dpy);
+ }
++ 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);
++ }
++ }
+ free(c);
+ focus(NULL);
+ updateclientlist();
+@@ -2030,6 +2116,23 @@ xerrorstart(Display *dpy, XErrorEvent *ee) {
+ return -1;
+ }
+
++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;
++ }
++ if (showxkb) {
++ drawbars();
++ }
++ break;
++ }
++}
+ void
+ zoom(const Arg *arg) {
+ Client *c = selmon->sel;
diff --git a/dwm.suckless.org/patches/xkb.md b/dwm.suckless.org/patches/xkb.md
@@ -0,0 +1,24 @@
+xkb
+=====
+Description
+-----------
+This patch replaces main functionality of xxkb. It will remember the
+client's xkb status and restores it when client became focused.
+
+Applying
+--------
+Firstly you have to configure xkb as you need as described here:
+http://www.x.org/archive/X11R7.5/doc/input/XKB-Config.html
+The patch depends on two variables: showxkb flag defines, should patch show
+current xkb group on the bar; xkb_layouts array defines the text, which will
+appear on the bar according to current group if showxkb set to TRUE.
+
+Download
+--------
+
+ * [dwm-6.1-xkb.diff](dwm-6.1-xkb.diff) (2014-02-15)
+
+Author
+------
+
+ * Yury Shvedov - shved at lvk dot cs dot msu dot su (or mestofel13 at gmail dot com).