dwm-awesomebar-20220925-6.3.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-awesomebar-20220925-6.3.diff (13182B)
       ---
            1 diff --git a/config.def.h b/config.def.h
            2 index a2ac963..6dad2f1 100644
            3 --- a/config.def.h
            4 +++ b/config.def.h
            5 @@ -16,6 +16,7 @@ static const char *colors[][3]      = {
            6          /*               fg         bg         border   */
            7          [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
            8          [SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
            9 +        [SchemeHid]  = { col_cyan,  col_gray1, col_cyan  },
           10  };
           11  
           12  /* tagging */
           13 @@ -65,8 +66,10 @@ static Key keys[] = {
           14          { MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
           15          { MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
           16          { MODKEY,                       XK_b,      togglebar,      {0} },
           17 -        { MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
           18 -        { MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
           19 +        { MODKEY,                       XK_j,      focusstackvis,  {.i = +1 } },
           20 +        { MODKEY,                       XK_k,      focusstackvis,  {.i = -1 } },
           21 +        { MODKEY|ShiftMask,             XK_j,      focusstackhid,  {.i = +1 } },
           22 +        { MODKEY|ShiftMask,             XK_k,      focusstackhid,  {.i = -1 } },
           23          { MODKEY,                       XK_i,      incnmaster,     {.i = +1 } },
           24          { MODKEY,                       XK_d,      incnmaster,     {.i = -1 } },
           25          { MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
           26 @@ -85,6 +88,9 @@ static Key keys[] = {
           27          { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
           28          { MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
           29          { MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
           30 +        { MODKEY,                       XK_s,      show,           {0} },
           31 +        { MODKEY|ShiftMask,             XK_s,      showall,        {0} },
           32 +        { MODKEY,                       XK_h,      hide,           {0} },
           33          TAGKEYS(                        XK_1,                      0)
           34          TAGKEYS(                        XK_2,                      1)
           35          TAGKEYS(                        XK_3,                      2)
           36 @@ -103,6 +109,7 @@ static Button buttons[] = {
           37          /* click                event mask      button          function        argument */
           38          { ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
           39          { ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },
           40 +        { ClkWinTitle,          0,              Button1,        togglewin,      {0} },
           41          { ClkWinTitle,          0,              Button2,        zoom,           {0} },
           42          { ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
           43          { ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
           44 diff --git a/dwm.c b/dwm.c
           45 index a96f33c..c375ba3 100644
           46 --- a/dwm.c
           47 +++ b/dwm.c
           48 @@ -50,6 +50,7 @@
           49  #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
           50                                 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
           51  #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
           52 +#define HIDDEN(C)               ((getstate(C->win) == IconicState))
           53  #define LENGTH(X)               (sizeof X / sizeof X[0])
           54  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
           55  #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
           56 @@ -59,7 +60,7 @@
           57  
           58  /* enums */
           59  enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
           60 -enum { SchemeNorm, SchemeSel }; /* color schemes */
           61 +enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */
           62  enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
           63         NetWMFullscreen, NetActiveWindow, NetWMWindowType,
           64         NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
           65 @@ -117,6 +118,8 @@ struct Monitor {
           66          int nmaster;
           67          int num;
           68          int by;               /* bar geometry */
           69 +        int btw;              /* width of tasks portion of bar */
           70 +        int bt;               /* number of tasks */
           71          int mx, my, mw, mh;   /* screen size */
           72          int wx, wy, ww, wh;   /* window area  */
           73          unsigned int seltags;
           74 @@ -124,6 +127,7 @@ struct Monitor {
           75          unsigned int tagset[2];
           76          int showbar;
           77          int topbar;
           78 +        int hidsel;
           79          Client *clients;
           80          Client *sel;
           81          Client *stack;
           82 @@ -168,13 +172,17 @@ static void expose(XEvent *e);
           83  static void focus(Client *c);
           84  static void focusin(XEvent *e);
           85  static void focusmon(const Arg *arg);
           86 -static void focusstack(const Arg *arg);
           87 +static void focusstackvis(const Arg *arg);
           88 +static void focusstackhid(const Arg *arg);
           89 +static void focusstack(int inc, int vis);
           90  static Atom getatomprop(Client *c, Atom prop);
           91  static int getrootptr(int *x, int *y);
           92  static long getstate(Window w);
           93  static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
           94  static void grabbuttons(Client *c, int focused);
           95  static void grabkeys(void);
           96 +static void hide(const Arg *arg);
           97 +static void hidewin(Client *c);
           98  static void incnmaster(const Arg *arg);
           99  static void keypress(XEvent *e);
          100  static void killclient(const Arg *arg);
          101 @@ -204,6 +212,9 @@ static void setlayout(const Arg *arg);
          102  static void setmfact(const Arg *arg);
          103  static void setup(void);
          104  static void seturgent(Client *c, int urg);
          105 +static void show(const Arg *arg);
          106 +static void showall(const Arg *arg);
          107 +static void showwin(Client *c);
          108  static void showhide(Client *c);
          109  static void sigchld(int unused);
          110  static void spawn(const Arg *arg);
          111 @@ -214,6 +225,7 @@ static void togglebar(const Arg *arg);
          112  static void togglefloating(const Arg *arg);
          113  static void toggletag(const Arg *arg);
          114  static void toggleview(const Arg *arg);
          115 +static void togglewin(const Arg *arg);
          116  static void unfocus(Client *c, int setfocus);
          117  static void unmanage(Client *c, int destroyed);
          118  static void unmapnotify(XEvent *e);
          119 @@ -440,10 +452,25 @@ buttonpress(XEvent *e)
          120                          arg.ui = 1 << i;
          121                  } else if (ev->x < x + blw)
          122                          click = ClkLtSymbol;
          123 -                else if (ev->x > selmon->ww - (int)TEXTW(stext))
          124 +                /* 2px right padding */
          125 +                else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2)
          126                          click = ClkStatusText;
          127 -                else
          128 -                        click = ClkWinTitle;
          129 +                else {
          130 +                        x += blw;
          131 +                        c = m->clients;
          132 +
          133 +                        if (c) {
          134 +                                do {
          135 +                                        if (!ISVISIBLE(c))
          136 +                                                continue;
          137 +                                        else
          138 +                                                x +=(1.0 / (double)m->bt) * m->btw;
          139 +                                } while (ev->x > x && (c = c->next));
          140 +
          141 +                                click = ClkWinTitle;
          142 +                                arg.v = c;
          143 +                        }
          144 +                }
          145          } else if ((c = wintoclient(ev->window))) {
          146                  focus(c);
          147                  restack(selmon);
          148 @@ -453,7 +480,7 @@ buttonpress(XEvent *e)
          149          for (i = 0; i < LENGTH(buttons); i++)
          150                  if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
          151                  && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
          152 -                        buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
          153 +                        buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
          154  }
          155  
          156  void
          157 @@ -696,7 +723,7 @@ dirtomon(int dir)
          158  void
          159  drawbar(Monitor *m)
          160  {
          161 -        int x, w, tw = 0;
          162 +        int x, w, tw = 0, n = 0, scm;
          163          int boxs = drw->fonts->h / 9;
          164          int boxw = drw->fonts->h / 6 + 2;
          165          unsigned int i, occ = 0, urg = 0;
          166 @@ -713,6 +740,8 @@ drawbar(Monitor *m)
          167          }
          168  
          169          for (c = m->clients; c; c = c->next) {
          170 +                if (ISVISIBLE(c))
          171 +                        n++;
          172                  occ |= c->tags;
          173                  if (c->isurgent)
          174                          urg |= c->tags;
          175 @@ -733,16 +762,36 @@ drawbar(Monitor *m)
          176          x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
          177  
          178          if ((w = m->ww - tw - x) > bh) {
          179 -                if (m->sel) {
          180 -                        drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
          181 -                        drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
          182 -                        if (m->sel->isfloating)
          183 -                                drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
          184 +                if (n > 0) {
          185 +                        int remainder = w % n;
          186 +                        int tabw = (1.0 / (double)n) * w + 1;
          187 +                        for (c = m->clients; c; c = c->next) {
          188 +                                if (!ISVISIBLE(c))
          189 +                                        continue;
          190 +                                if (m->sel == c)
          191 +                                        scm = SchemeSel;
          192 +                                else if (HIDDEN(c))
          193 +                                        scm = SchemeHid;
          194 +                                else
          195 +                                        scm = SchemeNorm;
          196 +                                drw_setscheme(drw, scheme[scm]);
          197 +
          198 +                                if (remainder >= 0) {
          199 +                                        if (remainder == 0) {
          200 +                                                tabw--;
          201 +                                        }
          202 +                                        remainder--;
          203 +                                }
          204 +                                drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0);
          205 +                                x += tabw;
          206 +                        }
          207                  } else {
          208                          drw_setscheme(drw, scheme[SchemeNorm]);
          209                          drw_rect(drw, x, 0, w, bh, 1, 1);
          210                  }
          211          }
          212 +        m->bt = n;
          213 +        m->btw = w;
          214          drw_map(drw, m->barwin, 0, 0, m->ww, bh);
          215  }
          216  
          217 @@ -788,9 +837,17 @@ void
          218  focus(Client *c)
          219  {
          220          if (!c || !ISVISIBLE(c))
          221 -                for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
          222 -        if (selmon->sel && selmon->sel != c)
          223 +                for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext);
          224 +        if (selmon->sel && selmon->sel != c) {
          225                  unfocus(selmon->sel, 0);
          226 +
          227 +                if (selmon->hidsel) {
          228 +                        hidewin(selmon->sel);
          229 +                        if (c)
          230 +                                arrange(c->mon);
          231 +                        selmon->hidsel = 0;
          232 +                }
          233 +        }
          234          if (c) {
          235                  if (c->mon != selmon)
          236                          selmon = c->mon;
          237 @@ -834,28 +891,52 @@ focusmon(const Arg *arg)
          238  }
          239  
          240  void
          241 -focusstack(const Arg *arg)
          242 +focusstackvis(const Arg *arg) {
          243 +        focusstack(arg->i, 0);
          244 +}
          245 +
          246 +void
          247 +focusstackhid(const Arg *arg) {
          248 +        focusstack(arg->i, 1);
          249 +}
          250 +
          251 +void
          252 +focusstack(int inc, int hid)
          253  {
          254          Client *c = NULL, *i;
          255 -
          256 -        if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
          257 +        // if no client selected AND exclude hidden client; if client selected but fullscreened
          258 +        if ((!selmon->sel && !hid) || (selmon->sel && selmon->sel->isfullscreen && lockfullscreen))
          259                  return;
          260 -        if (arg->i > 0) {
          261 -                for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
          262 +        if (!selmon->clients)
          263 +                return;
          264 +        if (inc > 0) {
          265 +                if (selmon->sel)
          266 +                        for (c = selmon->sel->next;
          267 +                                        c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
          268 +                                        c = c->next);
          269                  if (!c)
          270 -                        for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
          271 +                        for (c = selmon->clients;
          272 +                                        c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
          273 +                                        c = c->next);
          274          } else {
          275 -                for (i = selmon->clients; i != selmon->sel; i = i->next)
          276 -                        if (ISVISIBLE(i))
          277 -                                c = i;
          278 +                if (selmon->sel) {
          279 +                        for (i = selmon->clients; i != selmon->sel; i = i->next)
          280 +                                if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
          281 +                                        c = i;
          282 +                } else
          283 +                        c = selmon->clients;
          284                  if (!c)
          285                          for (; i; i = i->next)
          286 -                                if (ISVISIBLE(i))
          287 +                                if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
          288                                          c = i;
          289          }
          290          if (c) {
          291                  focus(c);
          292                  restack(selmon);
          293 +                if (HIDDEN(c)) {
          294 +                        showwin(c);
          295 +                        c->mon->hidsel = 1;
          296 +                }
          297          }
          298  }
          299  
          300 @@ -967,6 +1048,36 @@ grabkeys(void)
          301          }
          302  }
          303  
          304 +void
          305 +hide(const Arg *arg)
          306 +{
          307 +        hidewin(selmon->sel);
          308 +        focus(NULL);
          309 +        arrange(selmon);
          310 +}
          311 +
          312 +void
          313 +hidewin(Client *c) {
          314 +        if (!c || HIDDEN(c))
          315 +                return;
          316 +
          317 +        Window w = c->win;
          318 +        static XWindowAttributes ra, ca;
          319 +
          320 +        // more or less taken directly from blackbox's hide() function
          321 +        XGrabServer(dpy);
          322 +        XGetWindowAttributes(dpy, root, &ra);
          323 +        XGetWindowAttributes(dpy, w, &ca);
          324 +        // prevent UnmapNotify events
          325 +        XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
          326 +        XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask);
          327 +        XUnmapWindow(dpy, w);
          328 +        setclientstate(c, IconicState);
          329 +        XSelectInput(dpy, root, ra.your_event_mask);
          330 +        XSelectInput(dpy, w, ca.your_event_mask);
          331 +        XUngrabServer(dpy);
          332 +}
          333 +
          334  void
          335  incnmaster(const Arg *arg)
          336  {
          337 @@ -1071,12 +1182,14 @@ manage(Window w, XWindowAttributes *wa)
          338          XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
          339                  (unsigned char *) &(c->win), 1);
          340          XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
          341 -        setclientstate(c, NormalState);
          342 +        if (!HIDDEN(c))
          343 +                setclientstate(c, NormalState);
          344          if (c->mon == selmon)
          345                  unfocus(selmon->sel, 0);
          346          c->mon->sel = c;
          347          arrange(c->mon);
          348 -        XMapWindow(dpy, c->win);
          349 +        if (!HIDDEN(c))
          350 +                XMapWindow(dpy, c->win);
          351          focus(NULL);
          352  }
          353  
          354 @@ -1199,7 +1312,7 @@ movemouse(const Arg *arg)
          355  Client *
          356  nexttiled(Client *c)
          357  {
          358 -        for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
          359 +        for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next);
          360          return c;
          361  }
          362  
          363 @@ -1252,6 +1365,16 @@ propertynotify(XEvent *e)
          364  void
          365  quit(const Arg *arg)
          366  {
          367 +        // fix: reloading dwm keeps all the hidden clients hidden
          368 +        Monitor *m;
          369 +        Client *c;
          370 +        for (m = mons; m; m = m->next) {
          371 +                if (m) {
          372 +                        for (c = m->stack; c; c = c->next)
          373 +                                if (c && HIDDEN(c)) showwin(c);
          374 +                }
          375 +        }
          376 +
          377          running = 0;
          378  }
          379  
          380 @@ -1614,6 +1737,42 @@ seturgent(Client *c, int urg)
          381          XFree(wmh);
          382  }
          383  
          384 +void
          385 +show(const Arg *arg)
          386 +{
          387 +        if (selmon->hidsel)
          388 +                selmon->hidsel = 0;
          389 +        showwin(selmon->sel);
          390 +}
          391 +
          392 +void
          393 +showall(const Arg *arg)
          394 +{
          395 +        Client *c = NULL;
          396 +        selmon->hidsel = 0;
          397 +        for (c = selmon->clients; c; c = c->next) {
          398 +                if (ISVISIBLE(c))
          399 +                        showwin(c);
          400 +        }
          401 +        if (!selmon->sel) {
          402 +                for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
          403 +                if (c)
          404 +                        focus(c);
          405 +        }
          406 +        restack(selmon);
          407 +}
          408 +
          409 +void
          410 +showwin(Client *c)
          411 +{
          412 +        if (!c || !HIDDEN(c))
          413 +                return;
          414 +
          415 +        XMapWindow(dpy, c->win);
          416 +        setclientstate(c, NormalState);
          417 +        arrange(c->mon);
          418 +}
          419 +
          420  void
          421  showhide(Client *c)
          422  {
          423 @@ -1752,6 +1911,23 @@ toggleview(const Arg *arg)
          424          }
          425  }
          426  
          427 +void
          428 +togglewin(const Arg *arg)
          429 +{
          430 +        Client *c = (Client*)arg->v;
          431 +
          432 +        if (c == selmon->sel) {
          433 +                hidewin(c);
          434 +                focus(NULL);
          435 +                arrange(c->mon);
          436 +        } else {
          437 +                if (HIDDEN(c))
          438 +                        showwin(c);
          439 +                focus(c);
          440 +                restack(selmon);
          441 +        }
          442 +}
          443 +
          444  void
          445  unfocus(Client *c, int setfocus)
          446  {