Xinqi Bao's Git

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