JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
still something wrong with reorder()
[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 void
10 reorder()
11 {
12         Client *c, *orig, *p;
13
14         orig = clients;
15         clients = NULL;
16
17         while((c = orig)) {
18                 orig = orig->next;
19                 detach(c);
20
21                 for(p = clients; p && p->next && p->weight <= c->weight; p = p->next);
22                 c->prev = p;
23                 if(p) {
24                         if((c->next = p->next))
25                                 c->next->prev = c;
26                         p->next = c;
27                 }
28                 else
29                         clients = c;
30         }
31 }
32
33 /* extern */
34
35 void (*arrange)(Arg *) = DEFMODE;
36
37 void
38 detach(Client *c)
39 {
40         if(c->prev)
41                 c->prev->next = c->next;
42         if(c->next)
43                 c->next->prev = c->prev;
44         if(c == clients)
45                 clients = c->next;
46         c->next = c->prev = NULL;
47 }
48
49 void
50 dofloat(Arg *arg)
51 {
52         Client *c;
53
54         for(c = clients; c; c = c->next) {
55                 c->ismax = False;
56                 if(isvisible(c)) {
57                         resize(c, True, TopLeft);
58                 }
59                 else
60                         ban(c);
61         }
62         if(!sel || !isvisible(sel))
63                 sel = getnext(clients);
64         if(sel)
65                 focus(sel);
66         else
67                 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
68         restack();
69 }
70
71 void
72 dotile(Arg *arg)
73 {
74         int h, i, n, w;
75         Client *c;
76
77         w = sw - mw;
78         for(n = 0, c = clients; c; c = c->next)
79                 if(isvisible(c) && !c->isfloat)
80                         n++;
81
82         if(n > 1)
83                 h = (sh - bh) / (n - 1);
84         else
85                 h = sh - bh;
86
87         for(i = 0, c = clients; c; c = c->next) {
88                 c->ismax = False;
89                 if(isvisible(c)) {
90                         if(c->isfloat) {
91                                 resize(c, True, TopLeft);
92                                 continue;
93                         }
94                         if(n == 1) {
95                                 c->x = sx;
96                                 c->y = sy + bh;
97                                 c->w = sw - 2;
98                                 c->h = sh - 2 - bh;
99                         }
100                         else if(i == 0) {
101                                 c->x = sx;
102                                 c->y = sy + bh;
103                                 c->w = mw - 2;
104                                 c->h = sh - 2 - bh;
105                         }
106                         else if(h > bh) {
107                                 c->x = sx + mw;
108                                 c->y = sy + (i - 1) * h + bh;
109                                 c->w = w - 2;
110                                 if(i + 1 == n)
111                                         c->h = sh - c->y - 2;
112                                 else
113                                         c->h = h - 2;
114                         }
115                         else { /* fallback if h < bh */
116                                 c->x = sx + mw;
117                                 c->y = sy + bh;
118                                 c->w = w - 2;
119                                 c->h = sh - 2 - bh;
120                         }
121                         resize(c, False, TopLeft);
122                         i++;
123                 }
124                 else
125                         ban(c);
126         }
127         if(!sel || !isvisible(sel))
128                 sel = getnext(clients);
129         if(sel)
130                 focus(sel);
131         else
132                 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
133         restack();
134 }
135
136 void
137 focusnext(Arg *arg)
138 {
139         Client *c;
140    
141         if(!sel)
142                 return;
143
144         if(!(c = getnext(sel->next)))
145                 c = getnext(clients);
146         if(c) {
147                 focus(c);
148                 restack();
149         }
150 }
151
152 void
153 focusprev(Arg *arg)
154 {
155         Client *c;
156
157         if(!sel)
158                 return;
159
160         if(!(c = getprev(sel->prev))) {
161                 for(c = clients; c && c->next; c = c->next);
162                 c = getprev(c);
163         }
164         if(c) {
165                 focus(c);
166                 restack();
167         }
168 }
169
170 Bool
171 isvisible(Client *c)
172 {
173         unsigned int i;
174
175         for(i = 0; i < ntags; i++)
176                 if(c->tags[i] && seltag[i])
177                         return True;
178         return False;
179 }
180
181 void
182 restack()
183 {
184         static unsigned int nwins = 0;
185         static Window *wins = NULL;
186         unsigned int f, fi, m, mi, n;
187         Client *c;
188         XEvent ev;
189
190         for(f = 0, m = 0, c = clients; c; c = c->next)
191                 if(isvisible(c)) {
192                         if(c->isfloat || arrange == dofloat)
193                                 f++;
194                         else
195                                 m++;
196                 }
197         if(!(n = 2 * (f + m))) {
198                 drawstatus();
199                 return;
200         }
201         if(nwins < n) {
202                 nwins = n;
203                 wins = erealloc(wins, nwins * sizeof(Window));
204         }
205
206         fi = 0;
207         mi = 2 * f;
208         if(sel->isfloat || arrange == dofloat) {
209                 wins[fi++] = sel->twin;
210                 wins[fi++] = sel->win;
211         }
212         else {
213                 wins[mi++] = sel->twin;
214                 wins[mi++] = sel->win;
215         }
216         for(c = clients; c; c = c->next)
217                 if(isvisible(c) && c != sel) {
218                         if(c->isfloat || arrange == dofloat) {
219                                 wins[fi++] = c->twin;
220                                 wins[fi++] = c->win;
221                         }
222                         else {
223                                 wins[mi++] = c->twin;
224                                 wins[mi++] = c->win;
225                         }
226                 }
227         XRestackWindows(dpy, wins, n);
228         drawall();
229         XSync(dpy, False);
230         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
231 }
232
233 void
234 togglemode(Arg *arg)
235 {
236         arrange = (arrange == dofloat) ? dotile : dofloat;
237         if(sel)
238                 arrange(NULL);
239         else
240                 drawstatus();
241 }
242
243 void
244 toggleview(Arg *arg)
245 {
246         unsigned int i;
247
248         seltag[arg->i] = !seltag[arg->i];
249         for(i = 0; i < ntags && !seltag[i]; i++);
250         if(i == ntags)
251                 seltag[arg->i] = True; /* cannot toggle last view */
252         reorder();
253         arrange(NULL);
254 }
255
256 void
257 view(Arg *arg)
258 {
259         unsigned int i;
260         Client *c;
261
262         for(i = 0; i < ntags; i++)
263                 seltag[i] = False;
264         seltag[arg->i] = True;
265         reorder();
266         arrange(NULL);
267 }
268
269 void
270 zoom(Arg *arg)
271 {
272         Client *c = sel;
273
274         if(!c || (arrange != dotile) || c->isfloat || c->ismax)
275                 return;
276
277         if(c == getnext(clients))
278                 if(!(c = getnext(c->next)))
279                         return;
280         detach(c);
281         c->next = clients;
282         clients->prev = c;
283         clients = c;
284         focus(c);
285         arrange(NULL);
286 }