Xinqi Bao's Git

4e97f0985c60d3ddd8bf01137cf3a75fb6325739
[dwm.git] / screen.c
1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
2 * See LICENSE file for license details.
3 */
4 #include "dwm.h"
5 #include <regex.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <X11/Xutil.h>
11
12 void (*arrange)(void) = DEFMODE;
13 unsigned int master = MASTER;
14 unsigned int nmaster = NMASTER;
15
16 /* static */
17
18 typedef struct {
19 const char *prop;
20 const char *tags;
21 Bool isfloat;
22 } Rule;
23
24 typedef struct {
25 regex_t *propregex;
26 regex_t *tagregex;
27 } Regexps;
28
29 TAGS
30 RULES
31
32 static Regexps *regexps = NULL;
33 static unsigned int len = 0;
34
35 /* extern */
36
37 void
38 compileregexps(void) {
39 unsigned int i;
40 regex_t *reg;
41
42 if(regexps)
43 return;
44 len = sizeof rule / sizeof rule[0];
45 regexps = emallocz(len * sizeof(Regexps));
46 for(i = 0; i < len; i++) {
47 if(rule[i].prop) {
48 reg = emallocz(sizeof(regex_t));
49 if(regcomp(reg, rule[i].prop, REG_EXTENDED))
50 free(reg);
51 else
52 regexps[i].propregex = reg;
53 }
54 if(rule[i].tags) {
55 reg = emallocz(sizeof(regex_t));
56 if(regcomp(reg, rule[i].tags, REG_EXTENDED))
57 free(reg);
58 else
59 regexps[i].tagregex = reg;
60 }
61 }
62 }
63
64 void
65 dofloat(void) {
66 Client *c;
67
68 for(c = clients; c; c = c->next) {
69 if(isvisible(c)) {
70 if(c->isbanned)
71 XMoveWindow(dpy, c->win, c->x, c->y);
72 c->isbanned = False;
73 resize(c, c->x, c->y, c->w, c->h, True);
74 }
75 else {
76 c->isbanned = True;
77 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
78 }
79 }
80 if(!sel || !isvisible(sel)) {
81 for(c = stack; c && !isvisible(c); c = c->snext);
82 focus(c);
83 }
84 restack();
85 }
86
87 void
88 dotile(void) {
89 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
90 Client *c;
91
92 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
93 n++;
94 /* window geoms */
95 mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
96 mw = (n > nmaster) ? (waw * master) / 1000 : waw;
97 th = (n > nmaster) ? wah / (n - nmaster) : 0;
98 tw = waw - mw;
99
100 for(i = 0, c = clients; c; c = c->next)
101 if(isvisible(c)) {
102 if(c->isbanned)
103 XMoveWindow(dpy, c->win, c->x, c->y);
104 c->isbanned = False;
105 if(c->isfloat)
106 continue;
107 c->ismax = False;
108 nx = wax;
109 ny = way;
110 if(i < nmaster) {
111 ny += i * mh;
112 nw = mw - 2 * BORDERPX;
113 nh = mh - 2 * BORDERPX;
114 }
115 else { /* tile window */
116 nx += mw;
117 nw = tw - 2 * BORDERPX;
118 if(th > 2 * BORDERPX) {
119 ny += (i - nmaster) * th;
120 nh = th - 2 * BORDERPX;
121 }
122 else /* fallback if th <= 2 * BORDERPX */
123 nh = wah - 2 * BORDERPX;
124 }
125 resize(c, nx, ny, nw, nh, False);
126 i++;
127 }
128 else {
129 c->isbanned = True;
130 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
131 }
132 if(!sel || !isvisible(sel)) {
133 for(c = stack; c && !isvisible(c); c = c->snext);
134 focus(c);
135 }
136 restack();
137 }
138
139 void
140 incnmaster(Arg *arg) {
141 if((arrange == dofloat) || (nmaster + arg->i < 1)
142 || (wah / (nmaster + arg->i) <= 2 * BORDERPX))
143 return;
144 nmaster += arg->i;
145 if(sel)
146 arrange();
147 else
148 drawstatus();
149 }
150
151 Bool
152 isvisible(Client *c) {
153 unsigned int i;
154
155 for(i = 0; i < ntags; i++)
156 if(c->tags[i] && seltag[i])
157 return True;
158 return False;
159 }
160
161 void
162 resizemaster(Arg *arg) {
163 if(arrange != dotile)
164 return;
165 if(arg->i == 0)
166 master = MASTER;
167 else {
168 if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
169 || waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
170 return;
171 master += arg->i;
172 }
173 arrange();
174 }
175
176 void
177 restack(void) {
178 Client *c;
179 XEvent ev;
180
181 drawstatus();
182 if(!sel)
183 return;
184 if(sel->isfloat || arrange == dofloat)
185 XRaiseWindow(dpy, sel->win);
186 if(arrange != dofloat) {
187 if(!sel->isfloat)
188 XLowerWindow(dpy, sel->win);
189 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
190 if(c == sel)
191 continue;
192 XLowerWindow(dpy, c->win);
193 }
194 }
195 XSync(dpy, False);
196 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
197 }
198
199 void
200 settags(Client *c, Client *trans) {
201 char prop[512];
202 unsigned int i, j;
203 regmatch_t tmp;
204 Bool matched = trans != NULL;
205 XClassHint ch = { 0 };
206
207 if(matched)
208 for(i = 0; i < ntags; i++)
209 c->tags[i] = trans->tags[i];
210 else {
211 XGetClassHint(dpy, c->win, &ch);
212 snprintf(prop, sizeof prop, "%s:%s:%s",
213 ch.res_class ? ch.res_class : "",
214 ch.res_name ? ch.res_name : "", c->name);
215 for(i = 0; i < len; i++)
216 if(regexps[i].propregex && !regexec(regexps[i].propregex, prop, 1, &tmp, 0)) {
217 c->isfloat = rule[i].isfloat;
218 for(j = 0; regexps[i].tagregex && j < ntags; j++) {
219 if(!regexec(regexps[i].tagregex, tags[j], 1, &tmp, 0)) {
220 matched = True;
221 c->tags[j] = True;
222 }
223 }
224 }
225 if(ch.res_class)
226 XFree(ch.res_class);
227 if(ch.res_name)
228 XFree(ch.res_name);
229 }
230 if(!matched)
231 for(i = 0; i < ntags; i++)
232 c->tags[i] = seltag[i];
233 }
234
235 void
236 tag(Arg *arg) {
237 unsigned int i;
238
239 if(!sel)
240 return;
241 for(i = 0; i < ntags; i++)
242 sel->tags[i] = (arg->i == -1) ? True : False;
243 if(arg->i >= 0 && arg->i < ntags)
244 sel->tags[arg->i] = True;
245 arrange();
246 }
247
248 void
249 togglefloat(Arg *arg) {
250 if(!sel || arrange == dofloat)
251 return;
252 sel->isfloat = !sel->isfloat;
253 arrange();
254 }
255
256 void
257 toggletag(Arg *arg) {
258 unsigned int i;
259
260 if(!sel)
261 return;
262 sel->tags[arg->i] = !sel->tags[arg->i];
263 for(i = 0; i < ntags && !sel->tags[i]; i++);
264 if(i == ntags)
265 sel->tags[arg->i] = True;
266 arrange();
267 }
268
269 void
270 togglemode(Arg *arg) {
271 arrange = (arrange == dofloat) ? dotile : dofloat;
272 if(sel)
273 arrange();
274 else
275 drawstatus();
276 }
277
278 void
279 toggleview(Arg *arg) {
280 unsigned int i;
281
282 seltag[arg->i] = !seltag[arg->i];
283 for(i = 0; i < ntags && !seltag[i]; i++);
284 if(i == ntags)
285 seltag[arg->i] = True; /* cannot toggle last view */
286 arrange();
287 }
288
289 void
290 view(Arg *arg) {
291 unsigned int i;
292
293 for(i = 0; i < ntags; i++)
294 seltag[i] = (arg->i == -1) ? True : False;
295 if(arg->i >= 0 && arg->i < ntags)
296 seltag[arg->i] = True;
297 arrange();
298 }