sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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