sites

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

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