130 void attachstack(Client *c); |
125 void attachstack(Client *c); |
131 void ban(Client *c); |
126 void ban(Client *c); |
132 void buttonpress(XEvent *e); |
127 void buttonpress(XEvent *e); |
133 void checkotherwm(void); |
128 void checkotherwm(void); |
134 void cleanup(void); |
129 void cleanup(void); |
135 void compileregs(void); |
|
136 void configure(Client *c); |
130 void configure(Client *c); |
137 void configurenotify(XEvent *e); |
131 void configurenotify(XEvent *e); |
138 void configurerequest(XEvent *e); |
132 void configurerequest(XEvent *e); |
139 void destroynotify(XEvent *e); |
133 void destroynotify(XEvent *e); |
140 void detach(Client *c); |
134 void detach(Client *c); |
244 Client *sel = NULL; |
238 Client *sel = NULL; |
245 Client *stack = NULL; |
239 Client *stack = NULL; |
246 Cursor cursor[CurLast]; |
240 Cursor cursor[CurLast]; |
247 Display *dpy; |
241 Display *dpy; |
248 DC dc = {0}; |
242 DC dc = {0}; |
249 Regs *regs = NULL; |
|
250 View *views; |
243 View *views; |
251 Window root; |
244 Window root; |
252 |
245 |
253 /* configuration, allows nested code to access above variables */ |
246 /* configuration, allows nested code to access above variables */ |
254 #include "config.h" |
247 #include "config.h" |
255 |
248 |
256 /* function implementations */ |
249 /* function implementations */ |
257 void |
250 void |
258 applyrules(Client *c) { |
251 applyrules(Client *c) { |
259 static char buf[512]; |
252 unsigned int i; |
260 unsigned int i, j; |
|
261 regmatch_t tmp; |
|
262 Bool matched_tag = False; |
253 Bool matched_tag = False; |
|
254 Rule *r; |
263 XClassHint ch = { 0 }; |
255 XClassHint ch = { 0 }; |
264 |
256 |
265 /* rule matching */ |
257 /* rule matching */ |
266 XGetClassHint(dpy, c->win, &ch); |
258 XGetClassHint(dpy, c->win, &ch); |
267 snprintf(buf, sizeof buf, "%s:%s:%s", |
259 snprintf(buf, sizeof buf, "%s:%s:%s", |
268 ch.res_class ? ch.res_class : "", |
260 ch.res_class ? ch.res_class : "", |
269 ch.res_name ? ch.res_name : "", c->name); |
261 ch.res_name ? ch.res_name : "", c->name); |
270 for(i = 0; i < LENGTH(rules); i++) |
262 for(i = 0; i < LENGTH(rules); i++) { |
271 if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { |
263 r = &rules[i]; |
272 c->isfloating = rules[i].isfloating; |
264 if(strstr(c->name, r->prop) |
273 for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { |
265 || (ch.res_class && strstr(ch.res_class, r->prop)) |
274 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
266 || (ch.res_name && strstr(ch.res_name, r->prop))) |
275 matched_tag = True; |
267 { |
276 c->tags[j] = selview->id; |
268 c->isfloating = r->isfloating; |
277 } |
269 if(r->tag) { |
|
270 matched_tag = True; |
|
271 c->tags[idxoftag(r->tag)] = selview->id; |
278 } |
272 } |
279 } |
273 } |
|
274 } |
280 if(ch.res_class) |
275 if(ch.res_class) |
281 XFree(ch.res_class); |
276 XFree(ch.res_class); |
282 if(ch.res_name) |
277 if(ch.res_name) |
283 XFree(ch.res_name); |
278 XFree(ch.res_name); |
284 if(!matched_tag) |
279 if(!matched_tag) |
416 XFreeCursor(dpy, cursor[CurMove]); |
411 XFreeCursor(dpy, cursor[CurMove]); |
417 for(i = 0; i < nviews; i++) |
412 for(i = 0; i < nviews; i++) |
418 XDestroyWindow(dpy, views[i].barwin); |
413 XDestroyWindow(dpy, views[i].barwin); |
419 XSync(dpy, False); |
414 XSync(dpy, False); |
420 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
415 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
421 } |
|
422 |
|
423 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 } |
416 } |
448 |
417 |
449 void |
418 void |
450 configure(Client *c) { |
419 configure(Client *c) { |
451 XConfigureEvent ce; |
420 XConfigureEvent ce; |
622 } |
591 } |
623 |
592 |
624 void |
593 void |
625 drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) { |
594 drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) { |
626 int x, y, w, h; |
595 int x, y, w, h; |
627 static char buf[256]; |
|
628 unsigned int len, olen; |
596 unsigned int len, olen; |
629 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
597 XRectangle r = { dc.x, dc.y, dc.w, dc.h }; |
630 |
598 |
631 XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); |
599 XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); |
632 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
600 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
1143 return; |
1111 return; |
1144 if(wa.override_redirect) |
1112 if(wa.override_redirect) |
1145 return; |
1113 return; |
1146 if(!getclient(ev->window)) |
1114 if(!getclient(ev->window)) |
1147 manage(ev->window, &wa); |
1115 manage(ev->window, &wa); |
1148 } |
|
1149 |
|
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 } |
1116 } |
1164 |
1117 |
1165 void |
1118 void |
1166 movemouse(Client *c) { |
1119 movemouse(Client *c) { |
1167 int x1, y1, ocx, ocy, di, nx, ny; |
1120 int x1, y1, ocx, ocy, di, nx, ny; |
1428 if(errno == EINTR) |
1381 if(errno == EINTR) |
1429 continue; |
1382 continue; |
1430 eprint("select failed\n"); |
1383 eprint("select failed\n"); |
1431 } |
1384 } |
1432 if(FD_ISSET(STDIN_FILENO, &rd)) { |
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 case -1: |
1387 case -1: |
1435 strncpy(stext, strerror(errno), len); |
1388 strncpy(stext, strerror(errno), len); |
1436 readin = False; |
1389 readin = False; |
1437 break; |
1390 break; |
1438 case 0: |
1391 case 0: |
1439 strncpy(stext, "EOF", 4); |
1392 strncpy(stext, "EOF", 4); |
1440 readin = False; |
1393 readin = False; |
1441 break; |
1394 break; |
1442 default: |
1395 default: |
1443 for(p = buf + offset; r > 0; p++, r--, offset++) |
1396 for(p = sbuf + offset; r > 0; p++, r--, offset++) |
1444 if(*p == '\n' || *p == '\0') { |
1397 if(*p == '\n' || *p == '\0') { |
1445 *p = '\0'; |
1398 *p = '\0'; |
1446 strncpy(stext, buf, len); |
1399 strncpy(stext, sbuf, len); |
1447 p += r - 1; /* p is buf + offset + r - 1 */ |
1400 p += r - 1; /* p is sbuf + offset + r - 1 */ |
1448 for(r = 0; *(p - r) && *(p - r) != '\n'; r++); |
1401 for(r = 0; *(p - r) && *(p - r) != '\n'; r++); |
1449 offset = r; |
1402 offset = r; |
1450 if(r) |
1403 if(r) |
1451 memmove(buf, p - r + 1, r); |
1404 memmove(sbuf, p - r + 1, r); |
1452 break; |
1405 break; |
1453 } |
1406 } |
1454 break; |
1407 break; |
1455 } |
1408 } |
1456 drawbar(selview); |
1409 drawbar(selview); |
1948 c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; |
1898 c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; |
1949 XFree(wmh); |
1899 XFree(wmh); |
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 /* There's no way to check accesses to destroyed windows, thus those cases are |
1943 /* There's no way to check accesses to destroyed windows, thus those cases are |
1954 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1944 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1955 * default error handler, which may call exit. */ |
1945 * default error handler, which may call exit. */ |
1956 int |
1946 int |
1957 xerror(Display *dpy, XErrorEvent *ee) { |
1947 xerror(Display *dpy, XErrorEvent *ee) { |
1981 otherwm = True; |
1971 otherwm = True; |
1982 return -1; |
1972 return -1; |
1983 } |
1973 } |
1984 |
1974 |
1985 void |
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 zoom(const char *arg) { |
1976 zoom(const char *arg) { |
2012 Client *c = sel; |
1977 Client *c = sel; |
2013 |
1978 |
2014 if(!sel || !dozoom || sel->isfloating) |
1979 if(!sel || !dozoom || sel->isfloating) |
2015 return; |
1980 return; |
2020 attach(c); |
1985 attach(c); |
2021 focus(c); |
1986 focus(c); |
2022 arrange(); |
1987 arrange(); |
2023 } |
1988 } |
2024 |
1989 |
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 |
|
2040 int |
1990 int |
2041 main(int argc, char *argv[]) { |
1991 main(int argc, char *argv[]) { |
2042 if(argc == 2 && !strcmp("-v", argv[1])) |
1992 if(argc == 2 && !strcmp("-v", argv[1])) |
2043 eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n"); |
1993 eprint("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n"); |
2044 else if(argc != 1) |
1994 else if(argc != 1) |