dwm

dwm

https://git.tonybtw.com/dwm.git git://git.tonybtw.com/dwm.git
26,032 bytes raw
1
From 9709d08daa290c8c7319571cd9e6ef4ec40e7683 Mon Sep 17 00:00:00 2001
2
From: bakkeby <bakkeby@gmail.com>
3
Date: Wed, 6 May 2020 17:21:25 +0200
4
Subject: [PATCH] vanitygaps - adds gaps to layouts
5
6
This patch differentiates between inner and outer gaps as well as
7
horizontal and vertical gaps.
8
9
The logic of these layouts also aims to be pixel perfect by ensuring
10
an even split of the available space and re-distributing the remainder
11
among the available clients.
12
---
13
 config.def.h |  38 ++-
14
 dwm.c        |  35 +--
15
 vanitygaps.c | 809 +++++++++++++++++++++++++++++++++++++++++++++++++++
16
 3 files changed, 854 insertions(+), 28 deletions(-)
17
 create mode 100644 vanitygaps.c
18
19
diff --git a/config.def.h b/config.def.h
20
index 1c0b587..a886863 100644
21
--- a/config.def.h
22
+++ b/config.def.h
23
@@ -3,6 +3,11 @@
24
 /* appearance */
25
 static const unsigned int borderpx  = 1;        /* border pixel of windows */
26
 static const unsigned int snap      = 32;       /* snap pixel */
27
+static const unsigned int gappih    = 20;       /* horiz inner gap between windows */
28
+static const unsigned int gappiv    = 10;       /* vert inner gap between windows */
29
+static const unsigned int gappoh    = 10;       /* horiz outer gap between windows and screen edge */
30
+static const unsigned int gappov    = 30;       /* vert outer gap between windows and screen edge */
31
+static       int smartgaps          = 0;        /* 1 means no outer gap when there is only one window */
32
 static const int showbar            = 1;        /* 0 means no bar */
33
 static const int topbar             = 1;        /* 0 means bottom bar */
34
 static const char *fonts[]          = { "monospace:size=10" };
35
@@ -36,11 +41,26 @@ static const float mfact     = 0.55; /* factor of master area size [0.05..0.95]
36
 static const int nmaster     = 1;    /* number of clients in master area */
37
 static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */
38
 
39
+#define FORCE_VSPLIT 1  /* nrowgrid layout: force two clients to always split vertically */
40
+#include "vanitygaps.c"
41
+
42
 static const Layout layouts[] = {
43
 	/* symbol     arrange function */
44
 	{ "[]=",      tile },    /* first entry is default */
45
-	{ "><>",      NULL },    /* no layout function means floating behavior */
46
 	{ "[M]",      monocle },
47
+	{ "[@]",      spiral },
48
+	{ "[\\]",     dwindle },
49
+	{ "H[]",      deck },
50
+	{ "TTT",      bstack },
51
+	{ "===",      bstackhoriz },
52
+	{ "HHH",      grid },
53
+	{ "###",      nrowgrid },
54
+	{ "---",      horizgrid },
55
+	{ ":::",      gaplessgrid },
56
+	{ "|M|",      centeredmaster },
57
+	{ ">M>",      centeredfloatingmaster },
58
+	{ "><>",      NULL },    /* no layout function means floating behavior */
59
+	{ NULL,       NULL },
60
 };
61
 
62
 /* key definitions */
63
@@ -71,6 +91,22 @@ static Key keys[] = {
64
 	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
65
 	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
66
 	{ MODKEY,                       XK_Return, zoom,           {0} },
67
+	{ MODKEY|Mod4Mask,              XK_u,      incrgaps,       {.i = +1 } },
68
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_u,      incrgaps,       {.i = -1 } },
69
+	{ MODKEY|Mod4Mask,              XK_i,      incrigaps,      {.i = +1 } },
70
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_i,      incrigaps,      {.i = -1 } },
71
+	{ MODKEY|Mod4Mask,              XK_o,      incrogaps,      {.i = +1 } },
72
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_o,      incrogaps,      {.i = -1 } },
73
+	{ MODKEY|Mod4Mask,              XK_6,      incrihgaps,     {.i = +1 } },
74
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_6,      incrihgaps,     {.i = -1 } },
75
+	{ MODKEY|Mod4Mask,              XK_7,      incrivgaps,     {.i = +1 } },
76
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_7,      incrivgaps,     {.i = -1 } },
77
+	{ MODKEY|Mod4Mask,              XK_8,      incrohgaps,     {.i = +1 } },
78
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_8,      incrohgaps,     {.i = -1 } },
79
+	{ MODKEY|Mod4Mask,              XK_9,      incrovgaps,     {.i = +1 } },
80
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_9,      incrovgaps,     {.i = -1 } },
81
+	{ MODKEY|Mod4Mask,              XK_0,      togglegaps,     {0} },
82
+	{ MODKEY|Mod4Mask|ShiftMask,    XK_0,      defaultgaps,    {0} },
83
 	{ MODKEY,                       XK_Tab,    view,           {0} },
84
 	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
85
 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} },
86
diff --git a/dwm.c b/dwm.c
87
index 4465af1..c3b2d82 100644
88
--- a/dwm.c
89
+++ b/dwm.c
90
@@ -119,6 +119,10 @@ struct Monitor {
91
 	int by;               /* bar geometry */
92
 	int mx, my, mw, mh;   /* screen size */
93
 	int wx, wy, ww, wh;   /* window area  */
94
+	int gappih;           /* horizontal gap between windows */
95
+	int gappiv;           /* vertical gap between windows */
96
+	int gappoh;           /* horizontal outer gaps */
97
+	int gappov;           /* vertical outer gaps */
98
 	unsigned int seltags;
99
 	unsigned int sellt;
100
 	unsigned int tagset[2];
101
@@ -208,7 +212,6 @@ static void sigchld(int unused);
102
 static void spawn(const Arg *arg);
103
 static void tag(const Arg *arg);
104
 static void tagmon(const Arg *arg);
105
-static void tile(Monitor *);
106
 static void togglebar(const Arg *arg);
107
 static void togglefloating(const Arg *arg);
108
 static void toggletag(const Arg *arg);
109
@@ -638,6 +641,10 @@ createmon(void)
110
 	m->nmaster = nmaster;
111
 	m->showbar = showbar;
112
 	m->topbar = topbar;
113
+	m->gappih = gappih;
114
+	m->gappiv = gappiv;
115
+	m->gappoh = gappoh;
116
+	m->gappov = gappov;
117
 	m->lt[0] = &layouts[0];
118
 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
119
 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
120
@@ -1670,32 +1677,6 @@ tagmon(const Arg *arg)
121
 	sendmon(selmon->sel, dirtomon(arg->i));
122
 }
123
 
124
-void
125
-tile(Monitor *m)
126
-{
127
-	unsigned int i, n, h, mw, my, ty;
128
-	Client *c;
129
-
130
-	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
131
-	if (n == 0)
132
-		return;
133
-
134
-	if (n > m->nmaster)
135
-		mw = m->nmaster ? m->ww * m->mfact : 0;
136
-	else
137
-		mw = m->ww;
138
-	for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
139
-		if (i < m->nmaster) {
140
-			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
141
-			resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
142
-			my += HEIGHT(c);
143
-		} else {
144
-			h = (m->wh - ty) / (n - i);
145
-			resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
146
-			ty += HEIGHT(c);
147
-		}
148
-}
149
-
150
 void
151
 togglebar(const Arg *arg)
152
 {
153
diff --git a/vanitygaps.c b/vanitygaps.c
154
new file mode 100644
155
index 0000000..3f31593
156
--- /dev/null
157
+++ b/vanitygaps.c
158
@@ -0,0 +1,809 @@
159
+/* Key binding functions */
160
+static void defaultgaps(const Arg *arg);
161
+static void incrgaps(const Arg *arg);
162
+static void incrigaps(const Arg *arg);
163
+static void incrogaps(const Arg *arg);
164
+static void incrohgaps(const Arg *arg);
165
+static void incrovgaps(const Arg *arg);
166
+static void incrihgaps(const Arg *arg);
167
+static void incrivgaps(const Arg *arg);
168
+static void togglegaps(const Arg *arg);
169
+/* Layouts (delete the ones you do not need) */
170
+static void bstack(Monitor *m);
171
+static void bstackhoriz(Monitor *m);
172
+static void centeredmaster(Monitor *m);
173
+static void centeredfloatingmaster(Monitor *m);
174
+static void deck(Monitor *m);
175
+static void dwindle(Monitor *m);
176
+static void fibonacci(Monitor *m, int s);
177
+static void grid(Monitor *m);
178
+static void nrowgrid(Monitor *m);
179
+static void spiral(Monitor *m);
180
+static void tile(Monitor *m);
181
+/* Internals */
182
+static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
183
+static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
184
+static void setgaps(int oh, int ov, int ih, int iv);
185
+
186
+/* Settings */
187
+#if !PERTAG_PATCH
188
+static int enablegaps = 1;
189
+#endif // PERTAG_PATCH
190
+
191
+void
192
+setgaps(int oh, int ov, int ih, int iv)
193
+{
194
+	if (oh < 0) oh = 0;
195
+	if (ov < 0) ov = 0;
196
+	if (ih < 0) ih = 0;
197
+	if (iv < 0) iv = 0;
198
+
199
+	selmon->gappoh = oh;
200
+	selmon->gappov = ov;
201
+	selmon->gappih = ih;
202
+	selmon->gappiv = iv;
203
+	arrange(selmon);
204
+}
205
+
206
+void
207
+togglegaps(const Arg *arg)
208
+{
209
+	#if PERTAG_PATCH
210
+	selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
211
+	#else
212
+	enablegaps = !enablegaps;
213
+	#endif // PERTAG_PATCH
214
+	arrange(NULL);
215
+}
216
+
217
+void
218
+defaultgaps(const Arg *arg)
219
+{
220
+	setgaps(gappoh, gappov, gappih, gappiv);
221
+}
222
+
223
+void
224
+incrgaps(const Arg *arg)
225
+{
226
+	setgaps(
227
+		selmon->gappoh + arg->i,
228
+		selmon->gappov + arg->i,
229
+		selmon->gappih + arg->i,
230
+		selmon->gappiv + arg->i
231
+	);
232
+}
233
+
234
+void
235
+incrigaps(const Arg *arg)
236
+{
237
+	setgaps(
238
+		selmon->gappoh,
239
+		selmon->gappov,
240
+		selmon->gappih + arg->i,
241
+		selmon->gappiv + arg->i
242
+	);
243
+}
244
+
245
+void
246
+incrogaps(const Arg *arg)
247
+{
248
+	setgaps(
249
+		selmon->gappoh + arg->i,
250
+		selmon->gappov + arg->i,
251
+		selmon->gappih,
252
+		selmon->gappiv
253
+	);
254
+}
255
+
256
+void
257
+incrohgaps(const Arg *arg)
258
+{
259
+	setgaps(
260
+		selmon->gappoh + arg->i,
261
+		selmon->gappov,
262
+		selmon->gappih,
263
+		selmon->gappiv
264
+	);
265
+}
266
+
267
+void
268
+incrovgaps(const Arg *arg)
269
+{
270
+	setgaps(
271
+		selmon->gappoh,
272
+		selmon->gappov + arg->i,
273
+		selmon->gappih,
274
+		selmon->gappiv
275
+	);
276
+}
277
+
278
+void
279
+incrihgaps(const Arg *arg)
280
+{
281
+	setgaps(
282
+		selmon->gappoh,
283
+		selmon->gappov,
284
+		selmon->gappih + arg->i,
285
+		selmon->gappiv
286
+	);
287
+}
288
+
289
+void
290
+incrivgaps(const Arg *arg)
291
+{
292
+	setgaps(
293
+		selmon->gappoh,
294
+		selmon->gappov,
295
+		selmon->gappih,
296
+		selmon->gappiv + arg->i
297
+	);
298
+}
299
+
300
+void
301
+getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
302
+{
303
+	unsigned int n, oe, ie;
304
+	#if PERTAG_PATCH
305
+	oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
306
+	#else
307
+	oe = ie = enablegaps;
308
+	#endif // PERTAG_PATCH
309
+	Client *c;
310
+
311
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
312
+	if (smartgaps && n == 1) {
313
+		oe = 0; // outer gaps disabled when only one client
314
+	}
315
+
316
+	*oh = m->gappoh*oe; // outer horizontal gap
317
+	*ov = m->gappov*oe; // outer vertical gap
318
+	*ih = m->gappih*ie; // inner horizontal gap
319
+	*iv = m->gappiv*ie; // inner vertical gap
320
+	*nc = n;            // number of clients
321
+}
322
+
323
+void
324
+getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
325
+{
326
+	unsigned int n;
327
+	float mfacts, sfacts;
328
+	int mtotal = 0, stotal = 0;
329
+	Client *c;
330
+
331
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
332
+	mfacts = MIN(n, m->nmaster);
333
+	sfacts = n - m->nmaster;
334
+
335
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
336
+		if (n < m->nmaster)
337
+			mtotal += msize / mfacts;
338
+		else
339
+			stotal += ssize / sfacts;
340
+
341
+	*mf = mfacts; // total factor of master area
342
+	*sf = sfacts; // total factor of stack area
343
+	*mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
344
+	*sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
345
+}
346
+
347
+/***
348
+ * Layouts
349
+ */
350
+
351
+/*
352
+ * Bottomstack layout + gaps
353
+ * https://dwm.suckless.org/patches/bottomstack/
354
+ */
355
+static void
356
+bstack(Monitor *m)
357
+{
358
+	unsigned int i, n;
359
+	int oh, ov, ih, iv;
360
+	int mx = 0, my = 0, mh = 0, mw = 0;
361
+	int sx = 0, sy = 0, sh = 0, sw = 0;
362
+	float mfacts, sfacts;
363
+	int mrest, srest;
364
+	Client *c;
365
+
366
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
367
+	if (n == 0)
368
+		return;
369
+
370
+	sx = mx = m->wx + ov;
371
+	sy = my = m->wy + oh;
372
+	sh = mh = m->wh - 2*oh;
373
+	mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
374
+	sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
375
+
376
+	if (m->nmaster && n > m->nmaster) {
377
+		sh = (mh - ih) * (1 - m->mfact);
378
+		mh = mh - ih - sh;
379
+		sx = mx;
380
+		sy = my + mh + ih;
381
+	}
382
+
383
+	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
384
+
385
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
386
+		if (i < m->nmaster) {
387
+			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
388
+			mx += WIDTH(c) + iv;
389
+		} else {
390
+			resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
391
+			sx += WIDTH(c) + iv;
392
+		}
393
+	}
394
+}
395
+
396
+static void
397
+bstackhoriz(Monitor *m)
398
+{
399
+	unsigned int i, n;
400
+	int oh, ov, ih, iv;
401
+	int mx = 0, my = 0, mh = 0, mw = 0;
402
+	int sx = 0, sy = 0, sh = 0, sw = 0;
403
+	float mfacts, sfacts;
404
+	int mrest, srest;
405
+	Client *c;
406
+
407
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
408
+	if (n == 0)
409
+		return;
410
+
411
+	sx = mx = m->wx + ov;
412
+	sy = my = m->wy + oh;
413
+	mh = m->wh - 2*oh;
414
+	sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
415
+	mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
416
+	sw = m->ww - 2*ov;
417
+
418
+	if (m->nmaster && n > m->nmaster) {
419
+		sh = (mh - ih) * (1 - m->mfact);
420
+		mh = mh - ih - sh;
421
+		sy = my + mh + ih;
422
+		sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
423
+	}
424
+
425
+	getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
426
+
427
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
428
+		if (i < m->nmaster) {
429
+			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
430
+			mx += WIDTH(c) + iv;
431
+		} else {
432
+			resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
433
+			sy += HEIGHT(c) + ih;
434
+		}
435
+	}
436
+}
437
+
438
+/*
439
+ * Centred master layout + gaps
440
+ * https://dwm.suckless.org/patches/centeredmaster/
441
+ */
442
+void
443
+centeredmaster(Monitor *m)
444
+{
445
+	unsigned int i, n;
446
+	int oh, ov, ih, iv;
447
+	int mx = 0, my = 0, mh = 0, mw = 0;
448
+	int lx = 0, ly = 0, lw = 0, lh = 0;
449
+	int rx = 0, ry = 0, rw = 0, rh = 0;
450
+	float mfacts = 0, lfacts = 0, rfacts = 0;
451
+	int mtotal = 0, ltotal = 0, rtotal = 0;
452
+	int mrest = 0, lrest = 0, rrest = 0;
453
+	Client *c;
454
+
455
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
456
+	if (n == 0)
457
+		return;
458
+
459
+	/* initialize areas */
460
+	mx = m->wx + ov;
461
+	my = m->wy + oh;
462
+	mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
463
+	mw = m->ww - 2*ov;
464
+	lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
465
+	rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
466
+
467
+	if (m->nmaster && n > m->nmaster) {
468
+		/* go mfact box in the center if more than nmaster clients */
469
+		if (n - m->nmaster > 1) {
470
+			/* ||<-S->|<---M--->|<-S->|| */
471
+			mw = (m->ww - 2*ov - 2*iv) * m->mfact;
472
+			lw = (m->ww - mw - 2*ov - 2*iv) / 2;
473
+			rw = (m->ww - mw - 2*ov - 2*iv) - lw;
474
+			mx += lw + iv;
475
+		} else {
476
+			/* ||<---M--->|<-S->|| */
477
+			mw = (mw - iv) * m->mfact;
478
+			lw = 0;
479
+			rw = m->ww - mw - iv - 2*ov;
480
+		}
481
+		lx = m->wx + ov;
482
+		ly = m->wy + oh;
483
+		rx = mx + mw + iv;
484
+		ry = m->wy + oh;
485
+	}
486
+
487
+	/* calculate facts */
488
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
489
+		if (!m->nmaster || n < m->nmaster)
490
+			mfacts += 1;
491
+		else if ((n - m->nmaster) % 2)
492
+			lfacts += 1; // total factor of left hand stack area
493
+		else
494
+			rfacts += 1; // total factor of right hand stack area
495
+	}
496
+
497
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
498
+		if (!m->nmaster || n < m->nmaster)
499
+			mtotal += mh / mfacts;
500
+		else if ((n - m->nmaster) % 2)
501
+			ltotal += lh / lfacts;
502
+		else
503
+			rtotal += rh / rfacts;
504
+
505
+	mrest = mh - mtotal;
506
+	lrest = lh - ltotal;
507
+	rrest = rh - rtotal;
508
+
509
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
510
+		if (!m->nmaster || i < m->nmaster) {
511
+			/* nmaster clients are stacked vertically, in the center of the screen */
512
+			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
513
+			my += HEIGHT(c) + ih;
514
+		} else {
515
+			/* stack clients are stacked vertically */
516
+			if ((i - m->nmaster) % 2 ) {
517
+				resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
518
+				ly += HEIGHT(c) + ih;
519
+			} else {
520
+				resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
521
+				ry += HEIGHT(c) + ih;
522
+			}
523
+		}
524
+	}
525
+}
526
+
527
+void
528
+centeredfloatingmaster(Monitor *m)
529
+{
530
+	unsigned int i, n;
531
+	float mfacts, sfacts;
532
+	float mivf = 1.0; // master inner vertical gap factor
533
+	int oh, ov, ih, iv, mrest, srest;
534
+	int mx = 0, my = 0, mh = 0, mw = 0;
535
+	int sx = 0, sy = 0, sh = 0, sw = 0;
536
+	Client *c;
537
+
538
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
539
+	if (n == 0)
540
+		return;
541
+
542
+	sx = mx = m->wx + ov;
543
+	sy = my = m->wy + oh;
544
+	sh = mh = m->wh - 2*oh;
545
+	mw = m->ww - 2*ov - iv*(n - 1);
546
+	sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
547
+
548
+	if (m->nmaster && n > m->nmaster) {
549
+		mivf = 0.8;
550
+		/* go mfact box in the center if more than nmaster clients */
551
+		if (m->ww > m->wh) {
552
+			mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
553
+			mh = m->wh * 0.9;
554
+		} else {
555
+			mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
556
+			mh = m->wh * m->mfact;
557
+		}
558
+		mx = m->wx + (m->ww - mw) / 2;
559
+		my = m->wy + (m->wh - mh - 2*oh) / 2;
560
+
561
+		sx = m->wx + ov;
562
+		sy = m->wy + oh;
563
+		sh = m->wh - 2*oh;
564
+	}
565
+
566
+	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
567
+
568
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
569
+		if (i < m->nmaster) {
570
+			/* nmaster clients are stacked horizontally, in the center of the screen */
571
+			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
572
+			mx += WIDTH(c) + iv*mivf;
573
+		} else {
574
+			/* stack clients are stacked horizontally */
575
+			resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
576
+			sx += WIDTH(c) + iv;
577
+		}
578
+}
579
+
580
+/*
581
+ * Deck layout + gaps
582
+ * https://dwm.suckless.org/patches/deck/
583
+ */
584
+void
585
+deck(Monitor *m)
586
+{
587
+	unsigned int i, n;
588
+	int oh, ov, ih, iv;
589
+	int mx = 0, my = 0, mh = 0, mw = 0;
590
+	int sx = 0, sy = 0, sh = 0, sw = 0;
591
+	float mfacts, sfacts;
592
+	int mrest, srest;
593
+	Client *c;
594
+
595
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
596
+	if (n == 0)
597
+		return;
598
+
599
+	sx = mx = m->wx + ov;
600
+	sy = my = m->wy + oh;
601
+	sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
602
+	sw = mw = m->ww - 2*ov;
603
+
604
+	if (m->nmaster && n > m->nmaster) {
605
+		sw = (mw - iv) * (1 - m->mfact);
606
+		mw = mw - iv - sw;
607
+		sx = mx + mw + iv;
608
+		sh = m->wh - 2*oh;
609
+	}
610
+
611
+	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
612
+
613
+	if (n - m->nmaster > 0) /* override layout symbol */
614
+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
615
+
616
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
617
+		if (i < m->nmaster) {
618
+			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
619
+			my += HEIGHT(c) + ih;
620
+		} else {
621
+			resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
622
+		}
623
+}
624
+
625
+/*
626
+ * Fibonacci layout + gaps
627
+ * https://dwm.suckless.org/patches/fibonacci/
628
+ */
629
+void
630
+fibonacci(Monitor *m, int s)
631
+{
632
+	unsigned int i, n;
633
+	int nx, ny, nw, nh;
634
+	int oh, ov, ih, iv;
635
+	int nv, hrest = 0, wrest = 0, r = 1;
636
+	Client *c;
637
+
638
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
639
+	if (n == 0)
640
+		return;
641
+
642
+	nx = m->wx + ov;
643
+	ny = m->wy + oh;
644
+	nw = m->ww - 2*ov;
645
+	nh = m->wh - 2*oh;
646
+
647
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
648
+		if (r) {
649
+			if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
650
+			   || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
651
+				r = 0;
652
+			}
653
+			if (r && i < n - 1) {
654
+				if (i % 2) {
655
+					nv = (nh - ih) / 2;
656
+					hrest = nh - 2*nv - ih;
657
+					nh = nv;
658
+				} else {
659
+					nv = (nw - iv) / 2;
660
+					wrest = nw - 2*nv - iv;
661
+					nw = nv;
662
+				}
663
+
664
+				if ((i % 4) == 2 && !s)
665
+					nx += nw + iv;
666
+				else if ((i % 4) == 3 && !s)
667
+					ny += nh + ih;
668
+			}
669
+
670
+			if ((i % 4) == 0) {
671
+				if (s) {
672
+					ny += nh + ih;
673
+					nh += hrest;
674
+				}
675
+				else {
676
+					nh -= hrest;
677
+					ny -= nh + ih;
678
+				}
679
+			}
680
+			else if ((i % 4) == 1) {
681
+				nx += nw + iv;
682
+				nw += wrest;
683
+			}
684
+			else if ((i % 4) == 2) {
685
+				ny += nh + ih;
686
+				nh += hrest;
687
+				if (i < n - 1)
688
+					nw += wrest;
689
+			}
690
+			else if ((i % 4) == 3) {
691
+				if (s) {
692
+					nx += nw + iv;
693
+					nw -= wrest;
694
+				} else {
695
+					nw -= wrest;
696
+					nx -= nw + iv;
697
+					nh += hrest;
698
+				}
699
+			}
700
+			if (i == 0)	{
701
+				if (n != 1) {
702
+					nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
703
+					wrest = 0;
704
+				}
705
+				ny = m->wy + oh;
706
+			}
707
+			else if (i == 1)
708
+				nw = m->ww - nw - iv - 2*ov;
709
+			i++;
710
+		}
711
+
712
+		resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
713
+	}
714
+}
715
+
716
+void
717
+dwindle(Monitor *m)
718
+{
719
+	fibonacci(m, 1);
720
+}
721
+
722
+void
723
+spiral(Monitor *m)
724
+{
725
+	fibonacci(m, 0);
726
+}
727
+
728
+/*
729
+ * Gappless grid layout + gaps (ironically)
730
+ * https://dwm.suckless.org/patches/gaplessgrid/
731
+ */
732
+void
733
+gaplessgrid(Monitor *m)
734
+{
735
+	unsigned int i, n;
736
+	int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
737
+	int oh, ov, ih, iv;
738
+	Client *c;
739
+
740
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
741
+	if (n == 0)
742
+		return;
743
+
744
+	/* grid dimensions */
745
+	for (cols = 0; cols <= n/2; cols++)
746
+		if (cols*cols >= n)
747
+			break;
748
+	if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
749
+		cols = 2;
750
+	rows = n/cols;
751
+	cn = rn = 0; // reset column no, row no, client count
752
+
753
+	ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
754
+	cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
755
+	rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
756
+	crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
757
+	x = m->wx + ov;
758
+	y = m->wy + oh;
759
+
760
+	for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
761
+		if (i/rows + 1 > cols - n%cols) {
762
+			rows = n/cols + 1;
763
+			ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
764
+			rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
765
+		}
766
+		resize(c,
767
+			x,
768
+			y + rn*(ch + ih) + MIN(rn, rrest),
769
+			cw + (cn < crest ? 1 : 0) - 2*c->bw,
770
+			ch + (rn < rrest ? 1 : 0) - 2*c->bw,
771
+			0);
772
+		rn++;
773
+		if (rn >= rows) {
774
+			rn = 0;
775
+			x += cw + ih + (cn < crest ? 1 : 0);
776
+			cn++;
777
+		}
778
+	}
779
+}
780
+
781
+/*
782
+ * Gridmode layout + gaps
783
+ * https://dwm.suckless.org/patches/gridmode/
784
+ */
785
+void
786
+grid(Monitor *m)
787
+{
788
+	unsigned int i, n;
789
+	int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
790
+	int oh, ov, ih, iv;
791
+	Client *c;
792
+
793
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
794
+
795
+	/* grid dimensions */
796
+	for (rows = 0; rows <= n/2; rows++)
797
+		if (rows*rows >= n)
798
+			break;
799
+	cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
800
+
801
+	/* window geoms (cell height/width) */
802
+	ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
803
+	cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
804
+	chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
805
+	cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
806
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
807
+		cc = i / rows;
808
+		cr = i % rows;
809
+		cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
810
+		cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
811
+		resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
812
+	}
813
+}
814
+
815
+/*
816
+ * Horizontal grid layout + gaps
817
+ * https://dwm.suckless.org/patches/horizgrid/
818
+ */
819
+void
820
+horizgrid(Monitor *m) {
821
+	Client *c;
822
+	unsigned int n, i;
823
+	int oh, ov, ih, iv;
824
+	int mx = 0, my = 0, mh = 0, mw = 0;
825
+	int sx = 0, sy = 0, sh = 0, sw = 0;
826
+	int ntop, nbottom = 1;
827
+	float mfacts, sfacts;
828
+	int mrest, srest;
829
+
830
+	/* Count windows */
831
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
832
+	if (n == 0)
833
+		return;
834
+
835
+	if (n <= 2)
836
+		ntop = n;
837
+	else {
838
+		ntop = n / 2;
839
+		nbottom = n - ntop;
840
+	}
841
+	sx = mx = m->wx + ov;
842
+	sy = my = m->wy + oh;
843
+	sh = mh = m->wh - 2*oh;
844
+	sw = mw = m->ww - 2*ov;
845
+
846
+	if (n > ntop) {
847
+		sh = (mh - ih) / 2;
848
+		mh = mh - ih - sh;
849
+		sy = my + mh + ih;
850
+		mw = m->ww - 2*ov - iv * (ntop - 1);
851
+		sw = m->ww - 2*ov - iv * (nbottom - 1);
852
+	}
853
+
854
+	mfacts = ntop;
855
+	sfacts = nbottom;
856
+	mrest = mw - (mw / ntop) * ntop;
857
+	srest = sw - (sw / nbottom) * nbottom;
858
+
859
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
860
+		if (i < ntop) {
861
+			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
862
+			mx += WIDTH(c) + iv;
863
+		} else {
864
+			resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
865
+			sx += WIDTH(c) + iv;
866
+		}
867
+}
868
+
869
+/*
870
+ * nrowgrid layout + gaps
871
+ * https://dwm.suckless.org/patches/nrowgrid/
872
+ */
873
+void
874
+nrowgrid(Monitor *m)
875
+{
876
+	unsigned int n;
877
+	int ri = 0, ci = 0;  /* counters */
878
+	int oh, ov, ih, iv;                         /* vanitygap settings */
879
+	unsigned int cx, cy, cw, ch;                /* client geometry */
880
+	unsigned int uw = 0, uh = 0, uc = 0;        /* utilization trackers */
881
+	unsigned int cols, rows = m->nmaster + 1;
882
+	Client *c;
883
+
884
+	/* count clients */
885
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
886
+
887
+	/* nothing to do here */
888
+	if (n == 0)
889
+		return;
890
+
891
+	/* force 2 clients to always split vertically */
892
+	if (FORCE_VSPLIT && n == 2)
893
+		rows = 1;
894
+
895
+	/* never allow empty rows */
896
+	if (n < rows)
897
+		rows = n;
898
+
899
+	/* define first row */
900
+	cols = n / rows;
901
+	uc = cols;
902
+	cy = m->wy + oh;
903
+	ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
904
+	uh = ch;
905
+
906
+	for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
907
+		if (ci == cols) {
908
+			uw = 0;
909
+			ci = 0;
910
+			ri++;
911
+
912
+			/* next row */
913
+			cols = (n - uc) / (rows - ri);
914
+			uc += cols;
915
+			cy = m->wy + oh + uh + ih;
916
+			uh += ch + ih;
917
+		}
918
+
919
+		cx = m->wx + ov + uw;
920
+		cw = (m->ww - 2*ov - uw) / (cols - ci);
921
+		uw += cw + iv;
922
+
923
+		resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
924
+	}
925
+}
926
+
927
+/*
928
+ * Default tile layout + gaps
929
+ */
930
+static void
931
+tile(Monitor *m)
932
+{
933
+	unsigned int i, n;
934
+	int oh, ov, ih, iv;
935
+	int mx = 0, my = 0, mh = 0, mw = 0;
936
+	int sx = 0, sy = 0, sh = 0, sw = 0;
937
+	float mfacts, sfacts;
938
+	int mrest, srest;
939
+	Client *c;
940
+
941
+	getgaps(m, &oh, &ov, &ih, &iv, &n);
942
+	if (n == 0)
943
+		return;
944
+
945
+	sx = mx = m->wx + ov;
946
+	sy = my = m->wy + oh;
947
+	mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
948
+	sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
949
+	sw = mw = m->ww - 2*ov;
950
+
951
+	if (m->nmaster && n > m->nmaster) {
952
+		sw = (mw - iv) * (1 - m->mfact);
953
+		mw = mw - iv - sw;
954
+		sx = mx + mw + iv;
955
+	}
956
+
957
+	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
958
+
959
+	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
960
+		if (i < m->nmaster) {
961
+			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
962
+			my += HEIGHT(c) + ih;
963
+		} else {
964
+			resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
965
+			sy += HEIGHT(c) + ih;
966
+		}
967
+}
968
\ No newline at end of file
969
-- 
970
2.19.1