Xinqi Bao's Git

reverted release CFLAGs
[dwm.git] / screen.c
1 /* See LICENSE file for copyright and license details. */
2 #include "dwm.h"
3 #include <regex.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <X11/Xutil.h>
7
8 /* static */
9
10 typedef struct {
11 const char *symbol;
12 void (*arrange)(void);
13 } Layout;
14
15 typedef struct {
16 const char *prop;
17 const char *tags;
18 Bool isfloating;
19 } Rule;
20
21 typedef struct {
22 regex_t *propregex;
23 regex_t *tagregex;
24 } Regs;
25
26 TAGS
27 RULES
28
29 static unsigned int nrules = 0;
30 static unsigned int nlayouts = 0;
31 static unsigned int ltidx = 0; /* default */
32 static Regs *regs = NULL;
33
34 static unsigned int
35 idxoftag(const char *tag) {
36 unsigned int i;
37
38 for(i = 0; i < ntags; i++)
39 if(tags[i] == tag)
40 return i;
41 return 0;
42 }
43
44 static void
45 floating(void) { /* default floating layout */
46 Client *c;
47
48 for(c = clients; c; c = c->next)
49 if(isvisible(c))
50 resize(c, c->x, c->y, c->w, c->h, True);
51 }
52
53 LAYOUTS
54
55 /* extern */
56
57 unsigned int blw = 0;
58
59 void
60 applyrules(Client *c) {
61 static char buf[512];
62 unsigned int i, j;
63 regmatch_t tmp;
64 Bool matched = False;
65 XClassHint ch = { 0 };
66
67 /* rule matching */
68 XGetClassHint(dpy, c->win, &ch);
69 snprintf(buf, sizeof buf, "%s:%s:%s",
70 ch.res_class ? ch.res_class : "",
71 ch.res_name ? ch.res_name : "", c->name);
72 for(i = 0; i < nrules; i++)
73 if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
74 c->isfloating = rules[i].isfloating;
75 for(j = 0; regs[i].tagregex && j < ntags; j++) {
76 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
77 matched = True;
78 c->tags[j] = True;
79 }
80 }
81 }
82 if(ch.res_class)
83 XFree(ch.res_class);
84 if(ch.res_name)
85 XFree(ch.res_name);
86 if(!matched)
87 for(i = 0; i < ntags; i++)
88 c->tags[i] = seltags[i];
89 }
90
91 void
92 arrange(void) {
93 Client *c;
94
95 for(c = clients; c; c = c->next)
96 if(isvisible(c))
97 unban(c);
98 else
99 ban(c);
100 layouts[ltidx].arrange();
101 focus(NULL);
102 restack();
103 }
104
105 void
106 compileregs(void) {
107 unsigned int i;
108 regex_t *reg;
109
110 if(regs)
111 return;
112 nrules = sizeof rules / sizeof rules[0];
113 regs = emallocz(nrules * sizeof(Regs));
114 for(i = 0; i < nrules; i++) {
115 if(rules[i].prop) {
116 reg = emallocz(sizeof(regex_t));
117 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
118 free(reg);
119 else
120 regs[i].propregex = reg;
121 }
122 if(rules[i].tags) {
123 reg = emallocz(sizeof(regex_t));
124 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
125 free(reg);
126 else
127 regs[i].tagregex = reg;
128 }
129 }
130 }
131
132 void
133 focusnext(const char *arg) {
134 Client *c;
135
136 if(!sel)
137 return;
138 for(c = sel->next; c && !isvisible(c); c = c->next);
139 if(!c)
140 for(c = clients; c && !isvisible(c); c = c->next);
141 if(c) {
142 focus(c);
143 restack();
144 }
145 }
146
147 void
148 focusprev(const char *arg) {
149 Client *c;
150
151 if(!sel)
152 return;
153 for(c = sel->prev; c && !isvisible(c); c = c->prev);
154 if(!c) {
155 for(c = clients; c && c->next; c = c->next);
156 for(; c && !isvisible(c); c = c->prev);
157 }
158 if(c) {
159 focus(c);
160 restack();
161 }
162 }
163
164 const char *
165 getsymbol(void)
166 {
167 return layouts[ltidx].symbol;
168 }
169
170 void
171 initlayouts(void) {
172 unsigned int i, w;
173
174 nlayouts = sizeof layouts / sizeof layouts[0];
175 for(blw = i = 0; i < nlayouts; i++) {
176 w = textw(layouts[i].symbol);
177 if(w > blw)
178 blw = w;
179 }
180 }
181
182 Bool
183 isfloating(void) {
184 return layouts[ltidx].arrange == floating;
185 }
186
187 Bool
188 isarrange(void (*func)())
189 {
190 return func == layouts[ltidx].arrange;
191 }
192
193 Bool
194 isvisible(Client *c) {
195 unsigned int i;
196
197 for(i = 0; i < ntags; i++)
198 if(c->tags[i] && seltags[i])
199 return True;
200 return False;
201 }
202
203 Client *
204 nexttiled(Client *c) {
205 for(; c && (c->isfloating || !isvisible(c)); c = c->next);
206 return c;
207 }
208
209 void
210 restack(void) {
211 Client *c;
212 XEvent ev;
213 XWindowChanges wc;
214
215 drawstatus();
216 if(!sel)
217 return;
218 if(sel->isfloating || isfloating())
219 XRaiseWindow(dpy, sel->win);
220 if(!isfloating()) {
221 wc.stack_mode = Below;
222 wc.sibling = barwin;
223 if(!sel->isfloating) {
224 XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
225 wc.sibling = sel->win;
226 }
227 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
228 if(c == sel)
229 continue;
230 XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
231 wc.sibling = c->win;
232 }
233 }
234 XSync(dpy, False);
235 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
236 }
237
238 void
239 setlayout(const char *arg) {
240 unsigned int i;
241
242 if(!arg) {
243 if(++ltidx == nlayouts)
244 ltidx = 0;;
245 }
246 else {
247 for(i = 0; i < nlayouts; i++)
248 if(arg == layouts[i].symbol)
249 break;
250 if(i == nlayouts)
251 return;
252 ltidx = i;
253 }
254 if(sel)
255 arrange();
256 else
257 drawstatus();
258 }
259
260 void
261 tag(const char *arg) {
262 unsigned int i;
263
264 if(!sel)
265 return;
266 for(i = 0; i < ntags; i++)
267 sel->tags[i] = arg == NULL;
268 i = idxoftag(arg);
269 if(i >= 0 && i < ntags)
270 sel->tags[i] = True;
271 arrange();
272 }
273
274 void
275 togglebar(const char *arg) {
276 if(bpos == BarOff)
277 bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
278 else
279 bpos = BarOff;
280 updatebarpos();
281 arrange();
282 }
283
284 void
285 togglefloating(const char *arg) {
286 if(!sel || isfloating())
287 return;
288 sel->isfloating = !sel->isfloating;
289 if(sel->isfloating)
290 resize(sel, sel->x, sel->y, sel->w, sel->h, True);
291 arrange();
292 }
293
294 void
295 togglemax(const char *arg) {
296 XEvent ev;
297
298 if(!sel || (!isfloating() && !sel->isfloating) || sel->isfixed)
299 return;
300 if((sel->ismax = !sel->ismax)) {
301 sel->rx = sel->x;
302 sel->ry = sel->y;
303 sel->rw = sel->w;
304 sel->rh = sel->h;
305 resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
306 }
307 else
308 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
309 drawstatus();
310 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
311 }
312
313 void
314 toggletag(const char *arg) {
315 unsigned int i, j;
316
317 if(!sel)
318 return;
319 i = idxoftag(arg);
320 sel->tags[i] = !sel->tags[i];
321 for(j = 0; j < ntags && !sel->tags[j]; j++);
322 if(j == ntags)
323 sel->tags[i] = True;
324 arrange();
325 }
326
327 void
328 toggleview(const char *arg) {
329 unsigned int i, j;
330
331 i = idxoftag(arg);
332 seltags[i] = !seltags[i];
333 for(j = 0; j < ntags && !seltags[j]; j++);
334 if(j == ntags)
335 seltags[i] = True; /* cannot toggle last view */
336 arrange();
337 }
338
339 void
340 updatebarpos(void) {
341 XEvent ev;
342
343 wax = sx;
344 way = sy;
345 wah = sh;
346 waw = sw;
347 switch(bpos) {
348 default:
349 wah -= bh;
350 way += bh;
351 XMoveWindow(dpy, barwin, sx, sy);
352 break;
353 case BarBot:
354 wah -= bh;
355 XMoveWindow(dpy, barwin, sx, sy + wah);
356 break;
357 case BarOff:
358 XMoveWindow(dpy, barwin, sx, sy - bh);
359 break;
360 }
361 XSync(dpy, False);
362 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
363 }
364
365 void
366 view(const char *arg) {
367 unsigned int i;
368
369 for(i = 0; i < ntags; i++)
370 seltags[i] = arg == NULL;
371 i = idxoftag(arg);
372 if(i >= 0 && i < ntags)
373 seltags[i] = True;
374 arrange();
375 }