JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
this patch keeps track of global z-layer order of clients which are floating or if...
[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                 focus(getnext(clients));
81         restack();
82 }
83
84 void
85 dotile(Arg *arg)
86 {
87         int h, i, n, w;
88         Client *c;
89
90         maximized = False;
91
92         w = sw - mw;
93         for(n = 0, c = clients; c; c = c->next)
94                 if(isvisible(c) && !c->isfloat)
95                         n++;
96
97         if(n > 1)
98                 h = (sh - bh) / (n - 1);
99         else
100                 h = sh - bh;
101
102         for(i = 0, c = clients; c; c = c->next) {
103                 if(isvisible(c)) {
104                         if(c->isfloat) {
105                                 resize(c, True, TopLeft);
106                                 continue;
107                         }
108                         if(n == 1) {
109                                 c->x = sx;
110                                 c->y = sy + bh;
111                                 c->w = sw - 2;
112                                 c->h = sh - 2 - bh;
113                         }
114                         else if(i == 0) {
115                                 c->x = sx;
116                                 c->y = sy + bh;
117                                 c->w = mw - 2;
118                                 c->h = sh - 2 - bh;
119                         }
120                         else if(h > bh) {
121                                 c->x = sx + mw;
122                                 c->y = sy + (i - 1) * h + bh;
123                                 c->w = w - 2;
124                                 if(i + 1 == n)
125                                         c->h = sh - c->y - 2;
126                                 else
127                                         c->h = h - 2;
128                         }
129                         else { /* fallback if h < bh */
130                                 c->x = sx + mw;
131                                 c->y = sy + bh;
132                                 c->w = w - 2;
133                                 c->h = sh - 2 - bh;
134                         }
135                         resize(c, False, TopLeft);
136                         i++;
137                 }
138                 else
139                         ban(c);
140         }
141         if(!sel || !isvisible(sel))
142                 focus(getnext(clients));
143         restack();
144 }
145
146 void
147 focusnext(Arg *arg)
148 {
149         Client *c;
150    
151         if(!sel)
152                 return;
153
154         if(!(c = getnext(sel->next)))
155                 c = getnext(clients);
156         if(c) {
157                 focus(c);
158                 restack();
159         }
160 }
161
162 void
163 focusprev(Arg *arg)
164 {
165         Client *c;
166
167         if(!sel)
168                 return;
169
170         if(!(c = getprev(sel->prev))) {
171                 for(c = clients; c && c->next; c = c->next);
172                 c = getprev(c);
173         }
174         if(c) {
175                 focus(c);
176                 restack();
177         }
178 }
179
180 Bool
181 isvisible(Client *c)
182 {
183         unsigned int i;
184
185         for(i = 0; i < ntags; i++)
186                 if(c->tags[i] && seltag[i])
187                         return True;
188         return False;
189 }
190
191 void
192 resizecol(Arg *arg)
193 {
194         unsigned int n;
195         Client *c;
196
197         for(n = 0, c = clients; c; c = c->next)
198                 if(isvisible(c) && !c->isfloat)
199                         n++;
200         if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
201                 return;
202
203         if(sel == getnext(clients)) {
204                 if(mw + arg->i > sw - 100 || mw + arg->i < 100)
205                         return;
206                 mw += arg->i;
207         }
208         else {
209                 if(mw - arg->i > sw - 100 || mw - arg->i < 100)
210                         return;
211                 mw -= arg->i;
212         }
213         arrange(NULL);
214 }
215
216 void
217 restack()
218 {
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                 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
232                         XLowerWindow(dpy, c->twin);
233                         XLowerWindow(dpy, c->win);
234                 }
235         drawall();
236         XSync(dpy, False);
237         while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
238 }
239
240 void
241 togglemode(Arg *arg)
242 {
243         arrange = (arrange == dofloat) ? dotile : dofloat;
244         if(sel)
245                 arrange(NULL);
246         else
247                 drawstatus();
248 }
249
250 void
251 toggleview(Arg *arg)
252 {
253         unsigned int i;
254
255         seltag[arg->i] = !seltag[arg->i];
256         for(i = 0; i < ntags && !seltag[i]; i++);
257         if(i == ntags)
258                 seltag[arg->i] = True; /* cannot toggle last view */
259         reorder();
260         arrange(NULL);
261 }
262
263 void
264 view(Arg *arg)
265 {
266         unsigned int i;
267
268         for(i = 0; i < ntags; i++)
269                 seltag[i] = False;
270         seltag[arg->i] = True;
271         reorder();
272         arrange(NULL);
273 }
274
275 void
276 viewall(Arg *arg)
277 {
278         unsigned int i;
279
280         for(i = 0; i < ntags; i++)
281                 seltag[i] = True;
282         reorder();
283         arrange(NULL);
284 }
285
286 void
287 zoom(Arg *arg)
288 {
289         unsigned int n;
290         Client *c;
291
292         for(n = 0, c = clients; c; c = c->next)
293                 if(isvisible(c) && !c->isfloat)
294                         n++;
295         if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
296                 return;
297
298         if((c = sel) == nexttiled(clients))
299                 if(!(c = nexttiled(c->next)))
300                         return;
301         detach(c);
302         if(clients)
303                 clients->prev = c;
304         c->next = clients;
305         clients = c;
306         focus(c);
307         arrange(NULL);
308 }