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