JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
code polishing, removed unnecessary newlines
[dwm.git] / view.c
1 /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
2  * See LICENSE file for license details.
3  */
4 #include "dwm.h"
5
6 /* static */
7
8 static Client *
9 minclient(void) {
10         Client *c, *min;
11
12         if((clients && clients->isfloat) || arrange == dofloat)
13                 return clients; /* don't touch floating order */
14         for(min = c = clients; c; c = c->next)
15                 if(c->weight < min->weight)
16                         min = c;
17         return min;
18 }
19
20 static Client *
21 nexttiled(Client *c) {
22         for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
23         return c;
24 }
25
26 static void
27 reorder(void) {
28         Client *c, *newclients, *tail;
29
30         newclients = tail = NULL;
31         while((c = minclient())) {
32                 detach(c);
33                 if(tail) {
34                         c->prev = tail;
35                         tail->next = c;
36                         tail = c;
37                 }
38                 else
39                         tail = newclients = c;
40         }
41         clients = newclients;
42 }
43
44 static void
45 togglemax(Client *c) {
46         XEvent ev;
47
48         if((c->ismax = !c->ismax)) {
49                 c->rx = c->x; c->x = sx;
50                 c->ry = c->y; c->y = bh;
51                 c->rw = c->w; c->w = sw - 2 * BORDERPX;
52                 c->rh = c->h; c->h = sh - bh - 2 * BORDERPX;
53         }
54         else {
55                 c->x = c->rx;
56                 c->y = c->ry;
57                 c->w = c->rw;
58                 c->h = c->rh;
59         }
60         resize(c, True, TopLeft);
61         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
62 }
63
64 /* extern */
65
66 void (*arrange)(Arg *) = DEFMODE;
67
68 void
69 detach(Client *c) {
70         if(c->prev)
71                 c->prev->next = c->next;
72         if(c->next)
73                 c->next->prev = c->prev;
74         if(c == clients)
75                 clients = c->next;
76         c->next = c->prev = NULL;
77 }
78
79 void
80 dofloat(Arg *arg) {
81         Client *c;
82
83         for(c = clients; c; c = c->next) {
84                 if(isvisible(c)) {
85                         resize(c, True, TopLeft);
86                 }
87                 else
88                         ban(c);
89         }
90         if(!sel || !isvisible(sel)) {
91                 for(c = stack; c && !isvisible(c); c = c->snext);
92                 focus(c);
93         }
94         restack();
95 }
96
97 void
98 dotile(Arg *arg) {
99         unsigned int i, n, mpx, stackw, stackh, th;
100         Client *c;
101
102         for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
103                 n++;
104         mpx = (sw * master) / 1000;
105         stackw = sw - mpx;
106         stackh = sh - bh;
107         th = stackh;
108         if(n > 1)
109                 th /= (n - 1);
110
111         for(i = 0, c = clients; c; c = c->next, i++)
112                 if(isvisible(c)) {
113                         if(c->isfloat) {
114                                 resize(c, True, TopLeft);
115                                 continue;
116                         }
117                         c->ismax = False;
118                         c->x = sx;
119                         c->y = sy + bh;
120                         if(n == 1) { /* only 1 window */
121                                 c->w = sw - 2 * BORDERPX;
122                                 c->h = sh - 2 * BORDERPX - bh;
123                         }
124                         else if(i == 0) { /* master window */
125                                 c->w = mpx - 2 * BORDERPX;
126                                 c->h = sh - bh - 2 * BORDERPX;
127                         }
128                         else {  /* tile window */
129                                 c->x += mpx;
130                                 c->w = stackw - 2 * BORDERPX;
131                                 if(th > bh) {
132                                         c->y = sy + (i - 1) * th + bh;
133                                         if(i + 1 == n)
134                                                 c->h = sh - c->y - 2 * BORDERPX;
135                                         else
136                                                 c->h = th - 2 * BORDERPX;
137                                 }
138                                 else /* fallback if th < bh */
139                                         c->h = stackh - 2 * BORDERPX;
140                         }
141                         resize(c, False, TopLeft);
142                 }
143                 else
144                         ban(c);
145
146         if(!sel || !isvisible(sel)) {
147                 for(c = stack; c && !isvisible(c); c = c->snext);
148                 focus(c);
149         }
150         restack();
151 }
152
153 void
154 focusnext(Arg *arg) {
155         Client *c;
156    
157         if(!sel)
158                 return;
159         if(!(c = getnext(sel->next)))
160                 c = getnext(clients);
161         if(c) {
162                 focus(c);
163                 restack();
164         }
165 }
166
167 void
168 focusprev(Arg *arg) {
169         Client *c;
170
171         if(!sel)
172                 return;
173         if(!(c = getprev(sel->prev))) {
174                 for(c = clients; c && c->next; c = c->next);
175                 c = getprev(c);
176         }
177         if(c) {
178                 focus(c);
179                 restack();
180         }
181 }
182
183 Bool
184 isvisible(Client *c) {
185         unsigned int i;
186
187         for(i = 0; i < ntags; i++)
188                 if(c->tags[i] && seltag[i])
189                         return True;
190         return False;
191 }
192
193 void
194 resizecol(Arg *arg) {
195         unsigned int n;
196         Client *c;
197
198         for(n = 0, c = clients; c; c = c->next)
199                 if(isvisible(c) && !c->isfloat)
200                         n++;
201         if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
202                 return;
203         if(sel == getnext(clients)) {
204                 if(master + arg->i > 950 || master + arg->i < 50)
205                         return;
206                 master += arg->i;
207         }
208         else {
209                 if(master - arg->i > 950 || master - arg->i < 50)
210                         return;
211                 master -= arg->i;
212         }
213         arrange(NULL);
214 }
215
216 void
217 restack(void) {
218         Client *c;
219         XEvent ev;
220
221         if(!sel) {
222                 drawstatus();
223                 return;
224         }
225         if(sel->isfloat || arrange == dofloat) {
226                 XRaiseWindow(dpy, sel->win);
227                 XRaiseWindow(dpy, sel->twin);
228         }
229         if(arrange != dofloat) {
230                 if(!sel->isfloat) {
231                         XLowerWindow(dpy, sel->twin);
232                         XLowerWindow(dpy, sel->win);
233                 }
234                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
235                         if(c == sel)
236                                 continue;
237                         XLowerWindow(dpy, c->twin);
238                         XLowerWindow(dpy, c->win);
239                 }
240         }
241         drawall();
242         XSync(dpy, False);
243         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
244 }
245
246 void
247 togglemode(Arg *arg) {
248         arrange = (arrange == dofloat) ? dotile : dofloat;
249         if(sel)
250                 arrange(NULL);
251         else
252                 drawstatus();
253 }
254
255 void
256 toggleview(Arg *arg) {
257         unsigned int i;
258
259         seltag[arg->i] = !seltag[arg->i];
260         for(i = 0; i < ntags && !seltag[i]; i++);
261         if(i == ntags)
262                 seltag[arg->i] = True; /* cannot toggle last view */
263         reorder();
264         arrange(NULL);
265 }
266
267 void
268 view(Arg *arg) {
269         unsigned int i;
270
271         for(i = 0; i < ntags; i++)
272                 seltag[i] = False;
273         seltag[arg->i] = True;
274         reorder();
275         arrange(NULL);
276 }
277
278 void
279 viewall(Arg *arg) {
280         unsigned int i;
281
282         for(i = 0; i < ntags; i++)
283                 seltag[i] = True;
284         reorder();
285         arrange(NULL);
286 }
287
288 void
289 zoom(Arg *arg) {
290         unsigned int n;
291         Client *c;
292
293         if(!sel)
294                 return;
295         if(sel->isfloat || (arrange == dofloat)) {
296                 togglemax(sel);
297                 return;
298         }
299         for(n = 0, c = clients; c; c = c->next)
300                 if(isvisible(c) && !c->isfloat)
301                         n++;
302         if(n < 2 || (arrange == dofloat))
303                 return;
304         if((c = sel) == nexttiled(clients))
305                 if(!(c = nexttiled(c->next)))
306                         return;
307         detach(c);
308         if(clients)
309                 clients->prev = c;
310         c->next = clients;
311         clients = c;
312         focus(c);
313         arrange(NULL);
314 }