dwm-anybar-20200810-bb2e722.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) 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