Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff - sites - public wiki content…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff (13021B)
---
1 From 9b5719969ce85c3ecc0238d49c0255c5c2cc79f0 Mon Sep 17 00:00:00 2001
2 From: mihirlad55 <[email protected]>
3 Date: Mon, 10 Aug 2020 01:39:28 +0000
4 Subject: [PATCH] Add support for managing external status bars
5
6 This patch allows dwm to manage other status bars such as
7 polybar/lemonbar without them needing to set override-redirect. For
8 all intents and purposes, DWM treats this bar as if it were its own
9 and as a result helps the status bar and DWM live in harmony.
10
11 This has a few advantages
12 * The bar does not block fullscreen windows
13 * DWM makes room for the status bar, so windows do not overlap the bar
14 * The bar can be hidden/killed and DWM will not keep an unsightly gap
15 where the bar was
16 * DWM receives EnterNotify events when your cursor enters the bar
17
18 To use another status bar, set usealtbar to 1 in your config.h and set
19 altbarclass to the class name (can be found using xprop) to the class
20 name of your status bar. Also make sure that if your status bar will
21 be displayed on top, topbar is set to 1 in your config, and if it will
22 be displayed on bottom, topbar is set to 0. This patch does not
23 support bars that are not docked at the top or at the bottom of your
24 monitor.
25
26 This verison of the patch fixes handling of polybar's tray.
27
28 The patch is developed at https://github.com/mihirlad55/dwm-anybar
29 ---
30 config.def.h | 4 ++
31 dwm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++----
32 2 files changed, 181 insertions(+), 15 deletions(-)
33
34 diff --git a/config.def.h b/config.def.h
35 index 1c0b587..f45211b 100644
36 --- a/config.def.h
37 +++ b/config.def.h
38 @@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* bord…
39 static const unsigned int snap = 32; /* snap pixel */
40 static const int showbar = 1; /* 0 means no bar */
41 static const int topbar = 1; /* 0 means bottom bar */
42 +static const int usealtbar = 1; /* 1 means use non-dwm …
43 +static const char *altbarclass = "Polybar"; /* Alternate bar class…
44 +static const char *alttrayname = "tray"; /* Polybar tray instan…
45 +static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar …
46 static const char *fonts[] = { "monospace:size=10" };
47 static const char dmenufont[] = "monospace:size=10";
48 static const char col_gray1[] = "#222222";
49 diff --git a/dwm.c b/dwm.c
50 index 9fd0286..c1d8ce0 100644
51 --- a/dwm.c
52 +++ b/dwm.c
53 @@ -47,8 +47,8 @@
54 /* macros */
55 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
56 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (Shif…
57 -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - …
58 - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - …
59 +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - …
60 + * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - …
61 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->selt…
62 #define LENGTH(X) (sizeof X / sizeof X[0])
63 #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
64 @@ -116,7 +116,8 @@ struct Monitor {
65 float mfact;
66 int nmaster;
67 int num;
68 - int by; /* bar geometry */
69 + int by, bh; /* bar geometry */
70 + int tx, tw; /* bar tray geometry */
71 int mx, my, mw, mh; /* screen size */
72 int wx, wy, ww, wh; /* window area */
73 unsigned int seltags;
74 @@ -129,6 +130,7 @@ struct Monitor {
75 Client *stack;
76 Monitor *next;
77 Window barwin;
78 + Window traywin;
79 const Layout *lt[2];
80 };
81
82 @@ -179,6 +181,8 @@ static void incnmaster(const Arg *arg);
83 static void keypress(XEvent *e);
84 static void killclient(const Arg *arg);
85 static void manage(Window w, XWindowAttributes *wa);
86 +static void managealtbar(Window win, XWindowAttributes *wa);
87 +static void managetray(Window win, XWindowAttributes *wa);
88 static void mappingnotify(XEvent *e);
89 static void maprequest(XEvent *e);
90 static void monocle(Monitor *m);
91 @@ -195,6 +199,7 @@ static void resizemouse(const Arg *arg);
92 static void restack(Monitor *m);
93 static void run(void);
94 static void scan(void);
95 +static void scantray(void);
96 static int sendevent(Client *c, Atom proto);
97 static void sendmon(Client *c, Monitor *m);
98 static void setclientstate(Client *c, long state);
99 @@ -207,6 +212,7 @@ static void seturgent(Client *c, int urg);
100 static void showhide(Client *c);
101 static void sigchld(int unused);
102 static void spawn(const Arg *arg);
103 +static void spawnbar();
104 static void tag(const Arg *arg);
105 static void tagmon(const Arg *arg);
106 static void tile(Monitor *);
107 @@ -216,6 +222,8 @@ static void toggletag(const Arg *arg);
108 static void toggleview(const Arg *arg);
109 static void unfocus(Client *c, int setfocus);
110 static void unmanage(Client *c, int destroyed);
111 +static void unmanagealtbar(Window w);
112 +static void unmanagetray(Window w);
113 static void unmapnotify(XEvent *e);
114 static void updatebarpos(Monitor *m);
115 static void updatebars(void);
116 @@ -230,6 +238,7 @@ static void updatewmhints(Client *c);
117 static void view(const Arg *arg);
118 static Client *wintoclient(Window w);
119 static Monitor *wintomon(Window w);
120 +static int wmclasscontains(Window win, const char *class, const char *n…
121 static int xerror(Display *dpy, XErrorEvent *ee);
122 static int xerrordummy(Display *dpy, XErrorEvent *ee);
123 static int xerrorstart(Display *dpy, XErrorEvent *ee);
124 @@ -505,8 +514,10 @@ cleanupmon(Monitor *mon)
125 for (m = mons; m && m->next != mon; m = m->next);
126 m->next = mon->next;
127 }
128 - XUnmapWindow(dpy, mon->barwin);
129 - XDestroyWindow(dpy, mon->barwin);
130 + if (!usealtbar) {
131 + XUnmapWindow(dpy, mon->barwin);
132 + XDestroyWindow(dpy, mon->barwin);
133 + }
134 free(mon);
135 }
136
137 @@ -568,7 +579,7 @@ configurenotify(XEvent *e)
138 for (c = m->clients; c; c = c->next)
139 if (c->isfullscreen)
140 resizeclient(c, m->mx, …
141 - XMoveResizeWindow(dpy, m->barwin, m->wx…
142 + XMoveResizeWindow(dpy, m->barwin, m->wx…
143 }
144 focus(NULL);
145 arrange(NULL);
146 @@ -639,6 +650,7 @@ createmon(void)
147 m->nmaster = nmaster;
148 m->showbar = showbar;
149 m->topbar = topbar;
150 + m->bh = bh;
151 m->lt[0] = &layouts[0];
152 m->lt[1] = &layouts[1 % LENGTH(layouts)];
153 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
154 @@ -649,10 +661,15 @@ void
155 destroynotify(XEvent *e)
156 {
157 Client *c;
158 + Monitor *m;
159 XDestroyWindowEvent *ev = &e->xdestroywindow;
160
161 if ((c = wintoclient(ev->window)))
162 unmanage(c, 1);
163 + else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
164 + unmanagealtbar(ev->window);
165 + else if (m->traywin == ev->window)
166 + unmanagetray(ev->window);
167 }
168
169 void
170 @@ -696,6 +713,9 @@ dirtomon(int dir)
171 void
172 drawbar(Monitor *m)
173 {
174 + if (usealtbar)
175 + return;
176 +
177 int x, w, tw = 0;
178 int boxs = drw->fonts->h / 9;
179 int boxw = drw->fonts->h / 6 + 2;
180 @@ -1077,6 +1097,45 @@ manage(Window w, XWindowAttributes *wa)
181 focus(NULL);
182 }
183
184 +void
185 +managealtbar(Window win, XWindowAttributes *wa)
186 +{
187 + Monitor *m;
188 + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
189 + return;
190 +
191 + m->barwin = win;
192 + m->by = wa->y;
193 + bh = m->bh = wa->height;
194 + updatebarpos(m);
195 + arrange(m);
196 + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|Property…
197 + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height…
198 + XMapWindow(dpy, win);
199 + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 3…
200 + (unsigned char *) &win, 1);
201 +}
202 +
203 +void
204 +managetray(Window win, XWindowAttributes *wa)
205 +{
206 + Monitor *m;
207 + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
208 + return;
209 +
210 + m->traywin = win;
211 + m->tx = wa->x;
212 + m->tw = wa->width;
213 + updatebarpos(m);
214 + arrange(m);
215 + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|Property…
216 + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height…
217 + XMapWindow(dpy, win);
218 + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 3…
219 + (unsigned char *) &win, 1);
220 +}
221 +
222 +
223 void
224 mappingnotify(XEvent *e)
225 {
226 @@ -1097,7 +1156,9 @@ maprequest(XEvent *e)
227 return;
228 if (wa.override_redirect)
229 return;
230 - if (!wintoclient(ev->window))
231 + if (wmclasscontains(ev->window, altbarclass, ""))
232 + managealtbar(ev->window, &wa);
233 + else if (!wintoclient(ev->window))
234 manage(ev->window, &wa);
235 }
236
237 @@ -1393,7 +1454,9 @@ scan(void)
238 if (!XGetWindowAttributes(dpy, wins[i], &wa)
239 || wa.override_redirect || XGetTransientForHint…
240 continue;
241 - if (wa.map_state == IsViewable || getstate(wins…
242 + if (wmclasscontains(wins[i], altbarclass, ""))
243 + managealtbar(wins[i], &wa);
244 + else if (wa.map_state == IsViewable || getstate…
245 manage(wins[i], &wa);
246 }
247 for (i = 0; i < num; i++) { /* now the transients */
248 @@ -1408,6 +1471,29 @@ scan(void)
249 }
250 }
251
252 +void
253 +scantray(void)
254 +{
255 + unsigned int num;
256 + Window d1, d2, *wins = NULL;
257 + XWindowAttributes wa;
258 +
259 + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
260 + for (unsigned int i = 0; i < num; i++) {
261 + if (wmclasscontains(wins[i], altbarclass, alttr…
262 + if (!XGetWindowAttributes(dpy, wins[i],…
263 + break;
264 + managetray(wins[i], &wa);
265 + }
266 + }
267 + }
268 +
269 + if (wins)
270 + XFree(wins);
271 +}
272 +
273 +
274 +
275 void
276 sendmon(Client *c, Monitor *m)
277 {
278 @@ -1546,7 +1632,7 @@ setup(void)
279 if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
280 die("no fonts could be loaded.");
281 lrpad = drw->fonts->h;
282 - bh = drw->fonts->h + 2;
283 + bh = usealtbar ? 0 : drw->fonts->h + 2;
284 updategeom();
285 /* init atoms */
286 utf8string = XInternAtom(dpy, "UTF8_STRING", False);
287 @@ -1595,6 +1681,7 @@ setup(void)
288 XSelectInput(dpy, root, wa.event_mask);
289 grabkeys();
290 focus(NULL);
291 + spawnbar();
292 }
293
294
295 @@ -1653,6 +1740,13 @@ spawn(const Arg *arg)
296 }
297 }
298
299 +void
300 +spawnbar()
301 +{
302 + if (*altbarcmd)
303 + system(altbarcmd);
304 +}
305 +
306 void
307 tag(const Arg *arg)
308 {
309 @@ -1702,9 +1796,18 @@ tile(Monitor *m)
310 void
311 togglebar(const Arg *arg)
312 {
313 + /**
314 + * Polybar tray does not raise maprequest event. It must be manuall…
315 + * for. Scanning it too early while the tray is being populated…
316 + * wrong dimensions.
317 + */
318 + if (!selmon->traywin)
319 + scantray();
320 +
321 selmon->showbar = !selmon->showbar;
322 updatebarpos(selmon);
323 - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, …
324 + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, …
325 + XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by,…
326 arrange(selmon);
327 }
328
329 @@ -1787,10 +1890,41 @@ unmanage(Client *c, int destroyed)
330 arrange(m);
331 }
332
333 +void
334 +unmanagealtbar(Window w)
335 +{
336 + Monitor *m = wintomon(w);
337 +
338 + if (!m)
339 + return;
340 +
341 + m->barwin = 0;
342 + m->by = 0;
343 + m->bh = 0;
344 + updatebarpos(m);
345 + arrange(m);
346 +}
347 +
348 +void
349 +unmanagetray(Window w)
350 +{
351 + Monitor *m = wintomon(w);
352 +
353 + if (!m)
354 + return;
355 +
356 + m->traywin = 0;
357 + m->tx = 0;
358 + m->tw = 0;
359 + updatebarpos(m);
360 + arrange(m);
361 +}
362 +
363 void
364 unmapnotify(XEvent *e)
365 {
366 Client *c;
367 + Monitor *m;
368 XUnmapEvent *ev = &e->xunmap;
369
370 if ((c = wintoclient(ev->window))) {
371 @@ -1798,12 +1932,18 @@ unmapnotify(XEvent *e)
372 setclientstate(c, WithdrawnState);
373 else
374 unmanage(c, 0);
375 - }
376 + } else if ((m = wintomon(ev->window)) && m->barwin == ev->windo…
377 + unmanagealtbar(ev->window);
378 + else if (m->traywin == ev->window)
379 + unmanagetray(ev->window);
380 }
381
382 void
383 updatebars(void)
384 {
385 + if (usealtbar)
386 + return;
387 +
388 Monitor *m;
389 XSetWindowAttributes wa = {
390 .override_redirect = True,
391 @@ -1829,11 +1969,11 @@ updatebarpos(Monitor *m)
392 m->wy = m->my;
393 m->wh = m->mh;
394 if (m->showbar) {
395 - m->wh -= bh;
396 + m->wh -= m->bh;
397 m->by = m->topbar ? m->wy : m->wy + m->wh;
398 - m->wy = m->topbar ? m->wy + bh : m->wy;
399 + m->wy = m->topbar ? m->wy + m->bh : m->wy;
400 } else
401 - m->by = -bh;
402 + m->by = -m->bh;
403 }
404
405 void
406 @@ -2070,13 +2210,35 @@ wintomon(Window w)
407 if (w == root && getrootptr(&x, &y))
408 return recttomon(x, y, 1, 1);
409 for (m = mons; m; m = m->next)
410 - if (w == m->barwin)
411 + if (w == m->barwin || w == m->traywin)
412 return m;
413 if ((c = wintoclient(w)))
414 return c->mon;
415 return selmon;
416 }
417
418 +int
419 +wmclasscontains(Window win, const char *class, const char *name)
420 +{
421 + XClassHint ch = { NULL, NULL };
422 + int res = 1;
423 +
424 + if (XGetClassHint(dpy, win, &ch)) {
425 + if (ch.res_name && strstr(ch.res_name, name) == NULL)
426 + res = 0;
427 + if (ch.res_class && strstr(ch.res_class, class) == NULL)
428 + res = 0;
429 + } else
430 + res = 0;
431 +
432 + if (ch.res_class)
433 + XFree(ch.res_class);
434 + if (ch.res_name)
435 + XFree(ch.res_name);
436 +
437 + return res;
438 +}
439 +
440 /* There's no way to check accesses to destroyed windows, thus those ca…
441 * ignored (especially on UnmapNotify's). Other types of errors call Xl…
442 * default error handler, which may call exit. */
443 --
444 2.28.0
445
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.