dwm-6.1-xkb.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) 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;