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