dwm

my customized branch of dwm
git clone git://git.jakekoroman.com/dwm
Log | Files | Refs | README | LICENSE

vanitygaps.c (19251B)


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