JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
applied sanders patch of not manipulating sel
[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 #include <stdio.h>
7
8 /* static */
9
10 static Client *
11 minclient()
12 {
13         Client *c, *min;
14
15         if((clients && clients->isfloat) || arrange == dofloat)
16                 return clients; /* don't touch floating order */
17         for(min = c = clients; c; c = c->next)
18                 if(c->weight < min->weight)
19                         min = c;
20         return min;
21 }
22
23 static void
24 reorder()
25 {
26         Client *c, *newclients, *tail;
27
28         newclients = tail = NULL;
29         while((c = minclient())) {
30                 detach(c);
31                 if(tail) {
32                         c->prev = tail;
33                         tail->next = c;
34                         tail = c;
35                 }
36                 else
37                         tail = newclients = c;
38         }
39         clients = newclients;
40 }
41
42 static Client *
43 nexttiled(Client *c)
44 {
45         for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
46         return c;
47 }
48
49 /* extern */
50
51 void (*arrange)(Arg *) = DEFMODE;
52
53 void
54 detach(Client *c)
55 {
56         if(c->prev)
57                 c->prev->next = c->next;
58         if(c->next)
59                 c->next->prev = c->prev;
60         if(c == clients)
61                 clients = c->next;
62         c->next = c->prev = NULL;
63 }
64
65 void
66 dofloat(Arg *arg)
67 {
68         Client *c;
69
70         maximized = False;
71
72         for(c = clients; c; c = c->next) {
73                 if(isvisible(c)) {
74                         resize(c, True, TopLeft);
75                 }
76                 else
77                         ban(c);
78         }
79         if(!sel || !isvisible(sel)) {
80                 for(c = stack; c && !isvisible(c); c = c->snext);
81                 focus(c);
82         }
83         restack();
84 }
85
86 void
87 dotile(Arg *arg)
88 {
89         int h, i, n, w;
90         Client *c;
91
92         maximized = False;
93
94         w = sw - mw;
95         for(n = 0, c = clients; c; c = c->next)
96                 if(isvisible(c) && !c->isfloat)
97                         n++;
98
99         if(n > 1)
100                 h = (sh - bh) / (n - 1);
101         else
102                 h = sh - bh;
103
104         for(i = 0, c = clients; c; c = c->next) {
105                 if(isvisible(c)) {
106                         if(c->isfloat) {
107                                 resize(c, True, TopLeft);
108                                 continue;
109                         }
110                         if(n == 1) {
111                                 c->x = sx;
112                                 c->y = sy + bh;
113                                 c->w = sw - 2;
114                                 c->h = sh - 2 - bh;
115                         }
116                         else if(i == 0) {
117                                 c->x = sx;
118                                 c->y = sy + bh;
119                                 c->w = mw - 2;
120                                 c->h = sh - 2 - bh;
121                         }
122                         else if(h > bh) {
123                                 c->x = sx + mw;
124                                 c->y = sy + (i - 1) * h + bh;
125                                 c->w = w - 2;
126                                 if(i + 1 == n)
127                                         c->h = sh - c->y - 2;
128                                 else
129                                         c->h = h - 2;
130                         }
131                         else { /* fallback if h < bh */
132                                 c->x = sx + mw;
133                                 c->y = sy + bh;
134                                 c->w = w - 2;
135                                 c->h = sh - 2 - bh;
136                         }
137                         resize(c, False, TopLeft);
138                         i++;
139                 }
140                 else
141                         ban(c);
142         }
143         if(!sel || !isvisible(sel)) {
144                 for(c = stack; c && !isvisible(c); c = c->snext);
145                 focus(c);
146         }
147         restack();
148 }
149
150 void
151 focusnext(Arg *arg)
152 {
153         Client *c;
154    
155         if(!sel)
156                 return;
157
158         if(!(c = getnext(sel->next)))
159                 c = getnext(clients);
160         if(c) {
161                 focus(c);
162                 restack();
163         }
164 }
165
166 void
167 focusprev(Arg *arg)
168 {
169         Client *c;
170
171         if(!sel)
172                 return;
173
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 {
187         unsigned int i;
188
189         for(i = 0; i < ntags; i++)
190                 if(c->tags[i] && seltag[i])
191                         return True;
192         return False;
193 }
194
195 void
196 resizecol(Arg *arg)
197 {
198         unsigned int n;
199         Client *c;
200
201         for(n = 0, c = clients; c; c = c->next)
202                 if(isvisible(c) && !c->isfloat)
203                         n++;
204         if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
205                 return;
206
207         if(sel == getnext(clients)) {
208                 if(mw + arg->i > sw - 100 || mw + arg->i < 100)
209                         return;
210                 mw += arg->i;
211         }
212         else {
213                 if(mw - arg->i > sw - 100 || mw - arg->i < 100)
214                         return;
215                 mw -= arg->i;
216         }
217         arrange(NULL);
218 }
219
220 void
221 restack()
222 {
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                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
236                         XLowerWindow(dpy, c->twin);
237                         XLowerWindow(dpy, c->win);
238                 }
239         drawall();
240         XSync(dpy, False);
241         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
242 }
243
244 void
245 togglemode(Arg *arg)
246 {
247         arrange = (arrange == dofloat) ? dotile : dofloat;
248         if(sel)
249                 arrange(NULL);
250         else
251                 drawstatus();
252 }
253
254 void
255 toggleview(Arg *arg)
256 {
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 {
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(NULL);
277 }
278
279 void
280 viewall(Arg *arg)
281 {
282         unsigned int i;
283
284         for(i = 0; i < ntags; i++)
285                 seltag[i] = True;
286         reorder();
287         arrange(NULL);
288 }
289
290 void
291 zoom(Arg *arg)
292 {
293         unsigned int n;
294         Client *c;
295
296         for(n = 0, c = clients; c; c = c->next)
297                 if(isvisible(c) && !c->isfloat)
298                         n++;
299         if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
300                 return;
301
302         if((c = sel) == nexttiled(clients))
303                 if(!(c = nexttiled(c->next)))
304                         return;
305         detach(c);
306         if(clients)
307                 clients->prev = c;
308         c->next = clients;
309         clients = c;
310         focus(c);
311         arrange(NULL);
312 }