dwm

suckless dynamic window manager
git clone https://git.beauhilton.com/dwm.git
Log | Files | Refs | README | LICENSE

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 }