view.c (view raw)
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
8static Client *
9minclient(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
20static Client *
21nexttiled(Client *c) {
22 for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
23 return c;
24}
25
26static void
27reorder(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
44static void
45togglemax(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
66void (*arrange)(void) = DEFMODE;
67
68void
69detach(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
79void
80dofloat(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
97void
98dotile(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
154void
155focusnext(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
168void
169focusprev(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
184Bool
185isvisible(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
194void
195resizecol(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
217void
218restack(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
247void
248togglemode(Arg *arg) {
249 arrange = (arrange == dofloat) ? dotile : dofloat;
250 if(sel)
251 arrange();
252 else
253 drawstatus();
254}
255
256void
257toggleview(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
268void
269view(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
279void
280viewall(Arg *arg) {
281 unsigned int i;
282
283 for(i = 0; i < ntags; i++)
284 seltag[i] = True;
285 reorder();
286 arrange();
287}
288
289void
290zoom(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}