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 {