Xinqi Bao's Git

f3f8e26d3c2b52853be8d02bbf2e1be6b1000c2a
[dwm.git] / layout.c
1 /* See LICENSE file for copyright and license details. */
2 #include "dwm.h"
3 #include <stdlib.h>
4
5 unsigned int blw = 0;
6 Layout *lt = NULL;
7
8 /* static */
9
10 static unsigned int nlayouts = 0;
11 static unsigned int masterw = MASTERWIDTH;
12 static unsigned int nmaster = NMASTER;
13
14 static void
15 ban(Client *c) {
16 if (c->isbanned)
17 return;
18 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
19 c->isbanned = True;
20 }
21
22 static void
23 unban(Client *c) {
24 if (!c->isbanned)
25 return;
26 XMoveWindow(dpy, c->win, c->x, c->y);
27 c->isbanned = False;
28 }
29
30 static void
31 tile(void) {
32 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
33 Client *c;
34
35 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
36 n++;
37 /* window geoms */
38 mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
39 mw = (n > nmaster) ? (waw * masterw) / 1000 : waw;
40 th = (n > nmaster) ? wah / (n - nmaster) : 0;
41 tw = waw - mw;
42
43 for(i = 0, c = clients; c; c = c->next)
44 if(isvisible(c)) {
45 unban(c);
46 if(c->isfloating)
47 continue;
48 c->ismax = False;
49 nx = wax;
50 ny = way;
51 if(i < nmaster) {
52 ny += i * mh;
53 nw = mw - 2 * c->border;
54 nh = mh;
55 if(i + 1 == (n < nmaster ? n : nmaster)) /* remainder */
56 nh = wah - mh * i;
57 nh -= 2 * c->border;
58 }
59 else { /* tile window */
60 nx += mw;
61 nw = tw - 2 * c->border;
62 if(th > 2 * c->border) {
63 ny += (i - nmaster) * th;
64 nh = th;
65 if(i + 1 == n) /* remainder */
66 nh = wah - th * (i - nmaster);
67 nh -= 2 * c->border;
68 }
69 else /* fallback if th <= 2 * c->border */
70 nh = wah - 2 * c->border;
71 }
72 resize(c, nx, ny, nw, nh, False);
73 i++;
74 }
75 else
76 ban(c);
77 focus(NULL);
78 restack();
79 }
80
81 LAYOUTS
82
83 /* extern */
84
85 void
86 floating(void) {
87 Client *c;
88
89 for(c = clients; c; c = c->next)
90 if(isvisible(c)) {
91 if(c->isbanned)
92 XMoveWindow(dpy, c->win, c->x, c->y);
93 c->isbanned = False;
94 resize(c, c->x, c->y, c->w, c->h, True);
95 }
96 else
97 ban(c);
98 focus(NULL);
99 restack();
100 }
101
102 void
103 focusclient(const char *arg) {
104 Client *c;
105
106 if(!sel || !arg)
107 return;
108 if(atoi(arg) < 0) {
109 for(c = sel->prev; c && !isvisible(c); c = c->prev);
110 if(!c) {
111 for(c = clients; c && c->next; c = c->next);
112 for(; c && !isvisible(c); c = c->prev);
113 }
114 }
115 else {
116 for(c = sel->next; c && !isvisible(c); c = c->next);
117 if(!c)
118 for(c = clients; c && !isvisible(c); c = c->next);
119 }
120 if(c) {
121 focus(c);
122 restack();
123 }
124 }
125
126 void
127 incmasterw(const char *arg) {
128 int i;
129 if(lt->arrange != tile)
130 return;
131 if(!arg)
132 masterw = MASTERWIDTH;
133 else {
134 i = atoi(arg);
135 if(waw * (masterw + i) / 1000 >= waw - 2 * BORDERPX
136 || waw * (masterw + i) / 1000 <= 2 * BORDERPX)
137 return;
138 masterw += i;
139 }
140 lt->arrange();
141 }
142
143 void
144 incnmaster(const char *arg) {
145 int i;
146
147 if(!arg)
148 nmaster = NMASTER;
149 else {
150 i = atoi(arg);
151 if((lt->arrange != tile) || (nmaster + i < 1)
152 || (wah / (nmaster + i) <= 2 * BORDERPX))
153 return;
154 nmaster += i;
155 }
156 if(sel)
157 lt->arrange();
158 else
159 drawstatus();
160 }
161
162 void
163 initlayouts(void) {
164 unsigned int i, w;
165
166 lt = &layout[0];
167 nlayouts = sizeof layout / sizeof layout[0];
168 for(blw = i = 0; i < nlayouts; i++) {
169 w = textw(layout[i].symbol);
170 if(w > blw)
171 blw = w;
172 }
173 }
174
175 Client *
176 nexttiled(Client *c) {
177 for(; c && (c->isfloating || !isvisible(c)); c = c->next);
178 return c;
179 }
180
181 void
182 restack(void) {
183 Client *c;
184 XEvent ev;
185
186 drawstatus();
187 if(!sel)
188 return;
189 if(sel->isfloating || lt->arrange == floating)
190 XRaiseWindow(dpy, sel->win);
191 if(lt->arrange != floating) {
192 if(!sel->isfloating)
193 XLowerWindow(dpy, sel->win);
194 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
195 if(c == sel)
196 continue;
197 XLowerWindow(dpy, c->win);
198 }
199 }
200 XSync(dpy, False);
201 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
202 }
203
204 void
205 setlayout(const char *arg) {
206 int i;
207
208 if(!arg) {
209 lt++;
210 if(lt == layout + nlayouts)
211 lt = layout;
212 }
213 else {
214 i = atoi(arg);
215 if(i < 0 || i >= nlayouts)
216 return;
217 lt = &layout[i];
218 }
219 if(sel)
220 lt->arrange();
221 else
222 drawstatus();
223 }
224
225 void
226 togglebar(const char *arg) {
227 if(bpos == BarOff)
228 bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
229 else
230 bpos = BarOff;
231 updatebarpos();
232 lt->arrange();
233 }
234
235 void
236 togglemax(const char *arg) {
237 XEvent ev;
238
239 if(!sel || (lt->arrange != floating && !sel->isfloating) || sel->isfixed)
240 return;
241 if((sel->ismax = !sel->ismax)) {
242 sel->rx = sel->x;
243 sel->ry = sel->y;
244 sel->rw = sel->w;
245 sel->rh = sel->h;
246 resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
247 }
248 else
249 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
250 drawstatus();
251 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
252 }
253
254 void
255 zoom(const char *arg) {
256 Client *c;
257
258 if(!sel || lt->arrange == floating || sel->isfloating)
259 return;
260 if((c = sel) == nexttiled(clients))
261 if(!(c = nexttiled(c->next)))
262 return;
263 detach(c);
264 attach(c);
265 focus(c);
266 lt->arrange();
267 }