aewl
view view.c @ 380:4bf79305d675
this algorithm seems to keep order for any scenario
author | Anselm R. Garbe <arg@10kloc.org> |
---|---|
date | Tue, 29 Aug 2006 09:57:57 +0200 |
parents | 83576f5f0a90 |
children | b00cc483d13b |
line source
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"
7 /* static */
9 static Client *
10 getslot(Client *c)
11 {
12 unsigned int i, tic;
13 Client *p;
15 for(tic = 0; tic < ntags && !c->tags[tic]; tic++);
16 for(p = clients; p; p = p->next) {
17 for(i = 0; i < ntags && !p->tags[i]; i++);
18 if(tic < i)
19 return p;
20 }
21 return p;
22 }
24 static Client *
25 tail()
26 {
27 Client *c;
28 for(c = clients; c && c->next; c = c->next);
29 return c;
30 }
32 /* extern */
34 void (*arrange)(Arg *) = DEFMODE;
36 void
37 attach(Client *c)
38 {
39 Client *p;
41 if(!clients) {
42 clients = c;
43 return;
44 }
45 if(!(p = getnext(clients)) && !(p = getslot(c))) {
46 p = tail();
47 c->prev = p;
48 p->next = c;
49 return;
50 }
52 if(p == clients) {
53 c->next = clients;
54 clients->prev = c;
55 clients = c;
56 }
57 else {
58 p->prev->next = c;
59 c->prev = p->prev;
60 p->prev = c;
61 c->next = p;
62 }
63 }
65 void
66 detach(Client *c)
67 {
68 if(c->prev)
69 c->prev->next = c->next;
70 if(c->next)
71 c->next->prev = c->prev;
72 if(c == clients)
73 clients = c->next;
74 c->next = c->prev = NULL;
75 }
77 void
78 dofloat(Arg *arg)
79 {
80 Client *c;
82 for(c = clients; c; c = c->next) {
83 c->ismax = False;
84 if(isvisible(c)) {
85 resize(c, True, TopLeft);
86 }
87 else
88 ban(c);
89 }
90 if(!sel || !isvisible(sel))
91 sel = getnext(clients);
92 if(sel)
93 focus(sel);
94 else
95 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
96 restack();
97 }
99 void
100 dotile(Arg *arg)
101 {
102 int h, i, n, w;
103 Client *c;
105 w = sw - mw;
106 for(n = 0, c = clients; c; c = c->next)
107 if(isvisible(c) && !c->isfloat)
108 n++;
110 if(n > 1)
111 h = (sh - bh) / (n - 1);
112 else
113 h = sh - bh;
115 for(i = 0, c = clients; c; c = c->next) {
116 c->ismax = False;
117 if(isvisible(c)) {
118 if(c->isfloat) {
119 resize(c, True, TopLeft);
120 continue;
121 }
122 if(n == 1) {
123 c->x = sx;
124 c->y = sy + bh;
125 c->w = sw - 2;
126 c->h = sh - 2 - bh;
127 }
128 else if(i == 0) {
129 c->x = sx;
130 c->y = sy + bh;
131 c->w = mw - 2;
132 c->h = sh - 2 - bh;
133 }
134 else if(h > bh) {
135 c->x = sx + mw;
136 c->y = sy + (i - 1) * h + bh;
137 c->w = w - 2;
138 if(i + 1 == n)
139 c->h = sh - c->y - 2;
140 else
141 c->h = h - 2;
142 }
143 else { /* fallback if h < bh */
144 c->x = sx + mw;
145 c->y = sy + bh;
146 c->w = w - 2;
147 c->h = sh - 2 - bh;
148 }
149 resize(c, False, TopLeft);
150 i++;
151 }
152 else
153 ban(c);
154 }
155 if(!sel || !isvisible(sel))
156 sel = getnext(clients);
157 if(sel)
158 focus(sel);
159 else
160 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
161 restack();
162 }
164 void
165 focusnext(Arg *arg)
166 {
167 Client *c;
169 if(!sel)
170 return;
172 if(!(c = getnext(sel->next)))
173 c = getnext(clients);
174 if(c) {
175 focus(c);
176 restack();
177 }
178 }
180 void
181 focusprev(Arg *arg)
182 {
183 Client *c;
185 if(!sel)
186 return;
188 if(!(c = getprev(sel->prev))) {
189 for(c = clients; c && c->next; c = c->next);
190 c = getprev(c);
191 }
192 if(c) {
193 focus(c);
194 restack();
195 }
196 }
198 Bool
199 isvisible(Client *c)
200 {
201 unsigned int i;
203 for(i = 0; i < ntags; i++)
204 if(c->tags[i] && seltag[i])
205 return True;
206 return False;
207 }
209 void
210 restack()
211 {
212 static unsigned int nwins = 0;
213 static Window *wins = NULL;
214 unsigned int f, fi, m, mi, n;
215 Client *c;
216 XEvent ev;
218 for(f = 0, m = 0, c = clients; c; c = c->next)
219 if(isvisible(c)) {
220 if(c->isfloat || arrange == dofloat)
221 f++;
222 else
223 m++;
224 }
225 if(!(n = 2 * (f + m))) {
226 drawstatus();
227 return;
228 }
229 if(nwins < n) {
230 nwins = n;
231 wins = erealloc(wins, nwins * sizeof(Window));
232 }
234 fi = 0;
235 mi = 2 * f;
236 if(sel->isfloat || arrange == dofloat) {
237 wins[fi++] = sel->twin;
238 wins[fi++] = sel->win;
239 }
240 else {
241 wins[mi++] = sel->twin;
242 wins[mi++] = sel->win;
243 }
244 for(c = clients; c; c = c->next)
245 if(isvisible(c) && c != sel) {
246 if(c->isfloat || arrange == dofloat) {
247 wins[fi++] = c->twin;
248 wins[fi++] = c->win;
249 }
250 else {
251 wins[mi++] = c->twin;
252 wins[mi++] = c->win;
253 }
254 }
255 XRestackWindows(dpy, wins, n);
256 drawall();
257 XSync(dpy, False);
258 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
259 }
261 void
262 togglemode(Arg *arg)
263 {
264 arrange = (arrange == dofloat) ? dotile : dofloat;
265 if(sel)
266 arrange(NULL);
267 else
268 drawstatus();
269 }
271 void
272 toggleview(Arg *arg)
273 {
274 unsigned int i;
276 seltag[arg->i] = !seltag[arg->i];
277 for(i = 0; i < ntags && !seltag[i]; i++);
278 if(i == ntags)
279 seltag[arg->i] = True; /* cannot toggle last view */
280 arrange(NULL);
281 }
283 void
284 view(Arg *arg)
285 {
286 unsigned int i;
288 for(i = 0; i < ntags; i++)
289 seltag[i] = False;
290 seltag[arg->i] = True;
291 arrange(NULL);
292 }
294 void
295 zoom(Arg *arg)
296 {
297 Client *c = sel;
299 if(!c || (arrange != dotile) || c->isfloat || c->ismax)
300 return;
302 if(c == getnext(clients))
303 if(!(c = getnext(c->next)))
304 return;
305 detach(c);
306 attach(c);
307 focus(c);
308 arrange(NULL);
309 }