1 /* See LICENSE file for copyright and license details. */
12 void (*arrange)(void);
29 static unsigned int nrules = 0;
30 static unsigned int nlayouts = 0;
31 static unsigned int ltidx = 0; /* default */
32 static Regs *regs = NULL;
35 idxoftag(const char *tag) {
38 for(i = 0; i < ntags; i++)
45 floating(void) { /* default floating layout */
48 for(c = clients; c; c = c->next)
50 resize(c, c->x, c->y, c->w, c->h, True);
60 applyrules(Client *c) {
65 XClassHint ch = { 0 };
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)) {
87 for(i = 0; i < ntags; i++)
88 c->tags[i] = seltags[i];
95 for(c = clients; c; c = c->next)
100 layouts[ltidx].arrange();
112 nrules = sizeof rules / sizeof rules[0];
113 regs = emallocz(nrules * sizeof(Regs));
114 for(i = 0; i < nrules; i++) {
116 reg = emallocz(sizeof(regex_t));
117 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
120 regs[i].propregex = reg;
123 reg = emallocz(sizeof(regex_t));
124 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
127 regs[i].tagregex = reg;
133 focusnext(const char *arg) {
138 for(c = sel->next; c && !isvisible(c); c = c->next);
140 for(c = clients; c && !isvisible(c); c = c->next);
148 focusprev(const char *arg) {
153 for(c = sel->prev; c && !isvisible(c); c = c->prev);
155 for(c = clients; c && c->next; c = c->next);
156 for(; c && !isvisible(c); c = c->prev);
167 return layouts[ltidx].symbol;
174 nlayouts = sizeof layouts / sizeof layouts[0];
175 for(blw = i = 0; i < nlayouts; i++) {
176 w = textw(layouts[i].symbol);
184 return layouts[ltidx].arrange == floating;
188 isarrange(void (*func)())
190 return func == layouts[ltidx].arrange;
194 isvisible(Client *c) {
197 for(i = 0; i < ntags; i++)
198 if(c->tags[i] && seltags[i])
204 nexttiled(Client *c) {
205 for(; c && (c->isfloating || !isvisible(c)); c = c->next);
218 if(sel->isfloating || isfloating())
219 XRaiseWindow(dpy, sel->win);
221 wc.stack_mode = Below;
223 if(!sel->isfloating) {
224 XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
225 wc.sibling = sel->win;
227 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
230 XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
235 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
239 setlayout(const char *arg) {
243 if(++ltidx == nlayouts)
247 for(i = 0; i < nlayouts; i++)
248 if(arg == layouts[i].symbol)
261 tag(const char *arg) {
266 for(i = 0; i < ntags; i++)
267 sel->tags[i] = arg == NULL;
269 if(i >= 0 && i < ntags)
275 togglebar(const char *arg) {
277 bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
285 togglefloating(const char *arg) {
286 if(!sel || isfloating())
288 sel->isfloating = !sel->isfloating;
290 resize(sel, sel->x, sel->y, sel->w, sel->h, True);
295 togglemax(const char *arg) {
298 if(!sel || (!isfloating() && !sel->isfloating) || sel->isfixed)
300 if((sel->ismax = !sel->ismax)) {
305 resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
308 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
310 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
314 toggletag(const char *arg) {
320 sel->tags[i] = !sel->tags[i];
321 for(j = 0; j < ntags && !sel->tags[j]; j++);
328 toggleview(const char *arg) {
332 seltags[i] = !seltags[i];
333 for(j = 0; j < ntags && !seltags[j]; j++);
335 seltags[i] = True; /* cannot toggle last view */
351 XMoveWindow(dpy, barwin, sx, sy);
355 XMoveWindow(dpy, barwin, sx, sy + wah);
358 XMoveWindow(dpy, barwin, sx, sy - bh);
362 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
366 view(const char *arg) {
369 for(i = 0; i < ntags; i++)
370 seltags[i] = arg == NULL;
372 if(i >= 0 && i < ntags)