sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-6.1-xkb.diff (8882B)


      1 diff --git a/config.def.h b/config.def.h
      2 index 875885b..780ff6f 100644
      3 --- a/config.def.h
      4 +++ b/config.def.h
      5 @@ -21,9 +21,9 @@ static const Rule rules[] = {
      6  	 *	WM_CLASS(STRING) = instance, class
      7  	 *	WM_NAME(STRING) = title
      8  	 */
      9 -	/* class      instance    title       tags mask     isfloating   monitor */
     10 -	{ "Gimp",     NULL,       NULL,       0,            True,        -1 },
     11 -	{ "Firefox",  NULL,       NULL,       1 << 8,       False,       -1 },
     12 +	/* class      instance    title       tags mask     isfloating   monitor xkb_layout */
     13 +	{ "Gimp",     NULL,       NULL,       0,            True,        -1,     0 },
     14 +	{ "Firefox",  NULL,       NULL,       1 << 8,       False,       -1,     -1 },
     15  };
     16  
     17  /* layout(s) */
     18 @@ -31,6 +31,13 @@ static const float mfact      = 0.55; /* factor of master area size [0.05..0.95]
     19  static const int nmaster      = 1;    /* number of clients in master area */
     20  static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
     21  
     22 +/* xkb frontend */
     23 +static const Bool showxkb         = True; /* False means no xkb layout text */
     24 +static const char *xkb_layouts [] = {
     25 +    "en",
     26 +    "ru",
     27 +};
     28 +
     29  static const Layout layouts[] = {
     30  	/* symbol     arrange function */
     31  	{ "[]=",      tile },    /* first entry is default */
     32 diff --git a/dwm.c b/dwm.c
     33 index 1bbb4b3..ec39eef 100644
     34 --- a/dwm.c
     35 +++ b/dwm.c
     36 @@ -36,6 +36,7 @@
     37  #include <X11/Xlib.h>
     38  #include <X11/Xproto.h>
     39  #include <X11/Xutil.h>
     40 +#include <X11/XKBlib.h>
     41  #ifdef XINERAMA
     42  #include <X11/extensions/Xinerama.h>
     43  #endif /* XINERAMA */
     44 @@ -83,6 +84,7 @@ typedef struct {
     45  
     46  typedef struct Monitor Monitor;
     47  typedef struct Client Client;
     48 +typedef struct XkbInfo XkbInfo;
     49  struct Client {
     50  	char name[256];
     51  	float mina, maxa;
     52 @@ -96,6 +98,13 @@ struct Client {
     53  	Client *snext;
     54  	Monitor *mon;
     55  	Window win;
     56 +    XkbInfo *xkb;
     57 +};
     58 +struct XkbInfo {
     59 +    XkbInfo *next;
     60 +    XkbInfo *prev;
     61 +    int group;
     62 +    Window w;
     63  };
     64  
     65  typedef struct {
     66 @@ -138,6 +147,7 @@ typedef struct {
     67  	unsigned int tags;
     68  	Bool isfloating;
     69  	int monitor;
     70 +    int xkb_layout;
     71  } Rule;
     72  
     73  /* function declarations */
     74 @@ -157,6 +167,7 @@ static void configure(Client *c);
     75  static void configurenotify(XEvent *e);
     76  static void configurerequest(XEvent *e);
     77  static Monitor *createmon(void);
     78 +static XkbInfo *createxkb(Window w);
     79  static void destroynotify(XEvent *e);
     80  static void detach(Client *c);
     81  static void detachstack(Client *c);
     82 @@ -165,6 +176,7 @@ static void drawbar(Monitor *m);
     83  static void drawbars(void);
     84  static void enternotify(XEvent *e);
     85  static void expose(XEvent *e);
     86 +static XkbInfo *findxkb(Window w);
     87  static void focus(Client *c);
     88  static void focusin(XEvent *e);
     89  static void focusmon(const Arg *arg);
     90 @@ -231,6 +243,7 @@ static Monitor *wintomon(Window w);
     91  static int xerror(Display *dpy, XErrorEvent *ee);
     92  static int xerrordummy(Display *dpy, XErrorEvent *ee);
     93  static int xerrorstart(Display *dpy, XErrorEvent *ee);
     94 +static void xkbeventnotify(XEvent *e);
     95  static void zoom(const Arg *arg);
     96  
     97  /* variables */
     98 @@ -241,6 +254,7 @@ static int sw, sh;           /* X display screen geometry width, height */
     99  static int bh, blw = 0;      /* bar geometry */
    100  static int (*xerrorxlib)(Display *, XErrorEvent *);
    101  static unsigned int numlockmask = 0;
    102 +static int xkbEventType = 0;
    103  static void (*handler[LASTEvent]) (XEvent *) = {
    104  	[ButtonPress] = buttonpress,
    105  	[ClientMessage] = clientmessage,
    106 @@ -266,6 +280,8 @@ static Drw *drw;
    107  static Fnt *fnt;
    108  static Monitor *mons, *selmon;
    109  static Window root;
    110 +static XkbInfo xkbGlobal;
    111 +static XkbInfo *xkbSaved = NULL;
    112  
    113  /* configuration, allows nested code to access above variables */
    114  #include "config.h"
    115 @@ -299,6 +315,9 @@ applyrules(Client *c) {
    116  			for(m = mons; m && m->num != r->monitor; m = m->next);
    117  			if(m)
    118  				c->mon = m;
    119 +            if(r->xkb_layout > -1 ) {
    120 +                c->xkb->group = r->xkb_layout;
    121 +            }
    122  		}
    123  	}
    124  	if(ch.res_class)
    125 @@ -644,6 +663,25 @@ createmon(void) {
    126  	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
    127  	return m;
    128  }
    129 +static XkbInfo *
    130 +createxkb(Window w){
    131 +    XkbInfo *xkb;
    132 +
    133 +    xkb = malloc(sizeof *xkb);
    134 +    if (xkb == NULL) {
    135 +        die("fatal: could not malloc() %u bytes\n", sizeof *xkb);
    136 +    }
    137 +    xkb->group = xkbGlobal.group;
    138 +    xkb->w = w;
    139 +    xkb->next = xkbSaved;
    140 +    if (xkbSaved != NULL) {
    141 +        xkbSaved->prev = xkb;
    142 +    }
    143 +    xkb->prev = NULL;
    144 +    xkbSaved = xkb;
    145 +
    146 +    return xkb;
    147 +}
    148  
    149  void
    150  destroynotify(XEvent *e) {
    151 @@ -693,6 +731,7 @@ dirtomon(int dir) {
    152  void
    153  drawbar(Monitor *m) {
    154  	int x, xx, w;
    155 +    int ww = 0;
    156  	unsigned int i, occ = 0, urg = 0;
    157  	Client *c;
    158  
    159 @@ -718,14 +757,23 @@ drawbar(Monitor *m) {
    160  	if(m == selmon) { /* status is only drawn on selected monitor */
    161  		w = TEXTW(stext);
    162  		x = m->ww - w;
    163 +        if (showxkb) {
    164 +            ww = TEXTW(xkb_layouts[xkbGlobal.group]);
    165 +            x -= ww;
    166 +        }
    167  		if(x < xx) {
    168  			x = xx;
    169  			w = m->ww - xx;
    170  		}
    171  		drw_text(drw, x, 0, w, bh, stext, 0);
    172 +        if (showxkb) {
    173 +            drw_setscheme(drw, &scheme[SchemeNorm]);
    174 +            drw_text(drw, x+w, 0, ww, bh, xkb_layouts[xkbGlobal.group], 0);
    175 +        }
    176  	}
    177  	else
    178  		x = m->ww;
    179 +
    180  	if((w = x - xx) > bh) {
    181  		x = xx;
    182  		if(m->sel) {
    183 @@ -777,6 +825,18 @@ expose(XEvent *e) {
    184  		drawbar(m);
    185  }
    186  
    187 +XkbInfo *
    188 +findxkb(Window w)
    189 +{
    190 +    XkbInfo *xkb;
    191 +    for (xkb = xkbSaved; xkb != NULL; xkb=xkb->next) {
    192 +        if (xkb->w == w) {
    193 +            return xkb;
    194 +        }
    195 +    }
    196 +    return NULL;
    197 +}
    198 +
    199  void
    200  focus(Client *c) {
    201  	if(!c || !ISVISIBLE(c))
    202 @@ -1008,11 +1068,20 @@ manage(Window w, XWindowAttributes *wa) {
    203  	Client *c, *t = NULL;
    204  	Window trans = None;
    205  	XWindowChanges wc;
    206 +    XkbInfo *xkb;
    207  
    208  	if(!(c = calloc(1, sizeof(Client))))
    209  		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
    210  	c->win = w;
    211  	updatetitle(c);
    212 +
    213 +    /* Setting current xkb state must be before applyrules */
    214 +    xkb = findxkb(c->win);
    215 +    if (xkb == NULL) {
    216 +        xkb = createxkb(c->win);
    217 +    }
    218 +    c->xkb = xkb;
    219 +
    220  	if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
    221  		c->mon = t->mon;
    222  		c->tags = t->tags;
    223 @@ -1344,8 +1413,14 @@ run(void) {
    224  	/* main event loop */
    225  	XSync(dpy, False);
    226  	while(running && !XNextEvent(dpy, &ev))
    227 +    {
    228 +        if(ev.type == xkbEventType) {
    229 +            xkbeventnotify(&ev);
    230 +            continue;
    231 +        }
    232  		if(handler[ev.type])
    233  			handler[ev.type](&ev); /* call handler */
    234 +    }
    235  }
    236  
    237  void
    238 @@ -1428,6 +1503,7 @@ setfocus(Client *c) {
    239  		XChangeProperty(dpy, root, netatom[NetActiveWindow],
    240   		                XA_WINDOW, 32, PropModeReplace,
    241   		                (unsigned char *) &(c->win), 1);
    242 +        XkbLockGroup(dpy, XkbUseCoreKbd, c->xkb->group);
    243  	}
    244  	sendevent(c, wmatom[WMTakeFocus]);
    245  }
    246 @@ -1490,6 +1566,7 @@ setmfact(const Arg *arg) {
    247  void
    248  setup(void) {
    249  	XSetWindowAttributes wa;
    250 +    XkbStateRec xkbstate;
    251  
    252  	/* clean up any zombies immediately */
    253  	sigchld(0);
    254 @@ -1541,6 +1618,16 @@ setup(void) {
    255  	                |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
    256  	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
    257  	XSelectInput(dpy, root, wa.event_mask);
    258 +
    259 +    /* get xkb extension info, events and current state */
    260 +    if (!XkbQueryExtension(dpy, NULL, &xkbEventType, NULL, NULL, NULL)) {
    261 +		fputs("warning: can not query xkb extension\n", stderr);
    262 +    }
    263 +    XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify,
    264 +                          XkbAllStateComponentsMask, XkbGroupStateMask);
    265 +    XkbGetState(dpy, XkbUseCoreKbd, &xkbstate);
    266 +    xkbGlobal.group = xkbstate.locked_group;
    267 +
    268  	grabkeys();
    269  	focus(NULL);
    270  }
    271 @@ -1687,6 +1774,7 @@ void
    272  unmanage(Client *c, Bool destroyed) {
    273  	Monitor *m = c->mon;
    274  	XWindowChanges wc;
    275 +    XkbInfo *xkb;
    276  
    277  	/* The server grab construct avoids race conditions. */
    278  	detach(c);
    279 @@ -1702,6 +1790,18 @@ unmanage(Client *c, Bool destroyed) {
    280  		XSetErrorHandler(xerror);
    281  		XUngrabServer(dpy);
    282  	}
    283 +    else {
    284 +        xkb = findxkb(c->win);
    285 +        if (xkb != NULL) {
    286 +            if (xkb->prev) {
    287 +                xkb->prev->next = xkb->next;
    288 +            }
    289 +            if (xkb->next) {
    290 +                xkb->next->prev = xkb->prev;
    291 +            }
    292 +            free(xkb);
    293 +        }
    294 +    }
    295  	free(c);
    296  	focus(NULL);
    297  	updateclientlist();
    298 @@ -2030,6 +2130,23 @@ xerrorstart(Display *dpy, XErrorEvent *ee) {
    299  	return -1;
    300  }
    301  
    302 +void xkbeventnotify(XEvent *e)
    303 +{
    304 +    XkbEvent *ev;
    305 +
    306 +    ev = (XkbEvent *) e;
    307 +    switch (ev->any.xkb_type) {
    308 +    case XkbStateNotify:
    309 +        xkbGlobal.group = ev->state.locked_group;
    310 +        if (selmon != NULL && selmon->sel != NULL) {
    311 +            selmon->sel->xkb->group = xkbGlobal.group;
    312 +        }
    313 +        if (showxkb) {
    314 +            drawbars();
    315 +        }
    316 +        break;
    317 +    }
    318 +}
    319  void
    320  zoom(const Arg *arg) {
    321  	Client *c = selmon->sel;