dwm-anybar-20200721-bb2e722.diff (9691B)
1 From 31a6d3319c4299dcc6ea9735e12ee2a437a889e4 Mon Sep 17 00:00:00 2001 2 From: mihirlad55 <mihirlad55@gmail.com> 3 Date: Tue, 21 Jul 2020 01:32:07 +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 The patch is developed at https://github.com/mihirlad55/dwm-anybar 27 --- 28 config.def.h | 2 + 29 dwm.c | 105 ++++++++++++++++++++++++++++++++++++++++++++------- 30 2 files changed, 93 insertions(+), 14 deletions(-) 31 32 diff --git a/config.def.h b/config.def.h 33 index 1c0b587..cb32018 100644 34 --- a/config.def.h 35 +++ b/config.def.h 36 @@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ 37 static const unsigned int snap = 32; /* snap pixel */ 38 static const int showbar = 1; /* 0 means no bar */ 39 static const int topbar = 1; /* 0 means bottom bar */ 40 +static const int usealtbar = 1; /* 1 means use non-dwm status bar */ 41 +static const char *altbarclass = "Polybar"; /* Alternate bar class name */ 42 static const char *fonts[] = { "monospace:size=10" }; 43 static const char dmenufont[] = "monospace:size=10"; 44 static const char col_gray1[] = "#222222"; 45 diff --git a/dwm.c b/dwm.c 46 index 9fd0286..74ec400 100644 47 --- a/dwm.c 48 +++ b/dwm.c 49 @@ -47,8 +47,8 @@ 50 /* macros */ 51 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) 52 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) 53 -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 54 - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 55 +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ 56 + * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) 57 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) 58 #define LENGTH(X) (sizeof X / sizeof X[0]) 59 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) 60 @@ -116,7 +116,7 @@ struct Monitor { 61 float mfact; 62 int nmaster; 63 int num; 64 - int by; /* bar geometry */ 65 + int by, bh; /* bar geometry */ 66 int mx, my, mw, mh; /* screen size */ 67 int wx, wy, ww, wh; /* window area */ 68 unsigned int seltags; 69 @@ -179,6 +179,7 @@ static void incnmaster(const Arg *arg); 70 static void keypress(XEvent *e); 71 static void killclient(const Arg *arg); 72 static void manage(Window w, XWindowAttributes *wa); 73 +static void managealtbar(Window win, XWindowAttributes *wa); 74 static void mappingnotify(XEvent *e); 75 static void maprequest(XEvent *e); 76 static void monocle(Monitor *m); 77 @@ -216,6 +217,7 @@ static void toggletag(const Arg *arg); 78 static void toggleview(const Arg *arg); 79 static void unfocus(Client *c, int setfocus); 80 static void unmanage(Client *c, int destroyed); 81 +static void unmanagealtbar(Window w); 82 static void unmapnotify(XEvent *e); 83 static void updatebarpos(Monitor *m); 84 static void updatebars(void); 85 @@ -230,6 +232,7 @@ static void updatewmhints(Client *c); 86 static void view(const Arg *arg); 87 static Client *wintoclient(Window w); 88 static Monitor *wintomon(Window w); 89 +static int wmclasscontains(Window win, const char *class, const char *name); 90 static int xerror(Display *dpy, XErrorEvent *ee); 91 static int xerrordummy(Display *dpy, XErrorEvent *ee); 92 static int xerrorstart(Display *dpy, XErrorEvent *ee); 93 @@ -505,8 +508,10 @@ cleanupmon(Monitor *mon) 94 for (m = mons; m && m->next != mon; m = m->next); 95 m->next = mon->next; 96 } 97 - XUnmapWindow(dpy, mon->barwin); 98 - XDestroyWindow(dpy, mon->barwin); 99 + if (!usealtbar) { 100 + XUnmapWindow(dpy, mon->barwin); 101 + XDestroyWindow(dpy, mon->barwin); 102 + } 103 free(mon); 104 } 105 106 @@ -568,7 +573,7 @@ configurenotify(XEvent *e) 107 for (c = m->clients; c; c = c->next) 108 if (c->isfullscreen) 109 resizeclient(c, m->mx, m->my, m->mw, m->mh); 110 - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); 111 + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh); 112 } 113 focus(NULL); 114 arrange(NULL); 115 @@ -639,6 +644,7 @@ createmon(void) 116 m->nmaster = nmaster; 117 m->showbar = showbar; 118 m->topbar = topbar; 119 + m->bh = bh; 120 m->lt[0] = &layouts[0]; 121 m->lt[1] = &layouts[1 % LENGTH(layouts)]; 122 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); 123 @@ -649,10 +655,13 @@ void 124 destroynotify(XEvent *e) 125 { 126 Client *c; 127 + Monitor *m; 128 XDestroyWindowEvent *ev = &e->xdestroywindow; 129 130 if ((c = wintoclient(ev->window))) 131 unmanage(c, 1); 132 + else if ((m = wintomon(ev->window)) && m->barwin == ev->window) 133 + unmanagealtbar(ev->window); 134 } 135 136 void 137 @@ -696,6 +705,9 @@ dirtomon(int dir) 138 void 139 drawbar(Monitor *m) 140 { 141 + if (usealtbar) 142 + return; 143 + 144 int x, w, tw = 0; 145 int boxs = drw->fonts->h / 9; 146 int boxw = drw->fonts->h / 6 + 2; 147 @@ -1077,6 +1089,25 @@ manage(Window w, XWindowAttributes *wa) 148 focus(NULL); 149 } 150 151 +void 152 +managealtbar(Window win, XWindowAttributes *wa) 153 +{ 154 + Monitor *m; 155 + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) 156 + return; 157 + 158 + m->barwin = win; 159 + m->by = wa->y; 160 + bh = m->bh = wa->height; 161 + updatebarpos(m); 162 + arrange(m); 163 + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); 164 + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); 165 + XMapWindow(dpy, win); 166 + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, 167 + (unsigned char *) &win, 1); 168 +} 169 + 170 void 171 mappingnotify(XEvent *e) 172 { 173 @@ -1097,7 +1128,9 @@ maprequest(XEvent *e) 174 return; 175 if (wa.override_redirect) 176 return; 177 - if (!wintoclient(ev->window)) 178 + if (wmclasscontains(ev->window, altbarclass, "")) 179 + managealtbar(ev->window, &wa); 180 + else if (!wintoclient(ev->window)) 181 manage(ev->window, &wa); 182 } 183 184 @@ -1393,7 +1426,9 @@ scan(void) 185 if (!XGetWindowAttributes(dpy, wins[i], &wa) 186 || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) 187 continue; 188 - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) 189 + if (wmclasscontains(wins[i], altbarclass, "")) 190 + managealtbar(wins[i], &wa); 191 + else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) 192 manage(wins[i], &wa); 193 } 194 for (i = 0; i < num; i++) { /* now the transients */ 195 @@ -1546,7 +1581,7 @@ setup(void) 196 if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) 197 die("no fonts could be loaded."); 198 lrpad = drw->fonts->h; 199 - bh = drw->fonts->h + 2; 200 + bh = usealtbar ? 0 : drw->fonts->h + 2; 201 updategeom(); 202 /* init atoms */ 203 utf8string = XInternAtom(dpy, "UTF8_STRING", False); 204 @@ -1704,7 +1739,7 @@ togglebar(const Arg *arg) 205 { 206 selmon->showbar = !selmon->showbar; 207 updatebarpos(selmon); 208 - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); 209 + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh); 210 arrange(selmon); 211 } 212 213 @@ -1787,10 +1822,26 @@ unmanage(Client *c, int destroyed) 214 arrange(m); 215 } 216 217 +void 218 +unmanagealtbar(Window w) 219 +{ 220 + Monitor *m = wintomon(w); 221 + 222 + if (!m) 223 + return; 224 + 225 + m->barwin = 0; 226 + m->by = 0; 227 + m->bh = 0; 228 + updatebarpos(m); 229 + arrange(m); 230 +} 231 + 232 void 233 unmapnotify(XEvent *e) 234 { 235 Client *c; 236 + Monitor *m; 237 XUnmapEvent *ev = &e->xunmap; 238 239 if ((c = wintoclient(ev->window))) { 240 @@ -1798,12 +1849,16 @@ unmapnotify(XEvent *e) 241 setclientstate(c, WithdrawnState); 242 else 243 unmanage(c, 0); 244 - } 245 + } else if ((m = wintomon(ev->window)) && m->barwin == ev->window) 246 + unmanagealtbar(ev->window); 247 } 248 249 void 250 updatebars(void) 251 { 252 + if (usealtbar) 253 + return; 254 + 255 Monitor *m; 256 XSetWindowAttributes wa = { 257 .override_redirect = True, 258 @@ -1829,11 +1884,11 @@ updatebarpos(Monitor *m) 259 m->wy = m->my; 260 m->wh = m->mh; 261 if (m->showbar) { 262 - m->wh -= bh; 263 + m->wh -= m->bh; 264 m->by = m->topbar ? m->wy : m->wy + m->wh; 265 - m->wy = m->topbar ? m->wy + bh : m->wy; 266 + m->wy = m->topbar ? m->wy + m->bh : m->wy; 267 } else 268 - m->by = -bh; 269 + m->by = -m->bh; 270 } 271 272 void 273 @@ -2077,6 +2132,28 @@ wintomon(Window w) 274 return selmon; 275 } 276 277 +int 278 +wmclasscontains(Window win, const char *class, const char *name) 279 +{ 280 + XClassHint ch = { NULL, NULL }; 281 + int res = 1; 282 + 283 + if (XGetClassHint(dpy, win, &ch)) { 284 + if (ch.res_name && strstr(ch.res_name, name) == NULL) 285 + res = 0; 286 + if (ch.res_class && strstr(ch.res_class, class) == NULL) 287 + res = 0; 288 + } else 289 + res = 0; 290 + 291 + if (ch.res_class) 292 + XFree(ch.res_class); 293 + if (ch.res_name) 294 + XFree(ch.res_name); 295 + 296 + return res; 297 +} 298 + 299 /* There's no way to check accesses to destroyed windows, thus those cases are 300 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs 301 * default error handler, which may call exit. */ 302 -- 303 2.27.0 304