| 106 |
106 |
|
|
| 107 |
107 |
|
typedef struct { |
| 108 |
108 |
|
const char *prop; |
| 109 |
|
- |
const char *tags; |
|
109 |
+ |
const char *tag; |
| 110 |
110 |
|
Bool isfloating; |
| 111 |
111 |
|
} Rule; |
| 112 |
|
- |
|
| 113 |
|
- |
typedef struct { |
| 114 |
|
- |
regex_t *propregex; |
| 115 |
|
- |
regex_t *tagregex; |
| 116 |
|
- |
} Regs; |
| 117 |
112 |
|
|
| 118 |
113 |
|
struct View { |
| 119 |
114 |
|
int id; |
|
| 132 |
127 |
|
void buttonpress(XEvent *e); |
| 133 |
128 |
|
void checkotherwm(void); |
| 134 |
129 |
|
void cleanup(void); |
| 135 |
|
- |
void compileregs(void); |
| 136 |
130 |
|
void configure(Client *c); |
| 137 |
131 |
|
void configurenotify(XEvent *e); |
| 138 |
132 |
|
void configurerequest(XEvent *e); |
|
| 210 |
204 |
|
void selectview(const char *arg); |
| 211 |
205 |
|
|
| 212 |
206 |
|
/* variables */ |
| 213 |
|
- |
char stext[256]; |
|
207 |
+ |
char stext[256], buf[256]; |
| 214 |
208 |
|
int nviews = 1; |
| 215 |
209 |
|
View *selview; |
| 216 |
210 |
|
int screen; |
|
| 246 |
240 |
|
Cursor cursor[CurLast]; |
| 247 |
241 |
|
Display *dpy; |
| 248 |
242 |
|
DC dc = {0}; |
| 249 |
|
- |
Regs *regs = NULL; |
| 250 |
243 |
|
View *views; |
| 251 |
244 |
|
Window root; |
| 252 |
245 |
|
|
|
| 256 |
249 |
|
/* function implementations */ |
| 257 |
250 |
|
void |
| 258 |
251 |
|
applyrules(Client *c) { |
| 259 |
|
- |
static char buf[512]; |
| 260 |
|
- |
unsigned int i, j; |
| 261 |
|
- |
regmatch_t tmp; |
|
252 |
+ |
unsigned int i; |
| 262 |
253 |
|
Bool matched_tag = False; |
|
254 |
+ |
Rule *r; |
| 263 |
255 |
|
XClassHint ch = { 0 }; |
| 264 |
256 |
|
|
| 265 |
257 |
|
/* rule matching */ |
|
| 267 |
259 |
|
snprintf(buf, sizeof buf, "%s:%s:%s", |
| 268 |
260 |
|
ch.res_class ? ch.res_class : "", |
| 269 |
261 |
|
ch.res_name ? ch.res_name : "", c->name); |
| 270 |
|
- |
for(i = 0; i < LENGTH(rules); i++) |
| 271 |
|
- |
if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { |
| 272 |
|
- |
c->isfloating = rules[i].isfloating; |
| 273 |
|
- |
for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { |
| 274 |
|
- |
if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
| 275 |
|
- |
matched_tag = True; |
| 276 |
|
- |
c->tags[j] = selview->id; |
| 277 |
|
- |
} |
|
262 |
+ |
for(i = 0; i < LENGTH(rules); i++) { |
|
263 |
+ |
r = &rules[i]; |
|
264 |
+ |
if(strstr(c->name, r->prop) |
|
265 |
+ |
|| (ch.res_class && strstr(ch.res_class, r->prop)) |
|
266 |
+ |
|| (ch.res_name && strstr(ch.res_name, r->prop))) |
|
267 |
+ |
{ |
|
268 |
+ |
c->isfloating = r->isfloating; |
|
269 |
+ |
if(r->tag) { |
|
270 |
+ |
matched_tag = True; |
|
271 |
+ |
c->tags[idxoftag(r->tag)] = selview->id; |
| 278 |
272 |
|
} |
| 279 |
273 |
|
} |
|
274 |
+ |
} |
| 280 |
275 |
|
if(ch.res_class) |
| 281 |
276 |
|
XFree(ch.res_class); |
| 282 |
277 |
|
if(ch.res_name) |
|
| 421 |
416 |
|
} |
| 422 |
417 |
|
|
| 423 |
418 |
|
void |
| 424 |
|
- |
compileregs(void) { |
| 425 |
|
- |
unsigned int i; |
| 426 |
|
- |
regex_t *reg; |
| 427 |
|
- |
|
| 428 |
|
- |
if(regs) |
| 429 |
|
- |
return; |
| 430 |
|
- |
regs = emallocz(LENGTH(rules) * sizeof(Regs)); |
| 431 |
|
- |
for(i = 0; i < LENGTH(rules); i++) { |
| 432 |
|
- |
if(rules[i].prop) { |
| 433 |
|
- |
reg = emallocz(sizeof(regex_t)); |
| 434 |
|
- |
if(regcomp(reg, rules[i].prop, REG_EXTENDED)) |
| 435 |
|
- |
free(reg); |
| 436 |
|
- |
else |
| 437 |
|
- |
regs[i].propregex = reg; |
| 438 |
|
- |
} |
| 439 |
|
- |
if(rules[i].tags) { |
| 440 |
|
- |
reg = emallocz(sizeof(regex_t)); |
| 441 |
|
- |
if(regcomp(reg, rules[i].tags, REG_EXTENDED)) |
| 442 |
|
- |
free(reg); |
| 443 |
|
- |
else |
| 444 |
|
- |
regs[i].tagregex = reg; |
| 445 |
|
- |
} |
| 446 |
|
- |
} |
| 447 |
|
- |
} |
| 448 |
|
- |
|
| 449 |
|
- |
void |
| 450 |
419 |
|
configure(Client *c) { |
| 451 |
420 |
|
XConfigureEvent ce; |
| 452 |
421 |
|
|
|
| 624 |
593 |
|
void |
| 625 |
594 |
|
drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) { |
| 626 |
595 |
|
int x, y, w, h; |
| 627 |
|
- |
static char buf[256]; |
| 628 |
596 |
|
unsigned int len, olen; |
| 629 |
597 |
|
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
| 630 |
598 |
|
|
|
| 1147 |
1115 |
|
manage(ev->window, &wa); |
| 1148 |
1116 |
|
} |
| 1149 |
1117 |
|
|
| 1150 |
|
- |
View * |
| 1151 |
|
- |
viewat() { |
| 1152 |
|
- |
int i, x, y; |
| 1153 |
|
- |
Window win; |
| 1154 |
|
- |
unsigned int mask; |
| 1155 |
|
- |
|
| 1156 |
|
- |
XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); |
| 1157 |
|
- |
for(i = 0; i < nviews; i++) { |
| 1158 |
|
- |
if((x >= views[i].x && x < views[i].x + views[i].w) |
| 1159 |
|
- |
&& (y >= views[i].y && y < views[i].y + views[i].h)) |
| 1160 |
|
- |
return &views[i]; |
| 1161 |
|
- |
} |
| 1162 |
|
- |
return NULL; |
| 1163 |
|
- |
} |
| 1164 |
|
- |
|
| 1165 |
1118 |
|
void |
| 1166 |
1119 |
|
movemouse(Client *c) { |
| 1167 |
1120 |
|
int x1, y1, ocx, ocy, di, nx, ny; |
|
| 1406 |
1359 |
|
void |
| 1407 |
1360 |
|
run(void) { |
| 1408 |
1361 |
|
char *p; |
| 1409 |
|
- |
char buf[sizeof stext]; |
|
1362 |
+ |
char sbuf[sizeof stext]; |
| 1410 |
1363 |
|
fd_set rd; |
| 1411 |
1364 |
|
int r, xfd; |
| 1412 |
1365 |
|
unsigned int len, offset; |
|
| 1418 |
1371 |
|
readin = True; |
| 1419 |
1372 |
|
offset = 0; |
| 1420 |
1373 |
|
len = sizeof stext - 1; |
| 1421 |
|
- |
buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */ |
|
1374 |
+ |
sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */ |
| 1422 |
1375 |
|
while(running) { |
| 1423 |
1376 |
|
FD_ZERO(&rd); |
| 1424 |
1377 |
|
if(readin) |
|
| 1430 |
1383 |
|
eprint("select failed\n"); |
| 1431 |
1384 |
|
} |
| 1432 |
1385 |
|
if(FD_ISSET(STDIN_FILENO, &rd)) { |
| 1433 |
|
- |
switch((r = read(STDIN_FILENO, buf + offset, len - offset))) { |
|
1386 |
+ |
switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) { |
| 1434 |
1387 |
|
case -1: |
| 1435 |
1388 |
|
strncpy(stext, strerror(errno), len); |
| 1436 |
1389 |
|
readin = False; |
|
| 1440 |
1393 |
|
readin = False; |
| 1441 |
1394 |
|
break; |
| 1442 |
1395 |
|
default: |
| 1443 |
|
- |
for(p = buf + offset; r > 0; p++, r--, offset++) |
|
1396 |
+ |
for(p = sbuf + offset; r > 0; p++, r--, offset++) |
| 1444 |
1397 |
|
if(*p == '\n' || *p == '\0') { |
| 1445 |
1398 |
|
*p = '\0'; |
| 1446 |
|
- |
strncpy(stext, buf, len); |
| 1447 |
|
- |
p += r - 1; /* p is buf + offset + r - 1 */ |
|
1399 |
+ |
strncpy(stext, sbuf, len); |
|
1400 |
+ |
p += r - 1; /* p is sbuf + offset + r - 1 */ |
| 1448 |
1401 |
|
for(r = 0; *(p - r) && *(p - r) != '\n'; r++); |
| 1449 |
1402 |
|
offset = r; |
| 1450 |
1403 |
|
if(r) |
| 1451 |
|
- |
memmove(buf, p - r + 1, r); |
|
1404 |
+ |
memmove(sbuf, p - r + 1, r); |
| 1452 |
1405 |
|
break; |
| 1453 |
1406 |
|
} |
| 1454 |
1407 |
|
break; |
|
| 1665 |
1618 |
|
|
| 1666 |
1619 |
|
/* grab keys */ |
| 1667 |
1620 |
|
grabkeys(); |
| 1668 |
|
- |
|
| 1669 |
|
- |
/* init tags */ |
| 1670 |
|
- |
compileregs(); |
| 1671 |
1621 |
|
|
| 1672 |
1622 |
|
selview = &views[0]; |
| 1673 |
1623 |
|
} |
|
| 1950 |
1900 |
|
} |
| 1951 |
1901 |
|
} |
| 1952 |
1902 |
|
|
|
1903 |
+ |
void |
|
1904 |
+ |
view(const char *arg) { |
|
1905 |
+ |
unsigned int i; |
|
1906 |
+ |
int tmp[LENGTH(tags)]; |
|
1907 |
+ |
|
|
1908 |
+ |
for(i = 0; i < LENGTH(tags); i++) |
|
1909 |
+ |
tmp[i] = (NULL == arg) ? selview->id : 0; |
|
1910 |
+ |
tmp[idxoftag(arg)] = selview->id; |
|
1911 |
+ |
if(memcmp(seltags, tmp, sizeof initags) != 0) { |
|
1912 |
+ |
memcpy(prevtags, seltags, sizeof initags); |
|
1913 |
+ |
memcpy(seltags, tmp, sizeof initags); |
|
1914 |
+ |
arrange(); |
|
1915 |
+ |
} |
|
1916 |
+ |
} |
|
1917 |
+ |
|
|
1918 |
+ |
View * |
|
1919 |
+ |
viewat() { |
|
1920 |
+ |
int i, x, y; |
|
1921 |
+ |
Window win; |
|
1922 |
+ |
unsigned int mask; |
|
1923 |
+ |
|
|
1924 |
+ |
XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); |
|
1925 |
+ |
for(i = 0; i < nviews; i++) { |
|
1926 |
+ |
if((x >= views[i].x && x < views[i].x + views[i].w) |
|
1927 |
+ |
&& (y >= views[i].y && y < views[i].y + views[i].h)) |
|
1928 |
+ |
return &views[i]; |
|
1929 |
+ |
} |
|
1930 |
+ |
return NULL; |
|
1931 |
+ |
} |
|
1932 |
+ |
|
|
1933 |
+ |
void |
|
1934 |
+ |
viewprevtag(const char *arg) { |
|
1935 |
+ |
static Bool tmp[LENGTH(tags)]; |
|
1936 |
+ |
|
|
1937 |
+ |
memcpy(tmp, seltags, sizeof initags); |
|
1938 |
+ |
memcpy(seltags, prevtags, sizeof initags); |
|
1939 |
+ |
memcpy(prevtags, tmp, sizeof initags); |
|
1940 |
+ |
arrange(); |
|
1941 |
+ |
} |
|
1942 |
+ |
|
| 1953 |
1943 |
|
/* There's no way to check accesses to destroyed windows, thus those cases are |
| 1954 |
1944 |
|
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
| 1955 |
1945 |
|
* default error handler, which may call exit. */ |
|
| 1983 |
1973 |
|
} |
| 1984 |
1974 |
|
|
| 1985 |
1975 |
|
void |
| 1986 |
|
- |
view(const char *arg) { |
| 1987 |
|
- |
unsigned int i; |
| 1988 |
|
- |
int tmp[LENGTH(tags)]; |
| 1989 |
|
- |
|
| 1990 |
|
- |
for(i = 0; i < LENGTH(tags); i++) |
| 1991 |
|
- |
tmp[i] = (NULL == arg) ? selview->id : 0; |
| 1992 |
|
- |
tmp[idxoftag(arg)] = selview->id; |
| 1993 |
|
- |
if(memcmp(seltags, tmp, sizeof initags) != 0) { |
| 1994 |
|
- |
memcpy(prevtags, seltags, sizeof initags); |
| 1995 |
|
- |
memcpy(seltags, tmp, sizeof initags); |
| 1996 |
|
- |
arrange(); |
| 1997 |
|
- |
} |
| 1998 |
|
- |
} |
| 1999 |
|
- |
|
| 2000 |
|
- |
void |
| 2001 |
|
- |
viewprevtag(const char *arg) { |
| 2002 |
|
- |
static Bool tmp[LENGTH(tags)]; |
| 2003 |
|
- |
|
| 2004 |
|
- |
memcpy(tmp, seltags, sizeof initags); |
| 2005 |
|
- |
memcpy(seltags, prevtags, sizeof initags); |
| 2006 |
|
- |
memcpy(prevtags, tmp, sizeof initags); |
| 2007 |
|
- |
arrange(); |
| 2008 |
|
- |
} |
| 2009 |
|
- |
|
| 2010 |
|
- |
void |
| 2011 |
1976 |
|
zoom(const char *arg) { |
| 2012 |
1977 |
|
Client *c = sel; |
| 2013 |
1978 |
|
|
|
| 2021 |
1986 |
|
focus(c); |
| 2022 |
1987 |
|
arrange(); |
| 2023 |
1988 |
|
} |
| 2024 |
|
- |
|
| 2025 |
|
- |
void |
| 2026 |
|
- |
selectview(const char *arg) { |
| 2027 |
|
- |
int i; |
| 2028 |
|
- |
View *v; |
| 2029 |
|
- |
|
| 2030 |
|
- |
if(!arg) |
| 2031 |
|
- |
return; |
| 2032 |
|
- |
if(arg) |
| 2033 |
|
- |
i = atoi(arg); |
| 2034 |
|
- |
v = &views[i % nviews]; |
| 2035 |
|
- |
XWarpPointer(dpy, None, root, 0, 0, 0, 0, v->wax+v->waw/2, v->way+v->wah/2); |
| 2036 |
|
- |
focus(NULL); |
| 2037 |
|
- |
} |
| 2038 |
|
- |
|
| 2039 |
1989 |
|
|
| 2040 |
1990 |
|
int |
| 2041 |
1991 |
|
main(int argc, char *argv[]) { |