dwm-awesomebar-20200907-6.2.diff (12533B)
1 diff --git a/config.def.h b/config.def.h 2 index 1c0b587..bb8f3f7 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 @@ -64,8 +65,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 @@ -84,6 +87,8 @@ 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, XK_h, hide, {0} }, 32 TAGKEYS( XK_1, 0) 33 TAGKEYS( XK_2, 1) 34 TAGKEYS( XK_3, 2) 35 @@ -102,6 +107,7 @@ static Button buttons[] = { 36 /* click event mask button function argument */ 37 { ClkLtSymbol, 0, Button1, setlayout, {0} }, 38 { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, 39 + { ClkWinTitle, 0, Button1, togglewin, {0} }, 40 { ClkWinTitle, 0, Button2, zoom, {0} }, 41 { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 42 { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 43 diff --git a/dwm.c b/dwm.c 44 index 4465af1..e780189 100644 45 --- a/dwm.c 46 +++ b/dwm.c 47 @@ -50,6 +50,7 @@ 48 #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 49 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 50 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) 51 +#define HIDDEN(C) ((getstate(C->win) == IconicState)) 52 #define LENGTH(X) (sizeof X / sizeof X[0]) 53 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) 54 #define WIDTH(X) ((X)->w + 2 * (X)->bw) 55 @@ -59,7 +60,7 @@ 56 57 /* enums */ 58 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 59 -enum { SchemeNorm, SchemeSel }; /* color schemes */ 60 +enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */ 61 enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 62 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 63 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 64 @@ -117,6 +118,8 @@ struct Monitor { 65 int nmaster; 66 int num; 67 int by; /* bar geometry */ 68 + int btw; /* width of tasks portion of bar */ 69 + int bt; /* number of tasks */ 70 int mx, my, mw, mh; /* screen size */ 71 int wx, wy, ww, wh; /* window area */ 72 unsigned int seltags; 73 @@ -124,6 +127,7 @@ struct Monitor { 74 unsigned int tagset[2]; 75 int showbar; 76 int topbar; 77 + int hidsel; 78 Client *clients; 79 Client *sel; 80 Client *stack; 81 @@ -168,12 +172,16 @@ static void expose(XEvent *e); 82 static void focus(Client *c); 83 static void focusin(XEvent *e); 84 static void focusmon(const Arg *arg); 85 -static void focusstack(const Arg *arg); 86 +static void focusstackvis(const Arg *arg); 87 +static void focusstackhid(const Arg *arg); 88 +static void focusstack(int inc, int vis); 89 static int getrootptr(int *x, int *y); 90 static long getstate(Window w); 91 static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 92 static void grabbuttons(Client *c, int focused); 93 static void grabkeys(void); 94 +static void hide(const Arg *arg); 95 +static void hidewin(Client *c); 96 static void incnmaster(const Arg *arg); 97 static void keypress(XEvent *e); 98 static void killclient(const Arg *arg); 99 @@ -203,6 +211,8 @@ static void setlayout(const Arg *arg); 100 static void setmfact(const Arg *arg); 101 static void setup(void); 102 static void seturgent(Client *c, int urg); 103 +static void show(const Arg *arg); 104 +static void showwin(Client *c); 105 static void showhide(Client *c); 106 static void sigchld(int unused); 107 static void spawn(const Arg *arg); 108 @@ -213,6 +223,7 @@ static void togglebar(const Arg *arg); 109 static void togglefloating(const Arg *arg); 110 static void toggletag(const Arg *arg); 111 static void toggleview(const Arg *arg); 112 +static void togglewin(const Arg *arg); 113 static void unfocus(Client *c, int setfocus); 114 static void unmanage(Client *c, int destroyed); 115 static void unmapnotify(XEvent *e); 116 @@ -439,10 +450,25 @@ buttonpress(XEvent *e) 117 arg.ui = 1 << i; 118 } else if (ev->x < x + blw) 119 click = ClkLtSymbol; 120 - else if (ev->x > selmon->ww - TEXTW(stext)) 121 + /* 2px right padding */ 122 + else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2) 123 click = ClkStatusText; 124 - else 125 - click = ClkWinTitle; 126 + else { 127 + x += blw; 128 + c = m->clients; 129 + 130 + if (c) { 131 + do { 132 + if (!ISVISIBLE(c)) 133 + continue; 134 + else 135 + x += (1.0 / (double)m->bt) * m->btw; 136 + } while (ev->x > x && (c = c->next)); 137 + 138 + click = ClkWinTitle; 139 + arg.v = c; 140 + } 141 + } 142 } else if ((c = wintoclient(ev->window))) { 143 focus(c); 144 restack(selmon); 145 @@ -452,7 +478,7 @@ buttonpress(XEvent *e) 146 for (i = 0; i < LENGTH(buttons); i++) 147 if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button 148 && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) 149 - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); 150 + buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); 151 } 152 153 void 154 @@ -695,7 +721,7 @@ dirtomon(int dir) 155 void 156 drawbar(Monitor *m) 157 { 158 - int x, w, sw = 0; 159 + int x, w, sw = 0, n = 0, scm; 160 int boxs = drw->fonts->h / 9; 161 int boxw = drw->fonts->h / 6 + 2; 162 unsigned int i, occ = 0, urg = 0; 163 @@ -709,6 +735,8 @@ drawbar(Monitor *m) 164 } 165 166 for (c = m->clients; c; c = c->next) { 167 + if (ISVISIBLE(c)) 168 + n++; 169 occ |= c->tags; 170 if (c->isurgent) 171 urg |= c->tags; 172 @@ -729,16 +757,37 @@ drawbar(Monitor *m) 173 x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); 174 175 if ((w = m->ww - sw - x) > bh) { 176 - if (m->sel) { 177 - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 178 - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 179 - if (m->sel->isfloating) 180 - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); 181 + if (n > 0) { 182 + int remainder = w % n; 183 + int tabw = (1.0 / (double)n) * w + 1; 184 + for (c = m->clients; c; c = c->next) { 185 + if (!ISVISIBLE(c)) 186 + continue; 187 + if (m->sel == c) 188 + scm = SchemeSel; 189 + else if (HIDDEN(c)) 190 + scm = SchemeHid; 191 + else 192 + scm = SchemeNorm; 193 + drw_setscheme(drw, scheme[scm]); 194 + 195 + if (remainder >= 0) { 196 + if (remainder == 0) { 197 + tabw--; 198 + } 199 + remainder--; 200 + } 201 + drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0); 202 + x += tabw; 203 + } 204 } else { 205 drw_setscheme(drw, scheme[SchemeNorm]); 206 drw_rect(drw, x, 0, w, bh, 1, 1); 207 } 208 } 209 + 210 + m->bt = n; 211 + m->btw = w; 212 drw_map(drw, m->barwin, 0, 0, m->ww, bh); 213 } 214 215 @@ -784,9 +833,17 @@ void 216 focus(Client *c) 217 { 218 if (!c || !ISVISIBLE(c)) 219 - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); 220 - if (selmon->sel && selmon->sel != c) 221 + for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext); 222 + if (selmon->sel && selmon->sel != c) { 223 unfocus(selmon->sel, 0); 224 + 225 + if (selmon->hidsel) { 226 + hidewin(selmon->sel); 227 + if (c) 228 + arrange(c->mon); 229 + selmon->hidsel = 0; 230 + } 231 + } 232 if (c) { 233 if (c->mon != selmon) 234 selmon = c->mon; 235 @@ -830,28 +887,57 @@ focusmon(const Arg *arg) 236 } 237 238 void 239 -focusstack(const Arg *arg) 240 +focusstackvis(const Arg *arg) 241 +{ 242 + focusstack(arg->i, 0); 243 +} 244 + 245 +void 246 +focusstackhid(const Arg *arg) 247 +{ 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) 257 + if (!selmon->sel && !hid) 258 return; 259 - if (arg->i > 0) { 260 - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); 261 + if (!selmon->clients) 262 + return; 263 + 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 + 291 if (c) { 292 focus(c); 293 restack(selmon); 294 + 295 + if (HIDDEN(c)) { 296 + showwin(c); 297 + c->mon->hidsel = 1; 298 + } 299 } 300 } 301 302 @@ -963,6 +1049,36 @@ grabkeys(void) 303 } 304 } 305 306 +void 307 +hide(const Arg *arg) 308 +{ 309 + hidewin(selmon->sel); 310 + focus(NULL); 311 + arrange(selmon); 312 +} 313 + 314 +void 315 +hidewin(Client *c) { 316 + if (!c || HIDDEN(c)) 317 + return; 318 + 319 + Window w = c->win; 320 + static XWindowAttributes ra, ca; 321 + 322 + // more or less taken directly from blackbox's hide() function 323 + XGrabServer(dpy); 324 + XGetWindowAttributes(dpy, root, &ra); 325 + XGetWindowAttributes(dpy, w, &ca); 326 + // prevent UnmapNotify events 327 + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); 328 + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); 329 + XUnmapWindow(dpy, w); 330 + setclientstate(c, IconicState); 331 + XSelectInput(dpy, root, ra.your_event_mask); 332 + XSelectInput(dpy, w, ca.your_event_mask); 333 + XUngrabServer(dpy); 334 +} 335 + 336 void 337 incnmaster(const Arg *arg) 338 { 339 @@ -1067,12 +1183,14 @@ manage(Window w, XWindowAttributes *wa) 340 XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, 341 (unsigned char *) &(c->win), 1); 342 XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ 343 - setclientstate(c, NormalState); 344 + if (!HIDDEN(c)) 345 + setclientstate(c, NormalState); 346 if (c->mon == selmon) 347 unfocus(selmon->sel, 0); 348 c->mon->sel = c; 349 arrange(c->mon); 350 - XMapWindow(dpy, c->win); 351 + if (!HIDDEN(c)) 352 + XMapWindow(dpy, c->win); 353 focus(NULL); 354 } 355 356 @@ -1195,7 +1313,7 @@ movemouse(const Arg *arg) 357 Client * 358 nexttiled(Client *c) 359 { 360 - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); 361 + for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); 362 return c; 363 } 364 365 @@ -1248,6 +1366,16 @@ propertynotify(XEvent *e) 366 void 367 quit(const Arg *arg) 368 { 369 + // fix: reloading dwm keeps all the hidden clients hidden 370 + Monitor *m; 371 + Client *c; 372 + for (m = mons; m; m = m->next) { 373 + if (m) { 374 + for (c = m->stack; c; c = c->next) 375 + if (c && HIDDEN(c)) showwin(c); 376 + } 377 + } 378 + 379 running = 0; 380 } 381 382 @@ -1610,6 +1738,25 @@ seturgent(Client *c, int urg) 383 XFree(wmh); 384 } 385 386 +void 387 +show(const Arg *arg) 388 +{ 389 + if (selmon->hidsel) 390 + selmon->hidsel = 0; 391 + showwin(selmon->sel); 392 +} 393 + 394 +void 395 +showwin(Client *c) 396 +{ 397 + if (!c || !HIDDEN(c)) 398 + return; 399 + 400 + XMapWindow(dpy, c->win); 401 + setclientstate(c, NormalState); 402 + arrange(c->mon); 403 +} 404 + 405 void 406 showhide(Client *c) 407 { 408 @@ -1746,6 +1893,23 @@ toggleview(const Arg *arg) 409 } 410 } 411 412 +void 413 +togglewin(const Arg *arg) 414 +{ 415 + Client *c = (Client*)arg->v; 416 + 417 + if (c == selmon->sel) { 418 + hidewin(c); 419 + focus(NULL); 420 + arrange(c->mon); 421 + } else { 422 + if (HIDDEN(c)) 423 + showwin(c); 424 + focus(c); 425 + restack(selmon); 426 + } 427 +} 428 + 429 void 430 unfocus(Client *c, int setfocus) 431 {