JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
replaced Arg union with const char *arg, seems cleaner to me, even if we need atoi...
[dwm.git] / layout.c
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"
5
6 unsigned int blw = 0;
7 Layout *lt = NULL;
8
9 /* static */
10
11 static unsigned int nlayouts = 0;
12 static unsigned int masterw = MASTERWIDTH;
13 static unsigned int nmaster = NMASTER;
14
15 static void
16 tile(void) {
17         unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
18         Client *c;
19
20         for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
21                 n++;
22         /* window geoms */
23         mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
24         mw = (n > nmaster) ? (waw * masterw) / 1000 : waw;
25         th = (n > nmaster) ? wah / (n - nmaster) : 0;
26         tw = waw - mw;
27
28         for(i = 0, c = clients; c; c = c->next)
29                 if(isvisible(c)) {
30                         if(c->isbanned)
31                                 XMoveWindow(dpy, c->win, c->x, c->y);
32                         c->isbanned = False;
33                         if(c->isversatile)
34                                 continue;
35                         c->ismax = False;
36                         nx = wax;
37                         ny = way;
38                         if(i < nmaster) {
39                                 ny += i * mh;
40                                 nw = mw - 2 * BORDERPX;
41                                 nh = mh - 2 * BORDERPX;
42                         }
43                         else {  /* tile window */
44                                 nx += mw;
45                                 nw = tw - 2 * BORDERPX;
46                                 if(th > 2 * BORDERPX) {
47                                         ny += (i - nmaster) * th;
48                                         nh = th - 2 * BORDERPX;
49                                 }
50                                 else /* fallback if th <= 2 * BORDERPX */
51                                         nh = wah - 2 * BORDERPX;
52                         }
53                         resize(c, nx, ny, nw, nh, False);
54                         i++;
55                 }
56                 else {
57                         c->isbanned = True;
58                         XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
59                 }
60         if(!sel || !isvisible(sel)) {
61                 for(c = stack; c && !isvisible(c); c = c->snext);
62                 focus(c);
63         }
64         restack();
65 }
66
67 LAYOUTS
68
69 /* extern */
70
71 void
72 focusnext(const char *arg) {
73         Client *c;
74    
75         if(!sel)
76                 return;
77         for(c = sel->next; c && !isvisible(c); c = c->next);
78         if(!c)
79                 for(c = clients; c && !isvisible(c); c = c->next);
80         if(c) {
81                 focus(c);
82                 restack();
83         }
84 }
85
86 void
87 focusprev(const char *arg) {
88         Client *c;
89
90         if(!sel)
91                 return;
92         for(c = sel->prev; c && !isvisible(c); c = c->prev);
93         if(!c) {
94                 for(c = clients; c && c->next; c = c->next);
95                 for(; c && !isvisible(c); c = c->prev);
96         }
97         if(c) {
98                 focus(c);
99                 restack();
100         }
101 }
102
103 void
104 incmasterw(const char *arg) {
105         int i;
106         if(lt->arrange != tile)
107                 return;
108         if(!arg)
109                 masterw = MASTERWIDTH;
110         else {
111                 i = atoi(arg);
112                 if(waw * (masterw + i) / 1000 >= waw - 2 * BORDERPX
113                 || waw * (masterw + i) / 1000 <= 2 * BORDERPX)
114                         return;
115                 masterw += i;
116         }
117         lt->arrange();
118 }
119
120 void
121 incnmaster(const char *arg) {
122         int i = arg ? atoi(arg) : 0;
123         if((lt->arrange != tile) || (nmaster + i < 1)
124         || (wah / (nmaster + i) <= 2 * BORDERPX))
125                 return;
126         nmaster += i;
127         if(sel)
128                 lt->arrange();
129         else
130                 drawstatus();
131 }
132
133 void
134 initlayouts(void) {
135         unsigned int i, w;
136
137         lt = &layout[0];
138         nlayouts = sizeof layout / sizeof layout[0];
139         for(blw = i = 0; i < nlayouts; i++) {
140                 w = textw(layout[i].symbol);
141                 if(w > blw)
142                         blw = w;
143         }
144 }
145
146 Client *
147 nexttiled(Client *c) {
148         for(; c && (c->isversatile || !isvisible(c)); c = c->next);
149         return c;
150 }
151
152 void
153 restack(void) {
154         Client *c;
155         XEvent ev;
156
157         drawstatus();
158         if(!sel)
159                 return;
160         if(sel->isversatile || lt->arrange == versatile)
161                 XRaiseWindow(dpy, sel->win);
162         if(lt->arrange != versatile) {
163                 if(!sel->isversatile)
164                         XLowerWindow(dpy, sel->win);
165                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
166                         if(c == sel)
167                                 continue;
168                         XLowerWindow(dpy, c->win);
169                 }
170         }
171         XSync(dpy, False);
172         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
173 }
174
175 void
176 setlayout(const char *arg) {
177         unsigned int i;
178
179         if(!arg) {
180                 for(i = 0; i < nlayouts && lt != &layout[i]; i++);
181                 if(i == nlayouts - 1)
182                         lt = &layout[0];
183                 else
184                         lt = &layout[++i];
185         }
186         else {
187                 i = atoi(arg);
188                 if(i < 0 || i >= nlayouts)
189                         return;
190                 lt = &layout[i];
191         }
192         if(sel)
193                 lt->arrange();
194         else
195                 drawstatus();
196 }
197
198 void
199 togglemax(const char *arg) {
200         XEvent ev;
201
202         if(!sel || (lt->arrange != versatile && !sel->isversatile) || sel->isfixed)
203                 return;
204         if((sel->ismax = !sel->ismax)) {
205                 sel->rx = sel->x;
206                 sel->ry = sel->y;
207                 sel->rw = sel->w;
208                 sel->rh = sel->h;
209                 resize(sel, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True);
210         }
211         else
212                 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
213         drawstatus();
214         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
215 }
216
217 void
218 versatile(void) {
219         Client *c;
220
221         for(c = clients; c; c = c->next) {
222                 if(isvisible(c)) {
223                         if(c->isbanned)
224                                 XMoveWindow(dpy, c->win, c->x, c->y);
225                         c->isbanned = False;
226                         resize(c, c->x, c->y, c->w, c->h, True);
227                 }
228                 else {
229                         c->isbanned = True;
230                         XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
231                 }
232         }
233         if(!sel || !isvisible(sel)) {
234                 for(c = stack; c && !isvisible(c); c = c->snext);
235                 focus(c);
236         }
237         restack();
238 }
239
240 void
241 zoom(const char *arg) {
242         unsigned int n;
243         Client *c;
244
245         if(!sel || lt->arrange != tile || sel->isversatile)
246                 return;
247         for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
248                 n++;
249         if((c = sel) == nexttiled(clients))
250                 if(!(c = nexttiled(c->next)))
251                         return;
252         detach(c);
253         attach(c);
254         focus(c);
255         lt->arrange();
256 }