JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
hotfix
[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)(void) = 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(void) {
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(void) {
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)
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                         i++;
143                 }
144                 else
145                         ban(c);
146
147         if(!sel || !isvisible(sel)) {
148                 for(c = stack; c && !isvisible(c); c = c->snext);
149                 focus(c);
150         }
151         restack();
152 }
153
154 void
155 focusnext(Arg *arg) {
156         Client *c;
157    
158         if(!sel)
159                 return;
160         if(!(c = getnext(sel->next)))
161                 c = getnext(clients);
162         if(c) {
163                 focus(c);
164                 restack();
165         }
166 }
167
168 void
169 focusprev(Arg *arg) {
170         Client *c;
171
172         if(!sel)
173                 return;
174         if(!(c = getprev(sel->prev))) {
175                 for(c = clients; c && c->next; c = c->next);
176                 c = getprev(c);
177         }
178         if(c) {
179                 focus(c);
180                 restack();
181         }
182 }
183
184 Bool
185 isvisible(Client *c) {
186         unsigned int i;
187
188         for(i = 0; i < ntags; i++)
189                 if(c->tags[i] && seltag[i])
190                         return True;
191         return False;
192 }
193
194 void
195 resizecol(Arg *arg) {
196         unsigned int n;
197         Client *c;
198
199         for(n = 0, c = clients; c; c = c->next)
200                 if(isvisible(c) && !c->isfloat)
201                         n++;
202         if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
203                 return;
204         if(sel == getnext(clients)) {
205                 if(master + arg->i > 950 || master + arg->i < 50)
206                         return;
207                 master += arg->i;
208         }
209         else {
210                 if(master - arg->i > 950 || master - arg->i < 50)
211                         return;
212                 master -= arg->i;
213         }
214         arrange();
215 }
216
217 void
218 restack(void) {
219         Client *c;
220         XEvent ev;
221
222         if(!sel) {
223                 drawstatus();
224                 return;
225         }
226         if(sel->isfloat || arrange == dofloat) {
227                 XRaiseWindow(dpy, sel->win);
228                 XRaiseWindow(dpy, sel->twin);
229         }
230         if(arrange != dofloat) {
231                 if(!sel->isfloat) {
232                         XLowerWindow(dpy, sel->twin);
233                         XLowerWindow(dpy, sel->win);
234                 }
235                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
236                         if(c == sel)
237                                 continue;
238                         XLowerWindow(dpy, c->twin);
239                         XLowerWindow(dpy, c->win);
240                 }
241         }
242         drawall();
243         XSync(dpy, False);
244         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
245 }
246
247 void
248 togglemode(Arg *arg) {
249         arrange = (arrange == dofloat) ? dotile : dofloat;
250         if(sel)
251                 arrange();
252         else
253                 drawstatus();
254 }
255
256 void
257 toggleview(Arg *arg) {
258         unsigned int i;
259
260         seltag[arg->i] = !seltag[arg->i];
261         for(i = 0; i < ntags && !seltag[i]; i++);
262         if(i == ntags)
263                 seltag[arg->i] = True; /* cannot toggle last view */
264         reorder();
265         arrange();
266 }
267
268 void
269 view(Arg *arg) {
270         unsigned int i;
271
272         for(i = 0; i < ntags; i++)
273                 seltag[i] = False;
274         seltag[arg->i] = True;
275         reorder();
276         arrange();
277 }
278
279 void
280 viewall(Arg *arg) {
281         unsigned int i;
282
283         for(i = 0; i < ntags; i++)
284                 seltag[i] = True;
285         reorder();
286         arrange();
287 }
288
289 void
290 zoom(Arg *arg) {
291         unsigned int n;
292         Client *c;
293
294         if(!sel)
295                 return;
296         if(sel->isfloat || (arrange == dofloat)) {
297                 togglemax(sel);
298                 return;
299         }
300         for(n = 0, c = clients; c; c = c->next)
301                 if(isvisible(c) && !c->isfloat)
302                         n++;
303         if(n < 2 || (arrange == dofloat))
304                 return;
305         if((c = sel) == nexttiled(clients))
306                 if(!(c = nexttiled(c->next)))
307                         return;
308         detach(c);
309         if(clients)
310                 clients->prev = c;
311         c->next = clients;
312         clients = c;
313         focus(c);
314         arrange();
315 }