view layout.c @ 5:e060ab82b136

gapless grid
author paulo@thepaulopc
date Wed, 27 Jan 2010 23:28:29 -0800
parents faa4cb9d7bd6
children
line source
1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
2 * See LICENSE file for license details.
3 */
4 #include "dwm.h"
6 unsigned int master = MASTER;
7 unsigned int nmaster = NMASTER;
8 unsigned int blw = 0;
9 Layout *lt = NULL;
11 /* static */
13 static unsigned int nlayouts = 0;
15 static void
16 spiral(void) {
17 unsigned int i, n, nx, ny, nw, nh;
18 Client *c;
20 nx = wax;
21 ny = way + wah;
22 nw = waw;
23 nh = wah;
24 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
25 n++;
26 for(i = 0, c = clients; c; c = c->next)
27 if(isvisible(c)) {
28 if(c->isbanned)
29 XMoveWindow(dpy, c->win, c->x, c->y);
30 c->isbanned = False;
31 if(c->isversatile)
32 continue;
33 c->ismax = False;
34 if((i % 2 && nh / 2 > 2 * c->border)
35 || (!(i % 2) && nw / 2 > 2 * c->border))
36 {
37 if(i < n - 1) {
38 if(i % 2)
39 nh /= 2;
40 else
41 nw /= 2;
42 if((i % 4) == 2)
43 nx += nw;
44 else if((i % 4) == 3)
45 ny += nh;
46 }
47 if((i % 4) == 0)
48 ny -= nh;
49 else if((i % 4) == 1)
50 nx += nw;
51 else if((i % 4) == 2)
52 ny += nh;
53 else
54 nx -= nw;
55 i++;
56 }
57 resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
58 }
59 else {
60 c->isbanned = True;
61 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
62 }
63 if(!sel || !isvisible(sel)) {
64 for(c = stack; c && !isvisible(c); c = c->snext);
65 focus(c);
66 }
67 restack();
68 }
70 static void
71 spiral_h(void) {
72 unsigned int i, n, nx, ny, nw, nh;
73 Client *c;
75 nx = wax + waw;
76 ny = way;
77 nw = waw;
78 nh = wah;
79 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
80 n++;
81 for(i = 0, c = clients; c; c = c->next)
82 if(isvisible(c)) {
83 if(c->isbanned)
84 XMoveWindow(dpy, c->win, c->x, c->y);
85 c->isbanned = False;
86 if(c->isversatile)
87 continue;
88 c->ismax = False;
89 if((i % 2 && nw / 2 > 2 * c->border)
90 || (!(i % 2) && nh / 2 > 2 * c->border))
91 {
92 if(i < n - 1) {
93 if(i % 2)
94 nw /= 2;
95 else
96 nh /= 2;
97 if((i % 4) == 2)
98 ny += nh;
99 else if((i % 4) == 3)
100 nx += nw;
101 }
102 if((i % 4) == 0)
103 nx -= nw;
104 else if((i % 4) == 1)
105 ny += nh;
106 else if((i % 4) == 2)
107 nx += nw;
108 else
109 ny -= nh;
110 i++;
111 }
112 resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
113 }
114 else {
115 c->isbanned = True;
116 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
117 }
118 if(!sel || !isvisible(sel)) {
119 for(c = stack; c && !isvisible(c); c = c->snext);
120 focus(c);
121 }
122 restack();
123 }
125 static void
126 monocle(void) {
127 Client *c;
129 for(c = clients; c; c = c->next)
130 if(isvisible(c) && c->isbanned) {
131 XMoveWindow(dpy, c->win, c->x, c->y);
132 c->isbanned = False;
133 }
134 else if(!isvisible(c)) {
135 c->isbanned = True;
136 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
137 }
139 for(c = nexttiled(clients); c; c = nexttiled(c->next))
140 resize(c, wax, way, waw - 2*c->border, wah - 2*c->border, False);
142 restack();
143 }
145 static void
146 cascade(void) {
147 unsigned int i, n, px = 20;
148 Client *c;
150 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
152 for(i = 0, c = clients; c; c = c->next)
153 if(isvisible(c)) {
154 if(c->isbanned) {
155 XMoveWindow(dpy, c->win, c->x, c->y);
156 c->isbanned = False;
157 }
158 if(!c->isversatile) {
159 resize(c, wax+(px*i), way+(px*i), waw-(px*(n-1))-2*c->border, wah-(px*(n-1))-2*c->border, True);
160 i++;
161 }
162 }
163 else if(!isvisible(c)) {
164 c->isbanned = True;
165 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
166 }
168 restack();
169 }
171 static void
172 bstack(void) {
173 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
174 Client *c;
176 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
177 n++;
178 /* window geoms */
179 mh = (n > nmaster) ? (wah * master) / 1000 : wah;
180 mw = (n > nmaster) ? waw / nmaster : waw / (n > 0 ? n : 1);
181 th = wah - mh;
182 tw = (n > nmaster) ? waw / (n - nmaster) : 0;
184 for(i = 0, c = clients; c; c = c->next)
185 if(isvisible(c)) {
186 if(c->isbanned)
187 XMoveWindow(dpy, c->win, c->x, c->y);
188 c->isbanned = False;
189 if(c->isversatile)
190 continue;
191 c->ismax = False;
192 nx = wax;
193 ny = way;
194 if(i < nmaster) {
195 nx += i * mw;
196 nw = mw - 2 * BORDERPX;
197 nh = mh - 2 * BORDERPX;
198 }
199 else { /* tile window */
200 ny += mh;
201 nh = th - 2 * BORDERPX;
202 if(tw > 2 * BORDERPX) {
203 nx += (i - nmaster) * tw;
204 nw = tw - 2 * BORDERPX;
205 }
206 else /* fallback if th <= 2 * BORDERPX */
207 nw = waw - 2 * BORDERPX;
208 }
209 resize(c, nx, ny, nw, nh, False);
210 i++;
211 }
212 else {
213 c->isbanned = True;
214 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
215 }
216 if(!sel || !isvisible(sel)) {
217 for(c = stack; c && !isvisible(c); c = c->snext);
218 focus(c);
219 }
220 restack();
221 }
223 static void
224 grid(void) {
225 unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
226 Client *c;
228 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
229 n++;
230 if(n == 0)
231 return;
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;
241 /* window geometries */
242 cw = cols ? waw / cols : waw;
243 cn = 0; /* current column number */
244 rn = 0; /* current row number */
245 for(i = 0, c = clients; c; c = c->next)
246 if(isvisible(c)) {
247 if(i/rows + 1 > cols - n%cols)
248 rows = n/cols + 1;
249 ch = rows ? wah / rows : wah;
250 cx = cn*cw;
251 cy = (TOPBAR ? dc.h : 0) + rn*ch;
252 resize(c, cx, cy, cw - 2 * BORDERPX, ch - 2 * BORDERPX, False);
253 rn++;
254 if(rn >= rows) {
255 rn = 0;
256 cn++;
257 }
258 i++;
259 }
260 else {
261 c->isbanned = True;
262 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
263 }
265 if(!sel || !isvisible(sel)) {
266 for(c = stack; c && !isvisible(c); c = c->snext);
267 focus(c);
268 }
269 restack();
270 }
272 static void
273 tile(void) {
274 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
275 Client *c;
277 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
278 n++;
279 /* window geoms */
280 mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
281 mw = (n > nmaster) ? (waw * master) / 1000 : waw;
282 th = (n > nmaster) ? wah / (n - nmaster) : 0;
283 tw = waw - mw;
285 for(i = 0, c = clients; c; c = c->next)
286 if(isvisible(c)) {
287 if(c->isbanned)
288 XMoveWindow(dpy, c->win, c->x, c->y);
289 c->isbanned = False;
290 if(c->isversatile)
291 continue;
292 c->ismax = False;
293 nx = wax;
294 ny = way;
295 if(i < nmaster) {
296 ny += i * mh;
297 nw = mw - 2 * BORDERPX;
298 nh = mh - 2 * BORDERPX;
299 }
300 else { /* tile window */
301 nx += mw;
302 nw = tw - 2 * BORDERPX;
303 if(th > 2 * BORDERPX) {
304 ny += (i - nmaster) * th;
305 nh = th - 2 * BORDERPX;
306 }
307 else /* fallback if th <= 2 * BORDERPX */
308 nh = wah - 2 * BORDERPX;
309 }
310 resize(c, nx, ny, nw, nh, False);
311 i++;
312 }
313 else {
314 c->isbanned = True;
315 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
316 }
317 if(!sel || !isvisible(sel)) {
318 for(c = stack; c && !isvisible(c); c = c->snext);
319 focus(c);
320 }
321 restack();
322 }
324 LAYOUTS
326 /* extern */
328 void
329 focusnext(Arg *arg) {
330 Client *c;
332 if(!sel)
333 return;
334 for(c = sel->next; c && !isvisible(c); c = c->next);
335 if(!c)
336 for(c = clients; c && !isvisible(c); c = c->next);
337 if(c) {
338 focus(c);
339 restack();
340 }
341 }
343 void
344 focusprev(Arg *arg) {
345 Client *c;
347 if(!sel)
348 return;
349 for(c = sel->prev; c && !isvisible(c); c = c->prev);
350 if(!c) {
351 for(c = clients; c && c->next; c = c->next);
352 for(; c && !isvisible(c); c = c->prev);
353 }
354 if(c) {
355 focus(c);
356 restack();
357 }
358 }
360 void
361 incnmaster(Arg *arg) {
362 //if((lt->arrange != tile) || (nmaster + arg->i < 1)
363 //|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
364 // return;
365 if(nmaster + arg->i < 1 && nmaster + arg->i <= MAX_TASKS)
366 return;
367 nmaster += arg->i;
368 if(sel)
369 lt->arrange();
370 else
371 drawstatus();
372 }
374 void
375 initlayouts(void) {
376 unsigned int i, w;
378 lt = &layout[0];
379 nlayouts = sizeof layout / sizeof layout[0];
380 for(blw = i = 0; i < nlayouts; i++) {
381 w = textw(layout[i].symbol);
382 if(w > blw)
383 blw = w;
384 }
385 }
387 Client *
388 nexttiled(Client *c) {
389 for(; c && (c->isversatile || !isvisible(c)); c = c->next);
390 return c;
391 }
393 void
394 resizemaster(Arg *arg) {
395 //if(lt->arrange != tile)
396 // return;
397 if(arg->i == 0)
398 master = MASTER;
399 else {
400 //if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
401 //|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
402 // return;
403 master += arg->i;
404 }
405 lt->arrange();
406 }
408 void
409 restack(void) {
410 Client *c;
411 XEvent ev;
413 drawstatus();
414 if(!sel)
415 return;
416 if(sel->isversatile || lt->arrange == versatile)
417 XRaiseWindow(dpy, sel->win);
418 if(lt->arrange != versatile) {
419 if(!sel->isversatile)
420 XLowerWindow(dpy, sel->win);
421 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
422 if(c == sel)
423 continue;
424 XLowerWindow(dpy, c->win);
425 }
426 }
427 XSync(dpy, False);
428 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
429 }
431 void
432 setlayout(Arg *arg) {
433 int i;
435 if(arg->i < 0) {
436 for(i = 0; i < nlayouts && lt != &layout[i]; i++);
437 if(arg->i == -1)
438 lt = &layout[(i + 1) % nlayouts];
439 else if(arg->i == -2)
440 lt = &layout[(i - 1) >= 0 ? i - 1 : nlayouts - 1];
441 }
442 else {
443 if(arg->i < 0 || arg->i >= nlayouts)
444 return;
445 lt = &layout[arg->i];
446 }
447 if(sel)
448 lt->arrange();
449 else
450 drawstatus();
451 }
453 void
454 versatile(void) {
455 Client *c;
457 for(c = clients; c; c = c->next) {
458 if(isvisible(c)) {
459 if(c->isbanned)
460 XMoveWindow(dpy, c->win, c->x, c->y);
461 c->isbanned = False;
462 resize(c, c->x, c->y, c->w, c->h, True);
463 }
464 else {
465 c->isbanned = True;
466 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
467 }
468 }
469 if(!sel || !isvisible(sel)) {
470 for(c = stack; c && !isvisible(c); c = c->snext);
471 focus(c);
472 }
473 restack();
474 }