dwm

git clone git://mattcarlson.org/repos/dwm.git
Log | Files | Refs

vanitygaps.c (18649B)


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