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