dwm

My fork of dwm.
git clone git://git.alex.balgavy.eu/dwm.git
Log | Files | Refs | README | LICENSE

vanitygaps.c (18676B)


      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 /* Layouts (delete the ones you do not need) */
     12 static void bstack(Monitor *m);
     13 static void bstackhoriz(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 grid(Monitor *m);
     20 static void nrowgrid(Monitor *m);
     21 static void spiral(Monitor *m);
     22 static void tile(Monitor *m);
     23 /* Internals */
     24 static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
     25 static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
     26 static void setgaps(int oh, int ov, int ih, int iv);
     27 
     28 /* Settings */
     29 #if !PERTAG_PATCH
     30 static int enablegaps = 1;
     31 #endif // PERTAG_PATCH
     32 
     33 void
     34 setgaps(int oh, int ov, int ih, int iv)
     35 {
     36 	if (oh < 0) oh = 0;
     37 	if (ov < 0) ov = 0;
     38 	if (ih < 0) ih = 0;
     39 	if (iv < 0) iv = 0;
     40 
     41 	selmon->gappoh = oh;
     42 	selmon->gappov = ov;
     43 	selmon->gappih = ih;
     44 	selmon->gappiv = iv;
     45 	arrange(selmon);
     46 }
     47 
     48 void
     49 togglegaps(const Arg *arg)
     50 {
     51 	#if PERTAG_PATCH
     52 	selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
     53 	#else
     54 	enablegaps = !enablegaps;
     55 	#endif // PERTAG_PATCH
     56 	arrange(NULL);
     57 }
     58 
     59 void
     60 defaultgaps(const Arg *arg)
     61 {
     62 	setgaps(gappoh, gappov, gappih, gappiv);
     63 }
     64 
     65 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 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 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 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 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 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 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 void
    143 getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
    144 {
    145 	unsigned int n, oe, ie;
    146 	#if PERTAG_PATCH
    147 	oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
    148 	#else
    149 	oe = ie = enablegaps;
    150 	#endif // PERTAG_PATCH
    151 	Client *c;
    152 
    153 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    154 	if (smartgaps && n == 1) {
    155 		oe = 0; // outer gaps disabled when only one client
    156 	}
    157 
    158 	*oh = m->gappoh*oe; // outer horizontal gap
    159 	*ov = m->gappov*oe; // outer vertical gap
    160 	*ih = m->gappih*ie; // inner horizontal gap
    161 	*iv = m->gappiv*ie; // inner vertical gap
    162 	*nc = n;            // number of clients
    163 }
    164 
    165 void
    166 getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
    167 {
    168 	unsigned int n;
    169 	float mfacts, sfacts;
    170 	int mtotal = 0, stotal = 0;
    171 	Client *c;
    172 
    173 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    174 	mfacts = MIN(n, m->nmaster);
    175 	sfacts = n - m->nmaster;
    176 
    177 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
    178 		if (n < m->nmaster)
    179 			mtotal += msize / mfacts;
    180 		else
    181 			stotal += ssize / sfacts;
    182 
    183 	*mf = mfacts; // total factor of master area
    184 	*sf = sfacts; // total factor of stack area
    185 	*mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
    186 	*sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
    187 }
    188 
    189 /***
    190  * Layouts
    191  */
    192 
    193 /*
    194  * Bottomstack layout + gaps
    195  * https://dwm.suckless.org/patches/bottomstack/
    196  */
    197 static void
    198 bstack(Monitor *m)
    199 {
    200 	unsigned int i, n;
    201 	int oh, ov, ih, iv;
    202 	int mx = 0, my = 0, mh = 0, mw = 0;
    203 	int sx = 0, sy = 0, sh = 0, sw = 0;
    204 	float mfacts, sfacts;
    205 	int mrest, srest;
    206 	Client *c;
    207 
    208 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    209 	if (n == 0)
    210 		return;
    211 
    212 	sx = mx = m->wx + ov;
    213 	sy = my = m->wy + oh;
    214 	sh = mh = m->wh - 2*oh;
    215 	mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
    216 	sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
    217 
    218 	if (m->nmaster && n > m->nmaster) {
    219 		sh = (mh - ih) * (1 - m->mfact);
    220 		mh = mh - ih - sh;
    221 		sx = mx;
    222 		sy = my + mh + ih;
    223 	}
    224 
    225 	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
    226 
    227 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    228 		if (i < m->nmaster) {
    229 			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
    230 			mx += WIDTH(c) + iv;
    231 		} else {
    232 			resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
    233 			sx += WIDTH(c) + iv;
    234 		}
    235 	}
    236 }
    237 
    238 static void
    239 bstackhoriz(Monitor *m)
    240 {
    241 	unsigned int i, n;
    242 	int oh, ov, ih, iv;
    243 	int mx = 0, my = 0, mh = 0, mw = 0;
    244 	int sx = 0, sy = 0, sh = 0, sw = 0;
    245 	float mfacts, sfacts;
    246 	int mrest, srest;
    247 	Client *c;
    248 
    249 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    250 	if (n == 0)
    251 		return;
    252 
    253 	sx = mx = m->wx + ov;
    254 	sy = my = m->wy + oh;
    255 	mh = m->wh - 2*oh;
    256 	sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
    257 	mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
    258 	sw = m->ww - 2*ov;
    259 
    260 	if (m->nmaster && n > m->nmaster) {
    261 		sh = (mh - ih) * (1 - m->mfact);
    262 		mh = mh - ih - sh;
    263 		sy = my + mh + ih;
    264 		sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
    265 	}
    266 
    267 	getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
    268 
    269 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    270 		if (i < m->nmaster) {
    271 			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
    272 			mx += WIDTH(c) + iv;
    273 		} else {
    274 			resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
    275 			sy += HEIGHT(c) + ih;
    276 		}
    277 	}
    278 }
    279 
    280 /*
    281  * Centred master layout + gaps
    282  * https://dwm.suckless.org/patches/centeredmaster/
    283  */
    284 void
    285 centeredmaster(Monitor *m)
    286 {
    287 	unsigned int i, n;
    288 	int oh, ov, ih, iv;
    289 	int mx = 0, my = 0, mh = 0, mw = 0;
    290 	int lx = 0, ly = 0, lw = 0, lh = 0;
    291 	int rx = 0, ry = 0, rw = 0, rh = 0;
    292 	float mfacts = 0, lfacts = 0, rfacts = 0;
    293 	int mtotal = 0, ltotal = 0, rtotal = 0;
    294 	int mrest = 0, lrest = 0, rrest = 0;
    295 	Client *c;
    296 
    297 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    298 	if (n == 0)
    299 		return;
    300 
    301 	/* initialize areas */
    302 	mx = m->wx + ov;
    303 	my = m->wy + oh;
    304 	mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
    305 	mw = m->ww - 2*ov;
    306 	lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
    307 	rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
    308 
    309 	if (m->nmaster && n > m->nmaster) {
    310 		/* go mfact box in the center if more than nmaster clients */
    311 		if (n - m->nmaster > 1) {
    312 			/* ||<-S->|<---M--->|<-S->|| */
    313 			mw = (m->ww - 2*ov - 2*iv) * m->mfact;
    314 			lw = (m->ww - mw - 2*ov - 2*iv) / 2;
    315 			rw = (m->ww - mw - 2*ov - 2*iv) - lw;
    316 			mx += lw + iv;
    317 		} else {
    318 			/* ||<---M--->|<-S->|| */
    319 			mw = (mw - iv) * m->mfact;
    320 			lw = 0;
    321 			rw = m->ww - mw - iv - 2*ov;
    322 		}
    323 		lx = m->wx + ov;
    324 		ly = m->wy + oh;
    325 		rx = mx + mw + iv;
    326 		ry = m->wy + oh;
    327 	}
    328 
    329 	/* calculate facts */
    330 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
    331 		if (!m->nmaster || n < m->nmaster)
    332 			mfacts += 1;
    333 		else if ((n - m->nmaster) % 2)
    334 			lfacts += 1; // total factor of left hand stack area
    335 		else
    336 			rfacts += 1; // total factor of right hand stack area
    337 	}
    338 
    339 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
    340 		if (!m->nmaster || n < m->nmaster)
    341 			mtotal += mh / mfacts;
    342 		else if ((n - m->nmaster) % 2)
    343 			ltotal += lh / lfacts;
    344 		else
    345 			rtotal += rh / rfacts;
    346 
    347 	mrest = mh - mtotal;
    348 	lrest = lh - ltotal;
    349 	rrest = rh - rtotal;
    350 
    351 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    352 		if (!m->nmaster || i < m->nmaster) {
    353 			/* nmaster clients are stacked vertically, in the center of the screen */
    354 			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
    355 			my += HEIGHT(c) + ih;
    356 		} else {
    357 			/* stack clients are stacked vertically */
    358 			if ((i - m->nmaster) % 2 ) {
    359 				resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
    360 				ly += HEIGHT(c) + ih;
    361 			} else {
    362 				resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
    363 				ry += HEIGHT(c) + ih;
    364 			}
    365 		}
    366 	}
    367 }
    368 
    369 void
    370 centeredfloatingmaster(Monitor *m)
    371 {
    372 	unsigned int i, n;
    373 	float mfacts, sfacts;
    374 	float mivf = 1.0; // master inner vertical gap factor
    375 	int oh, ov, ih, iv, mrest, srest;
    376 	int mx = 0, my = 0, mh = 0, mw = 0;
    377 	int sx = 0, sy = 0, sh = 0, sw = 0;
    378 	Client *c;
    379 
    380 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    381 	if (n == 0)
    382 		return;
    383 
    384 	sx = mx = m->wx + ov;
    385 	sy = my = m->wy + oh;
    386 	sh = mh = m->wh - 2*oh;
    387 	mw = m->ww - 2*ov - iv*(n - 1);
    388 	sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
    389 
    390 	if (m->nmaster && n > m->nmaster) {
    391 		mivf = 0.8;
    392 		/* go mfact box in the center if more than nmaster clients */
    393 		if (m->ww > m->wh) {
    394 			mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
    395 			mh = m->wh * 0.9;
    396 		} else {
    397 			mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
    398 			mh = m->wh * m->mfact;
    399 		}
    400 		mx = m->wx + (m->ww - mw) / 2;
    401 		my = m->wy + (m->wh - mh - 2*oh) / 2;
    402 
    403 		sx = m->wx + ov;
    404 		sy = m->wy + oh;
    405 		sh = m->wh - 2*oh;
    406 	}
    407 
    408 	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
    409 
    410 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    411 		if (i < m->nmaster) {
    412 			/* nmaster clients are stacked horizontally, in the center of the screen */
    413 			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
    414 			mx += WIDTH(c) + iv*mivf;
    415 		} else {
    416 			/* stack clients are stacked horizontally */
    417 			resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
    418 			sx += WIDTH(c) + iv;
    419 		}
    420 }
    421 
    422 /*
    423  * Deck layout + gaps
    424  * https://dwm.suckless.org/patches/deck/
    425  */
    426 void
    427 deck(Monitor *m)
    428 {
    429 	unsigned int i, n;
    430 	int oh, ov, ih, iv;
    431 	int mx = 0, my = 0, mh = 0, mw = 0;
    432 	int sx = 0, sy = 0, sh = 0, sw = 0;
    433 	float mfacts, sfacts;
    434 	int mrest, srest;
    435 	Client *c;
    436 
    437 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    438 	if (n == 0)
    439 		return;
    440 
    441 	sx = mx = m->wx + ov;
    442 	sy = my = m->wy + oh;
    443 	sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
    444 	sw = mw = m->ww - 2*ov;
    445 
    446 	if (m->nmaster && n > m->nmaster) {
    447 		sw = (mw - iv) * (1 - m->mfact);
    448 		mw = mw - iv - sw;
    449 		sx = mx + mw + iv;
    450 		sh = m->wh - 2*oh;
    451 	}
    452 
    453 	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
    454 
    455 	if (n - m->nmaster > 0) /* override layout symbol */
    456 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
    457 
    458 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    459 		if (i < m->nmaster) {
    460 			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
    461 			my += HEIGHT(c) + ih;
    462 		} else {
    463 			resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
    464 		}
    465 }
    466 
    467 /*
    468  * Fibonacci layout + gaps
    469  * https://dwm.suckless.org/patches/fibonacci/
    470  */
    471 void
    472 fibonacci(Monitor *m, int s)
    473 {
    474 	unsigned int i, n;
    475 	int nx, ny, nw, nh;
    476 	int oh, ov, ih, iv;
    477 	int nv, hrest = 0, wrest = 0, r = 1;
    478 	Client *c;
    479 
    480 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    481 	if (n == 0)
    482 		return;
    483 
    484 	nx = m->wx + ov;
    485 	ny = m->wy + oh;
    486 	nw = m->ww - 2*ov;
    487 	nh = m->wh - 2*oh;
    488 
    489 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
    490 		if (r) {
    491 			if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
    492 			   || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
    493 				r = 0;
    494 			}
    495 			if (r && i < n - 1) {
    496 				if (i % 2) {
    497 					nv = (nh - ih) / 2;
    498 					hrest = nh - 2*nv - ih;
    499 					nh = nv;
    500 				} else {
    501 					nv = (nw - iv) / 2;
    502 					wrest = nw - 2*nv - iv;
    503 					nw = nv;
    504 				}
    505 
    506 				if ((i % 4) == 2 && !s)
    507 					nx += nw + iv;
    508 				else if ((i % 4) == 3 && !s)
    509 					ny += nh + ih;
    510 			}
    511 
    512 			if ((i % 4) == 0) {
    513 				if (s) {
    514 					ny += nh + ih;
    515 					nh += hrest;
    516 				}
    517 				else {
    518 					nh -= hrest;
    519 					ny -= nh + ih;
    520 				}
    521 			}
    522 			else if ((i % 4) == 1) {
    523 				nx += nw + iv;
    524 				nw += wrest;
    525 			}
    526 			else if ((i % 4) == 2) {
    527 				ny += nh + ih;
    528 				nh += hrest;
    529 				if (i < n - 1)
    530 					nw += wrest;
    531 			}
    532 			else if ((i % 4) == 3) {
    533 				if (s) {
    534 					nx += nw + iv;
    535 					nw -= wrest;
    536 				} else {
    537 					nw -= wrest;
    538 					nx -= nw + iv;
    539 					nh += hrest;
    540 				}
    541 			}
    542 			if (i == 0)	{
    543 				if (n != 1) {
    544 					nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
    545 					wrest = 0;
    546 				}
    547 				ny = m->wy + oh;
    548 			}
    549 			else if (i == 1)
    550 				nw = m->ww - nw - iv - 2*ov;
    551 			i++;
    552 		}
    553 
    554 		resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
    555 	}
    556 }
    557 
    558 void
    559 dwindle(Monitor *m)
    560 {
    561 	fibonacci(m, 1);
    562 }
    563 
    564 void
    565 spiral(Monitor *m)
    566 {
    567 	fibonacci(m, 0);
    568 }
    569 
    570 /*
    571  * Gappless grid layout + gaps (ironically)
    572  * https://dwm.suckless.org/patches/gaplessgrid/
    573  */
    574 void
    575 gaplessgrid(Monitor *m)
    576 {
    577 	unsigned int i, n;
    578 	int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
    579 	int oh, ov, ih, iv;
    580 	Client *c;
    581 
    582 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    583 	if (n == 0)
    584 		return;
    585 
    586 	/* grid dimensions */
    587 	for (cols = 0; cols <= n/2; cols++)
    588 		if (cols*cols >= n)
    589 			break;
    590 	if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
    591 		cols = 2;
    592 	rows = n/cols;
    593 	cn = rn = 0; // reset column no, row no, client count
    594 
    595 	ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
    596 	cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
    597 	rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
    598 	crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
    599 	x = m->wx + ov;
    600 	y = m->wy + oh;
    601 
    602 	for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
    603 		if (i/rows + 1 > cols - n%cols) {
    604 			rows = n/cols + 1;
    605 			ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
    606 			rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
    607 		}
    608 		resize(c,
    609 			x,
    610 			y + rn*(ch + ih) + MIN(rn, rrest),
    611 			cw + (cn < crest ? 1 : 0) - 2*c->bw,
    612 			ch + (rn < rrest ? 1 : 0) - 2*c->bw,
    613 			0);
    614 		rn++;
    615 		if (rn >= rows) {
    616 			rn = 0;
    617 			x += cw + ih + (cn < crest ? 1 : 0);
    618 			cn++;
    619 		}
    620 	}
    621 }
    622 
    623 /*
    624  * Gridmode layout + gaps
    625  * https://dwm.suckless.org/patches/gridmode/
    626  */
    627 void
    628 grid(Monitor *m)
    629 {
    630 	unsigned int i, n;
    631 	int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
    632 	int oh, ov, ih, iv;
    633 	Client *c;
    634 
    635 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    636 
    637 	/* grid dimensions */
    638 	for (rows = 0; rows <= n/2; rows++)
    639 		if (rows*rows >= n)
    640 			break;
    641 	cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
    642 
    643 	/* window geoms (cell height/width) */
    644 	ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
    645 	cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
    646 	chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
    647 	cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
    648 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    649 		cc = i / rows;
    650 		cr = i % rows;
    651 		cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
    652 		cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
    653 		resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
    654 	}
    655 }
    656 
    657 /*
    658  * Horizontal grid layout + gaps
    659  * https://dwm.suckless.org/patches/horizgrid/
    660  */
    661 void
    662 horizgrid(Monitor *m) {
    663 	Client *c;
    664 	unsigned int n, i;
    665 	int oh, ov, ih, iv;
    666 	int mx = 0, my = 0, mh = 0, mw = 0;
    667 	int sx = 0, sy = 0, sh = 0, sw = 0;
    668 	int ntop, nbottom = 1;
    669 	float mfacts, sfacts;
    670 	int mrest, srest;
    671 
    672 	/* Count windows */
    673 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    674 	if (n == 0)
    675 		return;
    676 
    677 	if (n <= 2)
    678 		ntop = n;
    679 	else {
    680 		ntop = n / 2;
    681 		nbottom = n - ntop;
    682 	}
    683 	sx = mx = m->wx + ov;
    684 	sy = my = m->wy + oh;
    685 	sh = mh = m->wh - 2*oh;
    686 	sw = mw = m->ww - 2*ov;
    687 
    688 	if (n > ntop) {
    689 		sh = (mh - ih) / 2;
    690 		mh = mh - ih - sh;
    691 		sy = my + mh + ih;
    692 		mw = m->ww - 2*ov - iv * (ntop - 1);
    693 		sw = m->ww - 2*ov - iv * (nbottom - 1);
    694 	}
    695 
    696 	mfacts = ntop;
    697 	sfacts = nbottom;
    698 	mrest = mw - (mw / ntop) * ntop;
    699 	srest = sw - (sw / nbottom) * nbottom;
    700 
    701 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    702 		if (i < ntop) {
    703 			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
    704 			mx += WIDTH(c) + iv;
    705 		} else {
    706 			resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
    707 			sx += WIDTH(c) + iv;
    708 		}
    709 }
    710 
    711 /*
    712  * nrowgrid layout + gaps
    713  * https://dwm.suckless.org/patches/nrowgrid/
    714  */
    715 void
    716 nrowgrid(Monitor *m)
    717 {
    718 	unsigned int n;
    719 	int ri = 0, ci = 0;  /* counters */
    720 	int oh, ov, ih, iv;                         /* vanitygap settings */
    721 	unsigned int cx, cy, cw, ch;                /* client geometry */
    722 	unsigned int uw = 0, uh = 0, uc = 0;        /* utilization trackers */
    723 	unsigned int cols, rows = m->nmaster + 1;
    724 	Client *c;
    725 
    726 	/* count clients */
    727 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    728 
    729 	/* nothing to do here */
    730 	if (n == 0)
    731 		return;
    732 
    733 	/* force 2 clients to always split vertically */
    734 	if (FORCE_VSPLIT && n == 2)
    735 		rows = 1;
    736 
    737 	/* never allow empty rows */
    738 	if (n < rows)
    739 		rows = n;
    740 
    741 	/* define first row */
    742 	cols = n / rows;
    743 	uc = cols;
    744 	cy = m->wy + oh;
    745 	ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
    746 	uh = ch;
    747 
    748 	for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
    749 		if (ci == cols) {
    750 			uw = 0;
    751 			ci = 0;
    752 			ri++;
    753 
    754 			/* next row */
    755 			cols = (n - uc) / (rows - ri);
    756 			uc += cols;
    757 			cy = m->wy + oh + uh + ih;
    758 			uh += ch + ih;
    759 		}
    760 
    761 		cx = m->wx + ov + uw;
    762 		cw = (m->ww - 2*ov - uw) / (cols - ci);
    763 		uw += cw + iv;
    764 
    765 		resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
    766 	}
    767 }
    768 
    769 /*
    770  * Default tile layout + gaps
    771  */
    772 static void
    773 tile(Monitor *m)
    774 {
    775 	unsigned int i, n;
    776 	int oh, ov, ih, iv;
    777 	int mx = 0, my = 0, mh = 0, mw = 0;
    778 	int sx = 0, sy = 0, sh = 0, sw = 0;
    779 	float mfacts, sfacts;
    780 	int mrest, srest;
    781 	Client *c;
    782 
    783 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    784 	if (n == 0)
    785 		return;
    786 
    787 	sx = mx = m->wx + ov;
    788 	sy = my = m->wy + oh;
    789 	mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
    790 	sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
    791 	sw = mw = m->ww - 2*ov;
    792 
    793 	if (m->nmaster && n > m->nmaster) {
    794 		sw = (mw - iv) * (1 - m->mfact);
    795 		mw = mw - iv - sw;
    796 		sx = mx + mw + iv;
    797 	}
    798 
    799 	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
    800 
    801 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    802 		if (i < m->nmaster) {
    803 			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
    804 			my += HEIGHT(c) + ih;
    805 		} else {
    806 			resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
    807 			sy += HEIGHT(c) + ih;
    808 		}
    809 }