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;