bar_flexwintitle.c (15519B)
1 /* Flexwintitle properties, you can override these in your config.h if you want. */ 2 #ifndef FLEXWINTITLE_BORDERS 3 #define FLEXWINTITLE_BORDERS 1 // 0 = off, 1 = on 4 #endif 5 #ifndef FLEXWINTITLE_SHOWFLOATING 6 #define FLEXWINTITLE_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown 7 #endif 8 #ifndef FLEXWINTITLE_MASTERWEIGHT 9 #define FLEXWINTITLE_MASTERWEIGHT 9 // master weight compared to stack, hidden and floating window titles 10 #endif 11 #ifndef FLEXWINTITLE_STACKWEIGHT 12 #define FLEXWINTITLE_STACKWEIGHT 3 // stack weight compared to master, hidden and floating window titles 13 #endif 14 #ifndef FLEXWINTITLE_HIDDENWEIGHT 15 #define FLEXWINTITLE_HIDDENWEIGHT 1 // hidden window title weight 16 #endif 17 #ifndef FLEXWINTITLE_FLOATWEIGHT 18 #define FLEXWINTITLE_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows 19 #endif 20 21 #define SCHEMEFOR(c) getschemefor(m, c, groupactive == c) 22 23 enum { GRP_NOSELECTION, GRP_MASTER, GRP_STACK1, GRP_STACK2, GRP_FLOAT, GRP_HIDDEN }; 24 25 int 26 width_flexwintitle(Bar *bar, BarArg *a) 27 { 28 return a->w; 29 } 30 31 int 32 draw_flexwintitle(Bar *bar, BarArg *a) 33 { 34 drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); 35 return flextitlecalculate(bar->mon, a->x, a->w, -1, flextitledraw, NULL, a); 36 } 37 38 int 39 click_flexwintitle(Bar *bar, Arg *arg, BarArg *a) 40 { 41 flextitlecalculate(bar->mon, 0, a->w, a->x, flextitleclick, arg, a); 42 return ClkWinTitle; 43 } 44 45 Client * 46 flextitledrawarea(Monitor *m, Client *c, int x, int r, int w, int max_clients, int scheme, int draw_tiled, int draw_hidden, int draw_floating, 47 int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg) 48 { 49 int i; 50 for (i = 0; c && i < max_clients; c = c->next) { 51 if ( 52 ISVISIBLE(c) && 53 ( 54 (draw_tiled && !c->isfloating && !HIDDEN(c)) || 55 (draw_floating && c->isfloating && !HIDDEN(c)) || 56 (draw_hidden && HIDDEN(c)) 57 ) 58 ) { 59 tabfn(m, c, passx, x, w + (i < r ? 1 : 0), scheme, arg, barg); 60 x += w + (i < r ? 1 : 0); 61 i++; 62 } 63 } 64 return c; 65 } 66 67 int 68 getschemefor(Monitor *m, int group, int activegroup) 69 { 70 switch (group) { 71 case GRP_NOSELECTION: 72 case GRP_MASTER: 73 case GRP_STACK1: 74 case GRP_STACK2: 75 #if BSTACK_LAYOUT 76 if (m->lt[m->sellt]->arrange == &bstack) 77 return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); 78 #endif // BSTACK_LAYOUT 79 #if BSTACKHORIZ_LAYOUT 80 if (m->lt[m->sellt]->arrange == &bstackhoriz) { 81 if (group == GRP_MASTER) 82 return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); 83 else 84 return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); 85 } 86 #endif // BSTACKHORIZ_LAYOUT 87 #if CENTEREDMASTER_LAYOUT 88 if (m->lt[m->sellt]->arrange == ¢eredmaster) 89 return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); 90 #endif // CENTEREDMASTER_LAYOUT 91 #if CENTEREDFLOATINGMASTER_LAYOUT 92 if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) 93 return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); 94 #endif // CENTEREDFLOATINGMASTER_LAYOUT 95 #if COLUMNS_LAYOUT 96 if (m->lt[m->sellt]->arrange == &col) { 97 if (group == GRP_MASTER) 98 return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR); 99 else 100 return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); 101 } 102 #endif // COLUMNS_LAYOUT 103 #if DECK_LAYOUT 104 if (m->lt[m->sellt]->arrange == &deck) { 105 if (group == GRP_MASTER) 106 return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); 107 else 108 return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO); 109 } 110 #endif // DECK_LAYOUT 111 #if FIBONACCI_DWINDLE_LAYOUT 112 if (m->lt[m->sellt]->arrange == &dwindle) 113 return (activegroup ? SchemeFlexActDWDL : SchemeFlexInaDWDL); 114 #endif // FIBONACCI_DWINDLE_LAYOUT 115 #if FIBONACCI_SPIRAL_LAYOUT 116 if (m->lt[m->sellt]->arrange == &spiral) 117 return (activegroup ? SchemeFlexActSPRL : SchemeFlexInaSPRL); 118 #endif // FIBONACCI_SPIRAL_LAYOUT 119 #if FLEXTILE_DELUXE_LAYOUT 120 if (m->lt[m->sellt]->arrange == &flextile) 121 return (activegroup ? SchemeFlexActTTB + m->ltaxis[group] : SchemeFlexInaTTB + m->ltaxis[group]); 122 #endif // FLEXTILE_DELUXE_LAYOUT 123 #if GAPPLESSGRID_LAYOUT 124 if (m->lt[m->sellt]->arrange == &gaplessgrid) 125 return (activegroup ? SchemeFlexActGRID : SchemeFlexInaGRID); 126 #endif // GAPPLESSGRID_LAYOUT 127 #if GRIDMODE_LAYOUT 128 if (m->lt[m->sellt]->arrange == &grid) 129 return (activegroup ? SchemeFlexActGRDM : SchemeFlexInaGRDM); 130 #endif // GRIDMODE_LAYOUT 131 #if HORIZGRID_LAYOUT 132 if (m->lt[m->sellt]->arrange == &horizgrid) 133 return (activegroup ? SchemeFlexActHGRD : SchemeFlexInaHGRD); 134 #endif // HORIZGRID_LAYOUT 135 #if NROWGRID_LAYOUT 136 if (m->lt[m->sellt]->arrange == &nrowgrid) 137 return (activegroup ? SchemeFlexActGRD1 : SchemeFlexInaGRD1); 138 #endif // NROWGRID_LAYOUT 139 #if TILE_LAYOUT 140 if (m->lt[m->sellt]->arrange == &tile) 141 return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB); 142 #endif // TILE_LAYOUT 143 #if MONOCLE_LAYOUT 144 if (m->lt[m->sellt]->arrange == &monocle) 145 return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO); 146 #endif // MONOCLE_LAYOUT 147 return SchemeTitleNorm; 148 case GRP_HIDDEN: 149 return SchemeHidNorm; 150 case GRP_FLOAT: 151 return (activegroup ? SchemeFlexActFloat : SchemeFlexInaFloat); 152 } 153 return SchemeTitleNorm; 154 } 155 156 int 157 getselschemefor(int scheme) 158 { 159 if (scheme == SchemeFlexActFloat || scheme == SchemeFlexInaFloat) 160 return SchemeFlexSelFloat; 161 if (scheme >= SchemeFlexInaTTB) 162 return scheme + SchemeFlexInaTTB - SchemeFlexActTTB; 163 if (scheme >= SchemeFlexActTTB) 164 return scheme + SchemeFlexSelTTB - SchemeFlexActTTB; 165 return SchemeTitleSel; 166 } 167 168 void 169 flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *a) 170 { 171 if (!c) 172 return; 173 int i, nclienttags = 0, nviewtags = 0; 174 int tpad = lrpad / 2; 175 #if BAR_WINICON_PATCH 176 int ipad = c->icon ? c->icw + ICONSPACING : 0; 177 #endif // BAR_WINICON_PATCH 178 #if BAR_CENTEREDWINDOWNAME_PATCH 179 int cpad = 0; 180 #endif // BAR_CENTEREDWINDOWNAME_PATCH 181 int tx = x; 182 int tw = w; 183 184 int clientscheme = ( 185 #if RENAMED_SCRATCHPADS_PATCH 186 c->scratchkey != 0 && c == selmon->sel 187 ? SchemeScratchSel 188 : c->scratchkey != 0 189 ? SchemeScratchNorm 190 : 191 #endif // RENAMED_SCRATCHPADS_PATCH 192 c == selmon->sel && HIDDEN(c) 193 ? SchemeHidSel 194 : HIDDEN(c) 195 ? SchemeHidNorm 196 : c == selmon->sel 197 ? getselschemefor(tabscheme) 198 : c->isurgent 199 ? SchemeUrg 200 : tabscheme 201 ); 202 203 drw_setscheme(drw, scheme[clientscheme]); 204 XSetWindowBorder(dpy, c->win, scheme[clientscheme][ColBorder].pixel); 205 206 if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small 207 tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); 208 #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH 209 else if (TEXTW(c->name) + ipad < w) 210 cpad = (w - TEXTW(c->name) - ipad) / 2; 211 #elif BAR_CENTEREDWINDOWNAME_PATCH 212 else if (TEXTW(c->name) < w) 213 cpad = (w - TEXTW(c->name)) / 2; 214 #endif // BAR_CENTEREDWINDOWNAME_PATCH 215 216 XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); 217 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); 218 219 #if BAR_CENTEREDWINDOWNAME_PATCH 220 /* Apply center padding, if any */ 221 tx += cpad; 222 tw -= cpad; 223 #endif // BAR_CENTEREDWINDOWNAME_PATCH 224 225 tx += tpad; 226 tw -= lrpad; 227 228 #if BAR_WINICON_PATCH 229 if (ipad) { 230 drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); 231 tx += ipad; 232 tw -= ipad; 233 } 234 #endif // BAR_WINICON_PATCH 235 236 drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); 237 drawstateindicator(m, c, 1, x + 2, a->y, w, a->h, 0, 0, 0); 238 239 if (FLEXWINTITLE_BORDERS) { 240 XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); 241 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); 242 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); 243 } 244 245 /* Optional tags icons */ 246 for (i = 0; i < NUMTAGS; i++) { 247 if ((m->tagset[m->seltags] >> i) & 1) 248 nviewtags++; 249 if ((c->tags >> i) & 1) 250 nclienttags++; 251 } 252 253 if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) 254 drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); 255 } 256 257 #ifndef HIDDEN 258 #define HIDDEN(C) 0 259 #endif 260 261 void 262 flextitleclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg) 263 { 264 if (passx >= x && passx <= x + w) 265 arg->v = c; 266 } 267 268 int 269 flextitlecalculate( 270 Monitor *m, int offx, int tabw, int passx, 271 void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), 272 Arg *arg, BarArg *barg 273 ) { 274 Client *c; 275 int n, center = 0, mirror = 0, fixed = 0; // layout configuration 276 int clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0; 277 int i, w, r, num = 0, den, fulllayout = 0; 278 int clientsnstack2 = 0; 279 int groupactive = 0; 280 int selidx = 0; 281 int dualstack = 0; 282 int rw, rr; 283 284 int mas_x = offx, st1_x = offx, st2_x = offx, hid_x = offx, flt_x = offx; 285 int mas_w, st1_w, st2_w, hid_w; 286 287 for (i = 0, c = m->clients; c; c = c->next) { 288 if (!ISVISIBLE(c)) 289 continue; 290 if (HIDDEN(c)) { 291 if (FLEXWINTITLE_HIDDENWEIGHT) 292 clientsnhidden++; 293 continue; 294 } 295 296 if (c->isfloating) { 297 if (FLEXWINTITLE_FLOATWEIGHT) 298 clientsnfloating++; 299 continue; 300 } 301 302 if (m->sel == c) 303 selidx = i; 304 305 if (i < m->nmaster) 306 clientsnmaster++; 307 #if FLEXTILE_DELUXE_LAYOUT 308 else if (m->nstack) { 309 if (clientsnstack < m->nstack) 310 clientsnstack++; 311 else 312 clientsnstack2++; 313 } 314 #endif // FLEXTILE_DELUXE_LAYOUT 315 else if ((i - m->nmaster) % 2) 316 clientsnstack2++; 317 else 318 clientsnstack++; 319 i++; 320 } 321 322 if (!m->sel) 323 groupactive = GRP_NOSELECTION; 324 else if (HIDDEN(m->sel)) 325 groupactive = GRP_HIDDEN; 326 else if (m->sel->isfloating) 327 groupactive = GRP_FLOAT; 328 else if (selidx < clientsnmaster) 329 groupactive = GRP_MASTER; 330 else if (selidx < clientsnmaster + clientsnstack) 331 groupactive = GRP_STACK1; 332 else if (selidx < clientsnmaster + clientsnstack + clientsnstack2) 333 groupactive = GRP_STACK2; 334 335 n = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden; 336 if (n == 0) 337 return 0; 338 #if FLEXTILE_DELUXE_LAYOUT 339 else if (m->lt[m->sellt]->arrange == &flextile) { 340 int layout = m->ltaxis[LAYOUT]; 341 if (layout < 0) { 342 mirror = 1; 343 layout *= -1; 344 } 345 if (layout > FLOATING_MASTER) { 346 layout -= FLOATING_MASTER; 347 fixed = 1; 348 } 349 350 if (layout == SPLIT_HORIZONTAL_DUAL_STACK || layout == SPLIT_HORIZONTAL_DUAL_STACK_FIXED) 351 dualstack = 1; 352 else if (layout == SPLIT_CENTERED_VERTICAL && (fixed || n - m->nmaster > 1)) 353 center = 1; 354 else if (layout == FLOATING_MASTER) 355 center = 1; 356 else if (layout == SPLIT_CENTERED_HORIZONTAL) { 357 if (fixed || n - m->nmaster > 1) 358 center = 1; 359 } 360 } 361 #endif // FLEXTILE_DELUXE_LAYOUT 362 #if CENTEREDMASTER_LAYOUT 363 else if (m->lt[m->sellt]->arrange == ¢eredmaster && (fixed || n - m->nmaster > 1)) 364 center = 1; 365 #endif // CENTEREDMASTER_LAYOUT 366 #if CENTEREDFLOATINGMASTER_LAYOUT 367 else if (m->lt[m->sellt]->arrange == ¢eredfloatingmaster) 368 center = 1; 369 #endif // CENTEREDFLOATINGMASTER_LAYOUT 370 371 /* Certain layouts have no master / stack areas */ 372 if (!m->lt[m->sellt]->arrange // floating layout 373 || (!n || (!fixed && m->nmaster && n <= m->nmaster)) // no master 374 #if MONOCLE_LAYOUT 375 || m->lt[m->sellt]->arrange == &monocle 376 #endif // MONOCLE_LAYOUT 377 #if GRIDMODE_LAYOUT 378 || m->lt[m->sellt]->arrange == &grid 379 #endif // GRIDMODE_LAYOUT 380 #if HORIZGRID_LAYOUT 381 || m->lt[m->sellt]->arrange == &horizgrid 382 #endif // HORIZGRID_LAYOUT 383 #if GAPPLESSGRID_LAYOUT 384 || m->lt[m->sellt]->arrange == &gaplessgrid 385 #endif // GAPPLESSGRID_LAYOUT 386 #if NROWGRID_LAYOUT 387 || m->lt[m->sellt]->arrange == &nrowgrid 388 #endif // NROWGRID_LAYOUT 389 #if FLEXTILE_DELUXE_LAYOUT 390 || (m->lt[m->sellt]->arrange == &flextile && m->ltaxis[LAYOUT] == NO_SPLIT) 391 #endif // FLEXTILE_DELUXE_LAYOUT 392 ) 393 fulllayout = 1; 394 395 num = tabw; 396 c = m->clients; 397 398 /* floating mode */ 399 if ((fulllayout && FLEXWINTITLE_FLOATWEIGHT > 0) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) { 400 den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden; 401 w = num / den; 402 r = num % den; // rest 403 c = flextitledrawarea(m, c, mas_x, r, w, den, !m->lt[m->sellt]->arrange ? SchemeFlexActFloat : SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, FLEXWINTITLE_FLOATWEIGHT, passx, tabfn, arg, barg); // floating 404 /* no master and stack mode, e.g. monocole, grid layouts, fibonacci */ 405 } else if (fulllayout) { 406 den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnhidden; 407 w = num / den; 408 r = num % den; // rest 409 c = flextitledrawarea(m, c, mas_x, r, w, den, SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, 0, passx, tabfn, arg, barg); // full 410 /* tiled mode */ 411 } else { 412 den = clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (clientsnstack + clientsnstack2) * FLEXWINTITLE_STACKWEIGHT + clientsnfloating * FLEXWINTITLE_FLOATWEIGHT + clientsnhidden * FLEXWINTITLE_HIDDENWEIGHT; 413 w = num / den; // weight width per client 414 r = num % den; // weight rest width 415 rw = r / n; // rest incr per client 416 rr = r % n; // rest rest 417 #if FLEXTILE_DELUXE_LAYOUT 418 if ((!center && !dualstack) || (center && n <= m->nmaster + (m->nstack ? m->nstack : 1))) 419 #else 420 if ((!center && !dualstack) || (center && n <= m->nmaster + 1)) 421 #endif // FLEXTILE_DELUXE_LAYOUT 422 { 423 clientsnstack += clientsnstack2; 424 clientsnstack2 = 0; 425 if (groupactive == GRP_STACK2) 426 groupactive = GRP_STACK1; 427 } 428 429 mas_w = clientsnmaster * rw + w * clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (rr > 0 ? MIN(rr, clientsnmaster) : 0); 430 rr -= clientsnmaster; 431 st1_w = clientsnstack * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack) : 0); 432 rr -= clientsnstack; 433 st2_w = clientsnstack2 * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack2) : 0); 434 rr -= clientsnstack2; 435 hid_w = clientsnhidden * (rw + w * FLEXWINTITLE_HIDDENWEIGHT) + (rr > 0 ? MIN(rr, clientsnhidden) : 0); 436 rr -= clientsnhidden; 437 rr = r % n; 438 439 if (mirror) { 440 if (center && clientsnstack2) { 441 mas_x = st1_x + st1_w; 442 st2_x = mas_x + mas_w; 443 hid_x = st2_x + st2_w; 444 } else { 445 if (clientsnstack2) { 446 st2_x = st1_x + st1_w; 447 mas_x = st2_x + st2_w; 448 } else 449 mas_x = st1_x + st1_w; 450 hid_x = mas_x + mas_w; 451 } 452 } else { 453 if (center && clientsnstack2) { 454 mas_x = st2_x + st2_w; 455 st1_x = mas_x + mas_w; 456 hid_x = st1_x + st1_w; 457 } else { 458 st1_x = mas_x + mas_w; 459 if (clientsnstack2) { 460 st2_x = st1_x + st1_w; 461 hid_x = st2_x + st2_w; 462 } else 463 hid_x = st1_x + st1_w; 464 } 465 } 466 467 flt_x = hid_x + hid_w; 468 c = flextitledrawarea(m, c, mas_x, rr, w * FLEXWINTITLE_MASTERWEIGHT + rw, clientsnmaster, SCHEMEFOR(GRP_MASTER), 1, 0, 0, passx, tabfn, arg, barg); // master 469 rr -= clientsnmaster; 470 c = flextitledrawarea(m, c, st1_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack, SCHEMEFOR(GRP_STACK1), 1, 0, 0, passx, tabfn, arg, barg); // stack1 471 rr -= clientsnstack; 472 if (clientsnstack2) { 473 c = flextitledrawarea(m, c, st2_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack2, SCHEMEFOR(GRP_STACK2), 1, 0, 0, passx, tabfn, arg, barg); // stack2 474 rr -= clientsnstack2; 475 } 476 c = flextitledrawarea(m, m->clients, hid_x, rr, w * FLEXWINTITLE_HIDDENWEIGHT + rw, clientsnhidden, SCHEMEFOR(GRP_HIDDEN), 0, 1, 0, passx, tabfn, arg, barg); // hidden 477 rr -= clientsnhidden; 478 c = flextitledrawarea(m, m->clients, flt_x, rr, w * FLEXWINTITLE_FLOATWEIGHT + rw, clientsnfloating, SCHEMEFOR(GRP_FLOAT), 0, 0, 1, passx, tabfn, arg, barg); // floating 479 } 480 return 1; 481 } 482