JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
applied sanders max size fix
[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 (x->maxw && x->minw && x->maxh && x->minh &&
49                         x->maxw == x->minw && x->maxh == x->minh)
50                 return;
51
52         if((c->ismax = !c->ismax)) {
53                 c->rx = c->x; c->x = sx;
54                 c->ry = c->y; c->y = bh;
55                 c->rw = c->w; c->w = sw - 2 * BORDERPX;
56                 c->rh = c->h; c->h = sh - bh - 2 * BORDERPX;
57         }
58         else {
59                 c->x = c->rx;
60                 c->y = c->ry;
61                 c->w = c->rw;
62                 c->h = c->rh;
63         }
64         resize(c, True, TopLeft);
65         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
66 }
67
68 /* extern */
69
70 void (*arrange)(void) = DEFMODE;
71
72 void
73 detach(Client *c) {
74         if(c->prev)
75                 c->prev->next = c->next;
76         if(c->next)
77                 c->next->prev = c->prev;
78         if(c == clients)
79                 clients = c->next;
80         c->next = c->prev = NULL;
81 }
82
83 void
84 dofloat(void) {
85         Client *c;
86
87         for(c = clients; c; c = c->next) {
88                 if(isvisible(c)) {
89                         resize(c, True, TopLeft);
90                 }
91                 else
92                         ban(c);
93         }
94         if(!sel || !isvisible(sel)) {
95                 for(c = stack; c && !isvisible(c); c = c->snext);
96                 focus(c);
97         }
98         restack();
99 }
100
101 void
102 dotile(void) {
103         unsigned int i, n, mpx, stackw, stackh, th;
104         Client *c;
105
106         for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
107                 n++;
108         mpx = (sw * master) / 1000;
109         stackw = sw - mpx;
110         stackh = sh - bh;
111         th = stackh;
112         if(n > 1)
113                 th /= (n - 1);
114
115         for(i = 0, c = clients; c; c = c->next)
116                 if(isvisible(c)) {
117                         if(c->isfloat) {
118                                 resize(c, True, TopLeft);
119                                 continue;
120                         }
121                         c->ismax = False;
122                         c->x = sx;
123                         c->y = sy + bh;
124                         if(n == 1) { /* only 1 window */
125                                 c->w = sw - 2 * BORDERPX;
126                                 c->h = sh - 2 * BORDERPX - bh;
127                         }
128                         else if(i == 0) { /* master window */
129                                 c->w = mpx - 2 * BORDERPX;
130                                 c->h = sh - bh - 2 * BORDERPX;
131                         }
132                         else {  /* tile window */
133                                 c->x += mpx;
134                                 c->w = stackw - 2 * BORDERPX;
135                                 if(th > bh) {
136                                         c->y = sy + (i - 1) * th + bh;
137                                         if(i + 1 == n)
138                                                 c->h = sh - c->y - 2 * BORDERPX;
139                                         else
140                                                 c->h = th - 2 * BORDERPX;
141                                 }
142                                 else /* fallback if th < bh */
143                                         c->h = stackh - 2 * BORDERPX;
144                         }
145                         resize(c, False, TopLeft);
146                         i++;
147                 }
148                 else
149                         ban(c);
150
151         if(!sel || !isvisible(sel)) {
152                 for(c = stack; c && !isvisible(c); c = c->snext);
153                 focus(c);
154         }
155         restack();
156 }
157
158 void
159 focusnext(Arg *arg) {
160         Client *c;
161    
162         if(!sel)
163                 return;
164         if(!(c = getnext(sel->next)))
165                 c = getnext(clients);
166         if(c) {
167                 focus(c);
168                 restack();
169         }
170 }
171
172 void
173 focusprev(Arg *arg) {
174         Client *c;
175
176         if(!sel)
177                 return;
178         if(!(c = getprev(sel->prev))) {
179                 for(c = clients; c && c->next; c = c->next);
180                 c = getprev(c);
181         }
182         if(c) {
183                 focus(c);
184                 restack();
185         }
186 }
187
188 Bool
189 isvisible(Client *c) {
190         unsigned int i;
191
192         for(i = 0; i < ntags; i++)
193                 if(c->tags[i] && seltag[i])
194                         return True;
195         return False;
196 }
197
198 void
199 resizecol(Arg *arg) {
200         unsigned int n;
201         Client *c;
202
203         for(n = 0, c = clients; c; c = c->next)
204                 if(isvisible(c) && !c->isfloat)
205                         n++;
206         if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
207                 return;
208         if(sel == getnext(clients)) {
209                 if(master + arg->i > 950 || master + arg->i < 50)
210                         return;
211                 master += arg->i;
212         }
213         else {
214                 if(master - arg->i > 950 || master - arg->i < 50)
215                         return;
216                 master -= arg->i;
217         }
218         arrange();
219 }
220
221 void
222 restack(void) {
223         Client *c;
224         XEvent ev;
225
226         if(!sel) {
227                 drawstatus();
228                 return;
229         }
230         if(sel->isfloat || arrange == dofloat) {
231                 XRaiseWindow(dpy, sel->win);
232                 XRaiseWindow(dpy, sel->twin);
233         }
234         if(arrange != dofloat) {
235                 if(!sel->isfloat) {
236                         XLowerWindow(dpy, sel->twin);
237                         XLowerWindow(dpy, sel->win);
238                 }
239                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
240                         if(c == sel)
241                                 continue;
242                         XLowerWindow(dpy, c->twin);
243                         XLowerWindow(dpy, c->win);
244                 }
245         }
246         drawall();
247         XSync(dpy, False);
248         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
249 }
250
251 void
252 togglemode(Arg *arg) {
253         arrange = (arrange == dofloat) ? dotile : dofloat;
254         if(sel)
255                 arrange();
256         else
257                 drawstatus();
258 }
259
260 void
261 toggleview(Arg *arg) {
262         unsigned int i;
263
264         seltag[arg->i] = !seltag[arg->i];
265         for(i = 0; i < ntags && !seltag[i]; i++);
266         if(i == ntags)
267                 seltag[arg->i] = True; /* cannot toggle last view */
268         reorder();
269         arrange();
270 }
271
272 void
273 view(Arg *arg) {
274         unsigned int i;
275
276         for(i = 0; i < ntags; i++)
277                 seltag[i] = False;
278         seltag[arg->i] = True;
279         reorder();
280         arrange();
281 }
282
283 void
284 viewall(Arg *arg) {
285         unsigned int i;
286
287         for(i = 0; i < ntags; i++)
288                 seltag[i] = True;
289         reorder();
290         arrange();
291 }
292
293 void
294 zoom(Arg *arg) {
295         unsigned int n;
296         Client *c;
297
298         if(!sel)
299                 return;
300         if(sel->isfloat || (arrange == dofloat)) {
301                 togglemax(sel);
302                 return;
303         }
304         for(n = 0, c = clients; c; c = c->next)
305                 if(isvisible(c) && !c->isfloat)
306                         n++;
307         if(n < 2 || (arrange == dofloat))
308                 return;
309         if((c = sel) == nexttiled(clients))
310                 if(!(c = nexttiled(c->next)))
311                         return;
312         detach(c);
313         if(clients)
314                 clients->prev = c;
315         c->next = clients;
316         clients = c;
317         focus(c);
318         arrange();
319 }