dwm-6.1-xkb.diff - 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 … | |
10 - { "Gimp", NULL, NULL, 0, True, … | |
11 - { "Firefox", NULL, NULL, 1 << 8, False, … | |
12 + /* class instance title tags mask isfloating … | |
13 + { "Gimp", NULL, NULL, 0, True, … | |
14 + { "Firefox", NULL, NULL, 1 << 8, False, … | |
15 }; | |
16 | |
17 /* layout(s) */ | |
18 @@ -31,6 +31,13 @@ static const float mfact = 0.55; /* factor of ma… | |
19 static const int nmaster = 1; /* number of clients in master ar… | |
20 static const Bool resizehints = True; /* True means respect size hints … | |
21 | |
22 +/* xkb frontend */ | |
23 +static const Bool showxkb = True; /* False means no xkb layout … | |
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 geo… | |
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-… | |
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],… | |
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(Clie… | |
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(tra… | |
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|StructureNotif… | |
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; |