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