--- config.def.h | 13 ++++-- dwm.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 061ad66..4170feb 100644 --- a/config.def.h +++ b/config.def.h _AT_@ -26,9 +26,9 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + /* class instance title tags mask isfloating monitor xkb_layout */ + { "Gimp", NULL, NULL, 0, 1, -1, 0 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1, -1 }, }; /* layout(s) */ _AT_@ -37,6 +37,13 @@ static const int nmaster = 1; /* number of clients in master area */ static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +/* 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 e5efb6a..5e3e3ca 100644 --- a/dwm.c +++ b/dwm.c _AT_@ -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 */ _AT_@ -84,6 +85,7 @@ typedef struct { typedef struct Monitor Monitor; typedef struct Client Client; +typedef struct XkbInfo XkbInfo; struct Client { char name[256]; float mina, maxa; _AT_@ -97,6 +99,13 @@ struct Client { Client *snext; Monitor *mon; Window win; + XkbInfo *xkb; +}; +struct XkbInfo { + XkbInfo *next; + XkbInfo *prev; + int group; + Window w; }; typedef struct { _AT_@ -139,6 +148,7 @@ typedef struct { unsigned int tags; int isfloating; int monitor; + int xkb_layout; } Rule; /* function declarations */ _AT_@ -157,6 +167,7 @@ static void configure(Client *c); static void configurenotify(XEvent *e); static void configurerequest(XEvent *e); static Monitor *createmon(void); +static XkbInfo *createxkb(Window w); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); _AT_@ -165,6 +176,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); _AT_@ -233,6 +245,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 */ _AT_@ -244,6 +257,7 @@ static int bh; /* bar height */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; +static int xkbEventType = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, [ClientMessage] = clientmessage, _AT_@ -268,6 +282,8 @@ static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +static XkbInfo xkbGlobal; +static XkbInfo *xkbSaved = NULL; /* configuration, allows nested code to access above variables */ #include "config.h" _AT_@ -303,6 +319,9 @@ applyrules(Client *c) for (m = mons; m && m->num != r->monitor; m = m->next); if (m) c->mon = m; + if(r->xkb_layout > -1 ) { + c->xkb->group = r->xkb_layout; + } } } if (ch.res_class) _AT_@ -647,6 +666,25 @@ createmon(void) strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); return m; } +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; +} void destroynotify(XEvent *e) _AT_@ -700,6 +738,7 @@ void drawbar(Monitor *m) { int x, w, tw = 0; + int ww = 0; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; _AT_@ -712,7 +751,15 @@ drawbar(Monitor *m) if (m == selmon) { /* status is only drawn on selected monitor */ drw_setscheme(drw, scheme[SchemeNorm]); tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + if (showxkb) { + ww = TEXTW(xkb_layouts[xkbGlobal.group]); + } drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + if (showxkb) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, m->ww - tw - ww, 0, ww, bh, 0, xkb_layouts[xkbGlobal.group], 0); + tw += ww; + } } for (c = m->clients; c; c = c->next) { _AT_@ -777,6 +824,18 @@ enternotify(XEvent *e) focus(c); } +XkbInfo * +findxkb(Window w) +{ + XkbInfo *xkb; + for (xkb = xkbSaved; xkb != NULL; xkb=xkb->next) { + if (xkb->w == w) { + return xkb; + } + } + return NULL; +} + void expose(XEvent *e) { _AT_@ -1025,6 +1084,7 @@ manage(Window w, XWindowAttributes *wa) Client *c, *t = NULL; Window trans = None; XWindowChanges wc; + XkbInfo *xkb; c = ecalloc(1, sizeof(Client)); c->win = w; _AT_@ -1036,6 +1096,14 @@ manage(Window w, XWindowAttributes *wa) c->oldbw = wa->border_width; updatetitle(c); + + /* Setting current xkb state must be before applyrules */ + xkb = findxkb(c->win); + if (xkb == NULL) { + xkb = createxkb(c->win); + } + c->xkb = xkb; + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; c->tags = t->tags; _AT_@ -1377,8 +1445,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 _AT_@ -1466,6 +1540,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]); } _AT_@ -1533,6 +1608,7 @@ setup(void) int i; XSetWindowAttributes wa; Atom utf8string; + XkbStateRec xkbstate; /* clean up any zombies immediately */ sigchld(0); _AT_@ -1593,6 +1669,16 @@ setup(void) |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); } _AT_@ -1762,6 +1848,7 @@ unmanage(Client *c, int destroyed) { Monitor *m = c->mon; XWindowChanges wc; + XkbInfo *xkb; detach(c); detachstack(c); _AT_@ -1777,6 +1864,18 @@ unmanage(Client *c, int 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(); _AT_@ -2110,6 +2209,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) { -- 2.38.1Received on Wed Nov 30 2022 - 21:38:05 CET
This archive was generated by hypermail 2.3.0 : Wed Nov 30 2022 - 22:12:32 CET