dwm

dwm

https://git.tonybtw.com/dwm.git git://git.tonybtw.com/dwm.git
7,970 bytes raw
1
/* Key binding functions */
2
static void defaultgaps(const Arg *arg);
3
static void incrgaps(const Arg *arg);
4
static void togglegaps(const Arg *arg);
5
/* Layouts (delete the ones you do not need) */
6
static void dwindle(Monitor *m);
7
static void fibonacci(Monitor *m, int s);
8
static void spiral(Monitor *m);
9
static void tile(Monitor *m);
10
/* Internals */
11
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
12
static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
13
static void setgaps(int oh, int ov, int ih, int iv);
14
15
/* Settings */
16
#if !PERTAG_PATCH
17
static int enablegaps = 1;
18
#endif // PERTAG_PATCH
19
20
void
21
setgaps(int oh, int ov, int ih, int iv)
22
{
23
	if (oh < 0) oh = 0;
24
	if (ov < 0) ov = 0;
25
	if (ih < 0) ih = 0;
26
	if (iv < 0) iv = 0;
27
28
	selmon->gappoh = oh;
29
	selmon->gappov = ov;
30
	selmon->gappih = ih;
31
	selmon->gappiv = iv;
32
	arrange(selmon);
33
}
34
35
void
36
togglegaps(const Arg *arg)
37
{
38
	#if PERTAG_PATCH
39
	selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
40
	#else
41
	enablegaps = !enablegaps;
42
	#endif // PERTAG_PATCH
43
	arrange(NULL);
44
}
45
46
void
47
defaultgaps(const Arg *arg)
48
{
49
	setgaps(gappoh, gappov, gappih, gappiv);
50
}
51
52
void
53
incrgaps(const Arg *arg)
54
{
55
	setgaps(
56
		selmon->gappoh + arg->i,
57
		selmon->gappov + arg->i,
58
		selmon->gappih + arg->i,
59
		selmon->gappiv + arg->i
60
	);
61
}
62
63
void
64
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
65
{
66
	unsigned int n, oe, ie;
67
	#if PERTAG_PATCH
68
	oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
69
	#else
70
	oe = ie = enablegaps;
71
	#endif // PERTAG_PATCH
72
	Client *c;
73
74
	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
75
	if (smartgaps && n == 1) {
76
		oe = 0; // outer gaps disabled when only one client
77
	}
78
79
	*oh = m->gappoh*oe; // outer horizontal gap
80
	*ov = m->gappov*oe; // outer vertical gap
81
	*ih = m->gappih*ie; // inner horizontal gap
82
	*iv = m->gappiv*ie; // inner vertical gap
83
	*nc = n;            // number of clients
84
}
85
86
void
87
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
88
{
89
	unsigned int n;
90
	float mfacts, sfacts;
91
	int mtotal = 0, stotal = 0;
92
	Client *c;
93
94
	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
95
	mfacts = MIN(n, m->nmaster);
96
	sfacts = n - m->nmaster;
97
98
	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
99
		if (n < m->nmaster)
100
			mtotal += msize / mfacts;
101
		else
102
			stotal += ssize / sfacts;
103
104
	*mf = mfacts; // total factor of master area
105
	*sf = sfacts; // total factor of stack area
106
	*mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
107
	*sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
108
}
109
110
/***
111
 * Layouts
112
 */
113
114
/*
115
 * Fibonacci layout + gaps
116
 * https://dwm.suckless.org/patches/fibonacci/
117
 */
118
void
119
fibonacci(Monitor *m, int s)
120
{
121
	unsigned int i, n;
122
	int nx, ny, nw, nh;
123
	int oh, ov, ih, iv;
124
	int nv, hrest = 0, wrest = 0, r = 1;
125
	Client *c;
126
127
	getgaps(m, &oh, &ov, &ih, &iv, &n);
128
	if (n == 0)
129
		return;
130
131
	nx = m->wx + ov;
132
	ny = m->wy + oh;
133
	nw = m->ww - 2*ov;
134
	nh = m->wh - 2*oh;
135
136
	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
137
		if (r) {
138
			if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
139
			   || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
140
				r = 0;
141
			}
142
			if (r && i < n - 1) {
143
				if (i % 2) {
144
					nv = (nh - ih) / 2;
145
					hrest = nh - 2*nv - ih;
146
					nh = nv;
147
				} else {
148
					nv = (nw - iv) / 2;
149
					wrest = nw - 2*nv - iv;
150
					nw = nv;
151
				}
152
153
				if ((i % 4) == 2 && !s)
154
					nx += nw + iv;
155
				else if ((i % 4) == 3 && !s)
156
					ny += nh + ih;
157
			}
158
159
			if ((i % 4) == 0) {
160
				if (s) {
161
					ny += nh + ih;
162
					nh += hrest;
163
				}
164
				else {
165
					nh -= hrest;
166
					ny -= nh + ih;
167
				}
168
			}
169
			else if ((i % 4) == 1) {
170
				nx += nw + iv;
171
				nw += wrest;
172
			}
173
			else if ((i % 4) == 2) {
174
				ny += nh + ih;
175
				nh += hrest;
176
				if (i < n - 1)
177
					nw += wrest;
178
			}
179
			else if ((i % 4) == 3) {
180
				if (s) {
181
					nx += nw + iv;
182
					nw -= wrest;
183
				} else {
184
					nw -= wrest;
185
					nx -= nw + iv;
186
					nh += hrest;
187
				}
188
			}
189
			if (i == 0)	{
190
				if (n != 1) {
191
					nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
192
					wrest = 0;
193
				}
194
				ny = m->wy + oh;
195
			}
196
			else if (i == 1)
197
				nw = m->ww - nw - iv - 2*ov;
198
			i++;
199
		}
200
201
		resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
202
	}
203
}
204
205
void
206
dwindle(Monitor *m)
207
{
208
	fibonacci(m, 1);
209
}
210
211
void
212
spiral(Monitor *m)
213
{
214
	fibonacci(m, 0);
215
}
216
217
/*
218
 * Gappless grid layout + gaps (ironically)
219
 * https://dwm.suckless.org/patches/gaplessgrid/
220
 */
221
void
222
gaplessgrid(Monitor *m)
223
{
224
	unsigned int i, n;
225
	int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
226
	int oh, ov, ih, iv;
227
	Client *c;
228
229
	getgaps(m, &oh, &ov, &ih, &iv, &n);
230
	if (n == 0)
231
		return;
232
233
	/* grid dimensions */
234
	for (cols = 0; cols <= n/2; cols++)
235
		if (cols*cols >= n)
236
			break;
237
	if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
238
		cols = 2;
239
	rows = n/cols;
240
	cn = rn = 0; // reset column no, row no, client count
241
242
	ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
243
	cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
244
	rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
245
	crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
246
	x = m->wx + ov;
247
	y = m->wy + oh;
248
249
	for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
250
		if (i/rows + 1 > cols - n%cols) {
251
			rows = n/cols + 1;
252
			ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
253
			rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
254
		}
255
		resize(c,
256
			x,
257
			y + rn*(ch + ih) + MIN(rn, rrest),
258
			cw + (cn < crest ? 1 : 0) - 2*c->bw,
259
			ch + (rn < rrest ? 1 : 0) - 2*c->bw,
260
			0);
261
		rn++;
262
		if (rn >= rows) {
263
			rn = 0;
264
			x += cw + ih + (cn < crest ? 1 : 0);
265
			cn++;
266
		}
267
	}
268
}
269
270
/*
271
 * Horizontal grid layout + gaps
272
 * https://dwm.suckless.org/patches/horizgrid/
273
 */
274
void
275
horizgrid(Monitor *m) {
276
	Client *c;
277
	unsigned int n, i;
278
	int oh, ov, ih, iv;
279
	int mx = 0, my = 0, mh = 0, mw = 0;
280
	int sx = 0, sy = 0, sh = 0, sw = 0;
281
	int ntop, nbottom = 1;
282
	float mfacts, sfacts;
283
	int mrest, srest;
284
285
	/* Count windows */
286
	getgaps(m, &oh, &ov, &ih, &iv, &n);
287
	if (n == 0)
288
		return;
289
290
	if (n <= 2)
291
		ntop = n;
292
	else {
293
		ntop = n / 2;
294
		nbottom = n - ntop;
295
	}
296
	sx = mx = m->wx + ov;
297
	sy = my = m->wy + oh;
298
	sh = mh = m->wh - 2*oh;
299
	sw = mw = m->ww - 2*ov;
300
301
	if (n > ntop) {
302
		sh = (mh - ih) / 2;
303
		mh = mh - ih - sh;
304
		sy = my + mh + ih;
305
		mw = m->ww - 2*ov - iv * (ntop - 1);
306
		sw = m->ww - 2*ov - iv * (nbottom - 1);
307
	}
308
309
	mfacts = ntop;
310
	sfacts = nbottom;
311
	mrest = mw - (mw / ntop) * ntop;
312
	srest = sw - (sw / nbottom) * nbottom;
313
314
	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
315
		if (i < ntop) {
316
			resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
317
			mx += WIDTH(c) + iv;
318
		} else {
319
			resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
320
			sx += WIDTH(c) + iv;
321
		}
322
}
323
324
/*
325
 * Default tile layout + gaps
326
 */
327
static void
328
tile(Monitor *m)
329
{
330
	unsigned int i, n;
331
	int oh, ov, ih, iv;
332
	int mx = 0, my = 0, mh = 0, mw = 0;
333
	int sx = 0, sy = 0, sh = 0, sw = 0;
334
	float mfacts, sfacts;
335
	int mrest, srest;
336
	Client *c;
337
338
	getgaps(m, &oh, &ov, &ih, &iv, &n);
339
	if (n == 0)
340
		return;
341
342
	sx = mx = m->wx + ov;
343
	sy = my = m->wy + oh;
344
	mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
345
	sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
346
	sw = mw = m->ww - 2*ov;
347
348
	if (m->nmaster && n > m->nmaster) {
349
		sw = (mw - iv) * (1 - m->mfact);
350
		mw = mw - iv - sw;
351
		sx = mx + mw + iv;
352
	}
353
354
	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
355
356
	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
357
		if (i < m->nmaster) {
358
			resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
359
			my += HEIGHT(c) + ih;
360
		} else {
361
			resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
362
			sy += HEIGHT(c) + ih;
363
		}
364
}