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