vanitygaps.c (12226B)
1 /* Key binding functions */ 2 __attribute__((unused)) static void defaultgaps(const Arg *arg); 3 __attribute__((unused)) static void incrigaps(const Arg *arg); 4 __attribute__((unused)) static void incrogaps(const Arg *arg); 5 __attribute__((unused)) static void incrohgaps(const Arg *arg); 6 __attribute__((unused)) static void incrovgaps(const Arg *arg); 7 __attribute__((unused)) static void incrihgaps(const Arg *arg); 8 __attribute__((unused)) static void incrivgaps(const Arg *arg); 9 static void incrgaps(const Arg *arg); 10 static void togglegaps(const Arg *arg); 11 12 /* Layouts */ 13 static void bstack(Monitor *m); 14 static void centeredmaster(Monitor *m); 15 static void centeredfloatingmaster(Monitor *m); 16 static void deck(Monitor *m); 17 static void dwindle(Monitor *m); 18 static void fibonacci(Monitor *m, int s); 19 static void spiral(Monitor *m); 20 static void tile(Monitor *); 21 22 /* Internals */ 23 static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); 24 static void setgaps(int oh, int ov, int ih, int iv); 25 26 /* Settings */ 27 static int enablegaps = 1; 28 29 static void 30 setgaps(int oh, int ov, int ih, int iv) 31 { 32 if (oh < 0) oh = 0; 33 if (ov < 0) ov = 0; 34 if (ih < 0) ih = 0; 35 if (iv < 0) iv = 0; 36 37 selmon->gappoh = oh; 38 selmon->gappov = ov; 39 selmon->gappih = ih; 40 selmon->gappiv = iv; 41 arrange(selmon); 42 } 43 44 static void 45 togglegaps(const Arg *arg) 46 { 47 enablegaps = !enablegaps; 48 arrange(NULL); 49 } 50 51 static void 52 defaultgaps(const Arg *arg) 53 { 54 setgaps(gappoh, gappov, gappih, gappiv); 55 } 56 57 static void 58 incrgaps(const Arg *arg) 59 { 60 setgaps( 61 selmon->gappoh + arg->i, 62 selmon->gappov + arg->i, 63 selmon->gappih + arg->i, 64 selmon->gappiv + arg->i 65 ); 66 } 67 68 static void 69 incrigaps(const Arg *arg) 70 { 71 setgaps( 72 selmon->gappoh, 73 selmon->gappov, 74 selmon->gappih + arg->i, 75 selmon->gappiv + arg->i 76 ); 77 } 78 79 static void 80 incrogaps(const Arg *arg) 81 { 82 setgaps( 83 selmon->gappoh + arg->i, 84 selmon->gappov + arg->i, 85 selmon->gappih, 86 selmon->gappiv 87 ); 88 } 89 90 static void 91 incrohgaps(const Arg *arg) 92 { 93 setgaps( 94 selmon->gappoh + arg->i, 95 selmon->gappov, 96 selmon->gappih, 97 selmon->gappiv 98 ); 99 } 100 101 static void 102 incrovgaps(const Arg *arg) 103 { 104 setgaps( 105 selmon->gappoh, 106 selmon->gappov + arg->i, 107 selmon->gappih, 108 selmon->gappiv 109 ); 110 } 111 112 static void 113 incrihgaps(const Arg *arg) 114 { 115 setgaps( 116 selmon->gappoh, 117 selmon->gappov, 118 selmon->gappih + arg->i, 119 selmon->gappiv 120 ); 121 } 122 123 static void 124 incrivgaps(const Arg *arg) 125 { 126 setgaps( 127 selmon->gappoh, 128 selmon->gappov, 129 selmon->gappih, 130 selmon->gappiv + arg->i 131 ); 132 } 133 134 static void 135 getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) 136 { 137 unsigned int n, oe, ie; 138 oe = ie = enablegaps; 139 Client *c; 140 141 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 142 if (smartgaps && n == 1) { 143 oe = 0; // outer gaps disabled when only one client 144 } 145 146 *oh = m->gappoh*oe; // outer horizontal gap 147 *ov = m->gappov*oe; // outer vertical gap 148 *ih = m->gappih*ie; // inner horizontal gap 149 *iv = m->gappiv*ie; // inner vertical gap 150 *nc = n; // number of clients 151 } 152 153 void 154 getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) 155 { 156 unsigned int n; 157 float mfacts, sfacts; 158 int mtotal = 0, stotal = 0; 159 Client *c; 160 161 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 162 mfacts = MIN(n, m->nmaster); 163 sfacts = n - m->nmaster; 164 165 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) 166 if (n < m->nmaster) 167 mtotal += msize / mfacts; 168 else 169 stotal += ssize / sfacts; 170 171 *mf = mfacts; // total factor of master area 172 *sf = sfacts; // total factor of stack area 173 *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split 174 *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split 175 } 176 177 /*** 178 * Layouts 179 */ 180 181 /* 182 * Bottomstack layout + gaps 183 * https://dwm.suckless.org/patches/bottomstack/ 184 */ 185 186 static void 187 bstack(Monitor *m) 188 { 189 unsigned int i, n; 190 int mx = 0, my = 0, mh = 0, mw = 0; 191 int sx = 0, sy = 0, sh = 0, sw = 0; 192 float mfacts, sfacts; 193 int mrest, srest; 194 Client *c; 195 196 int oh, ov, ih, iv; 197 getgaps(m, &oh, &ov, &ih, &iv, &n); 198 199 if (n == 0) 200 return; 201 202 sx = mx = m->wx + ov; 203 sy = my = m->wy + oh; 204 sh = mh = m->wh - 2*oh; 205 mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); 206 sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); 207 208 if (m->nmaster && n > m->nmaster) { 209 sh = (mh - ih) * (1 - m->mfact); 210 mh = (mh - ih) * m->mfact; 211 sx = mx; 212 sy = my + mh + ih; 213 } 214 215 getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); 216 217 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { 218 if (i < m->nmaster) { 219 resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); 220 mx += WIDTH(c) + iv; 221 } else { 222 resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); 223 sx += WIDTH(c) + iv; 224 } 225 } 226 } 227 228 /* 229 * Centred master layout + gaps 230 * https://dwm.suckless.org/patches/centeredmaster/ 231 */ 232 233 void 234 centeredmaster(Monitor *m) 235 { 236 unsigned int i, n; 237 int mx = 0, my = 0, mh = 0, mw = 0; 238 int lx = 0, ly = 0, lw = 0, lh = 0; 239 int rx = 0, ry = 0, rw = 0, rh = 0; 240 float mfacts = 0, lfacts = 0, rfacts = 0; 241 int mtotal = 0, ltotal = 0, rtotal = 0; 242 int mrest = 0, lrest = 0, rrest = 0; 243 Client *c; 244 245 int oh, ov, ih, iv; 246 getgaps(m, &oh, &ov, &ih, &iv, &n); 247 248 if (n == 0) 249 return; 250 251 /* initialize areas */ 252 mx = m->wx + ov; 253 my = m->wy + oh; 254 mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); 255 mw = m->ww - 2*ov; 256 lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); 257 rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); 258 259 if (m->nmaster && n > m->nmaster) { 260 /* go mfact box in the center if more than nmaster clients */ 261 if (n - m->nmaster > 1) { 262 /* ||<-S->|<---M--->|<-S->|| */ 263 mw = (m->ww - 2*ov - 2*iv) * m->mfact; 264 lw = (m->ww - mw - 2*ov - 2*iv) / 2; 265 mx += lw + iv; 266 } else { 267 /* ||<---M--->|<-S->|| */ 268 mw = (mw - iv) * m->mfact; 269 lw = m->ww - mw - iv - 2*ov; 270 } 271 rw = lw; 272 lx = m->wx + ov; 273 ly = m->wy + oh; 274 rx = mx + mw + iv; 275 ry = m->wy + oh; 276 } 277 278 /* calculate facts */ 279 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { 280 if (!m->nmaster || n < m->nmaster) 281 mfacts += 1; 282 else if ((n - m->nmaster) % 2) 283 lfacts += 1; // total factor of left hand stack area 284 else 285 rfacts += 1; // total factor of right hand stack area 286 } 287 288 for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) 289 if (!m->nmaster || n < m->nmaster) 290 mtotal += mh / mfacts; 291 else if ((n - m->nmaster) % 2) 292 ltotal += lh / lfacts; 293 else 294 rtotal += rh / rfacts; 295 296 mrest = mh - mtotal; 297 lrest = lh - ltotal; 298 rrest = rh - rtotal; 299 300 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { 301 if (!m->nmaster || i < m->nmaster) { 302 /* nmaster clients are stacked vertically, in the center of the screen */ 303 resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); 304 my += HEIGHT(c) + ih; 305 } else { 306 /* stack clients are stacked vertically */ 307 if ((i - m->nmaster) % 2 ) { 308 resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); 309 ly += HEIGHT(c) + ih; 310 } else { 311 resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); 312 ry += HEIGHT(c) + ih; 313 } 314 } 315 } 316 } 317 318 void 319 centeredfloatingmaster(Monitor *m) 320 { 321 unsigned int i, n; 322 float mfacts, sfacts; 323 int mrest, srest; 324 int mx = 0, my = 0, mh = 0, mw = 0; 325 int sx = 0, sy = 0, sh = 0, sw = 0; 326 Client *c; 327 328 float mivf = 1.0; // master inner vertical gap factor 329 int oh, ov, ih, iv; 330 getgaps(m, &oh, &ov, &ih, &iv, &n); 331 332 if (n == 0) 333 return; 334 335 sx = mx = m->wx + ov; 336 sy = my = m->wy + oh; 337 sh = mh = m->wh - 2*oh; 338 mw = m->ww - 2*ov - iv*(n - 1); 339 sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); 340 341 if (m->nmaster && n > m->nmaster) { 342 mivf = 0.8; 343 /* go mfact box in the center if more than nmaster clients */ 344 if (m->ww > m->wh) { 345 mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); 346 mh = m->wh * 0.9; 347 } else { 348 mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); 349 mh = m->wh * m->mfact; 350 } 351 mx = m->wx + (m->ww - mw) / 2; 352 my = m->wy + (m->wh - mh - 2*oh) / 2; 353 354 sx = m->wx + ov; 355 sy = m->wy + oh; 356 sh = m->wh - 2*oh; 357 } 358 359 getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); 360 361 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 362 if (i < m->nmaster) { 363 /* nmaster clients are stacked horizontally, in the center of the screen */ 364 resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); 365 mx += WIDTH(c) + iv*mivf; 366 } else { 367 /* stack clients are stacked horizontally */ 368 resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); 369 sx += WIDTH(c) + iv; 370 } 371 } 372 373 /* 374 * Deck layout + gaps 375 * https://dwm.suckless.org/patches/deck/ 376 */ 377 378 static void 379 deck(Monitor *m) 380 { 381 unsigned int i, n; 382 int mx = 0, my = 0, mh = 0, mw = 0; 383 int sx = 0, sy = 0, sh = 0, sw = 0; 384 float mfacts, sfacts; 385 int mrest, srest; 386 Client *c; 387 388 int oh, ov, ih, iv; 389 getgaps(m, &oh, &ov, &ih, &iv, &n); 390 391 if (n == 0) 392 return; 393 394 sx = mx = m->wx + ov; 395 sy = my = m->wy + oh; 396 sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); 397 sw = mw = m->ww - 2*ov; 398 399 if (m->nmaster && n > m->nmaster) { 400 sw = (mw - iv) * (1 - m->mfact); 401 mw = (mw - iv) * m->mfact; 402 sx = mx + mw + iv; 403 sh = m->wh - 2*oh; 404 } 405 406 getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); 407 408 if (n - m->nmaster > 0) /* override layout symbol */ 409 snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); 410 411 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 412 if (i < m->nmaster) { 413 resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); 414 my += HEIGHT(c) + ih; 415 } else { 416 resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); 417 } 418 } 419 420 /* 421 * Fibonacci layout + gaps 422 * https://dwm.suckless.org/patches/fibonacci/ 423 */ 424 425 static void 426 fibonacci(Monitor *m, int s) 427 { 428 unsigned int i, n; 429 int nx, ny, nw, nh; 430 int oh, ov, ih, iv; 431 Client *c; 432 433 getgaps(m, &oh, &ov, &ih, &iv, &n); 434 435 if (n == 0) 436 return; 437 438 nx = m->wx + ov; 439 ny = oh; 440 nw = m->ww - 2*ov; 441 nh = m->wh - 2*oh; 442 443 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { 444 if ((i % 2 && nh / 2 > 2*c->bw) 445 || (!(i % 2) && nw / 2 > 2*c->bw)) { 446 if (i < n - 1) { 447 if (i % 2) 448 nh = (nh - ih) / 2; 449 else 450 nw = (nw - iv) / 2; 451 452 if ((i % 4) == 2 && !s) 453 nx += nw + iv; 454 else if ((i % 4) == 3 && !s) 455 ny += nh + ih; 456 } 457 if ((i % 4) == 0) { 458 if (s) 459 ny += nh + ih; 460 else 461 ny -= nh + ih; 462 } 463 else if ((i % 4) == 1) 464 nx += nw + iv; 465 else if ((i % 4) == 2) 466 ny += nh + ih; 467 else if ((i % 4) == 3) { 468 if (s) 469 nx += nw + iv; 470 else 471 nx -= nw + iv; 472 } 473 if (i == 0) { 474 if (n != 1) 475 nw = (m->ww - 2*ov - iv) * m->mfact; 476 ny = m->wy + oh; 477 } 478 else if (i == 1) 479 nw = m->ww - nw - iv - 2*ov; 480 i++; 481 } 482 483 resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); 484 } 485 } 486 487 static void 488 dwindle(Monitor *m) 489 { 490 fibonacci(m, 1); 491 } 492 493 static void 494 spiral(Monitor *m) 495 { 496 fibonacci(m, 0); 497 } 498 499 /* 500 * Default tile layout + gaps 501 */ 502 503 static void 504 tile(Monitor *m) 505 { 506 unsigned int i, n; 507 int mx = 0, my = 0, mh = 0, mw = 0; 508 int sx = 0, sy = 0, sh = 0, sw = 0; 509 float mfacts, sfacts; 510 int mrest, srest; 511 Client *c; 512 513 514 int oh, ov, ih, iv; 515 getgaps(m, &oh, &ov, &ih, &iv, &n); 516 517 if (n == 0) 518 return; 519 520 sx = mx = m->wx + ov; 521 sy = my = m->wy + oh; 522 mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); 523 sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); 524 sw = mw = m->ww - 2*ov; 525 526 if (m->nmaster && n > m->nmaster) { 527 sw = (mw - iv) * (1 - m->mfact); 528 mw = (mw - iv) * m->mfact; 529 sx = mx + mw + iv; 530 } 531 532 getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); 533 534 for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 535 if (i < m->nmaster) { 536 resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); 537 my += HEIGHT(c) + ih; 538 } else { 539 resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); 540 sy += HEIGHT(c) + ih; 541 } 542 }