X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=dwm.c;h=87bc1d2d23a4cac6be2bbdea77b234ed7f515e14;hb=2f70a14ee12bad6bf8dd5aa5489d88cddfaa3b06;hp=3a789d9499acd6b462bd45c3c2f48d9abc1027dd;hpb=2bfd3fffbf5c913acfb7f56bdd7a29dc39d6d5d5;p=dwm.git diff --git a/dwm.c b/dwm.c index 3a789d9..87bc1d2 100644 --- a/dwm.c +++ b/dwm.c @@ -67,10 +67,11 @@ struct Client { int x, y, w, h; int basew, baseh, incw, inch, maxw, maxh, minw, minh; int minax, maxax, minay, maxay; - int *tags; long flags; unsigned int border, oldborder; Bool isbanned, isfixed, isfloating, isurgent; + Bool *tags; + View *view; Client *next; Client *prev; Client *snext; @@ -106,17 +107,12 @@ typedef struct { typedef struct { const char *prop; - const char *tags; + const char *tag; Bool isfloating; } Rule; -typedef struct { - regex_t *propregex; - regex_t *tagregex; -} Regs; - struct View { - int id; + unsigned int id; int x, y, w, h, wax, way, wah, waw; double mwfact; Layout *layout; @@ -124,6 +120,7 @@ struct View { }; /* function declarations */ +void addtag(Client *c, const char *t); void applyrules(Client *c); void arrange(void); void attach(Client *c); @@ -132,7 +129,6 @@ void ban(Client *c); void buttonpress(XEvent *e); void checkotherwm(void); void cleanup(void); -void compileregs(void); void configure(Client *c); void configurenotify(XEvent *e); void configurerequest(XEvent *e); @@ -140,8 +136,8 @@ void destroynotify(XEvent *e); void detach(Client *c); void detachstack(Client *c); void drawbar(View *v); -void drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); -void drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert); +void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); +void drawtext(const char *text, unsigned long col[ColLast], Bool invert); void *emallocz(unsigned int size); void enternotify(XEvent *e); void eprint(const char *errstr, ...); @@ -154,12 +150,11 @@ void focusprev(const char *arg); Client *getclient(Window w); unsigned long getcolor(const char *colstr); View *getviewbar(Window barwin); -View *getview(Client *c); long getstate(Window w); Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); void grabbuttons(Client *c, Bool focused); void grabkeys(void); -unsigned int idxoftag(const char *tag); +unsigned int idxoftag(const char *t); void initfont(const char *fontstr); Bool isoccupied(unsigned int t); Bool isprotodel(Client *c); @@ -210,12 +205,9 @@ void zoom(const char *arg); void selectview(const char *arg); /* variables */ -char stext[256]; +char stext[256], buf[256]; int nviews = 1; -View *selview; int screen; -int *seltags; -int *prevtags; int (*xerrorxlib)(Display *, XErrorEvent *); unsigned int bh, bpos; unsigned int blw = 0; @@ -240,14 +232,16 @@ Bool domwfact = True; Bool dozoom = True; Bool otherwm, readin; Bool running = True; +Bool *prevtags; +Bool *seltags; Client *clients = NULL; Client *sel = NULL; Client *stack = NULL; Cursor cursor[CurLast]; Display *dpy; DC dc = {0}; -Regs *regs = NULL; View *views; +View *selview; Window root; /* configuration, allows nested code to access above variables */ @@ -255,34 +249,46 @@ Window root; /* function implementations */ void +addtag(Client *c, const char *t) { + unsigned int i, tidx = idxoftag(t); + + for(i = 0; i < LENGTH(tags); i++) + if(c->tags[i] && vtags[i] != vtags[tidx]) + return; /* conflict */ + c->tags[tidx] = True; + c->view = &views[vtags[tidx]]; +} + +void applyrules(Client *c) { - static char buf[512]; - unsigned int i, j; - regmatch_t tmp; - Bool matched_tag = False; + unsigned int i; + Bool matched = False; + Rule *r; XClassHint ch = { 0 }; /* rule matching */ XGetClassHint(dpy, c->win, &ch); - snprintf(buf, sizeof buf, "%s:%s:%s", - ch.res_class ? ch.res_class : "", - ch.res_name ? ch.res_name : "", c->name); - for(i = 0; i < LENGTH(rules); i++) - if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { - c->isfloating = rules[i].isfloating; - for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { - if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { - matched_tag = True; - c->tags[j] = selview->id; - } + for(i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if(strstr(c->name, r->prop) + || (ch.res_class && strstr(ch.res_class, r->prop)) + || (ch.res_name && strstr(ch.res_name, r->prop))) + { + c->isfloating = r->isfloating; + if(r->tag) { + addtag(c, r->tag); + matched = True; } } + } if(ch.res_class) XFree(ch.res_class); if(ch.res_name) XFree(ch.res_name); - if(!matched_tag) + if(!matched) { memcpy(c->tags, seltags, sizeof initags); + c->view = selview; + } } @@ -323,7 +329,7 @@ void ban(Client *c) { if(c->isbanned) return; - XMoveWindow(dpy, c->win, c->x + 3 * getview(c)->w, c->y); + XMoveWindow(dpy, c->win, c->x + 3 * c->view->w, c->y); c->isbanned = True; } @@ -333,9 +339,7 @@ buttonpress(XEvent *e) { Client *c; XButtonPressedEvent *ev = &e->xbutton; - View *v = selview; - - if(ev->window == v->barwin) { + if(ev->window == selview->barwin) { x = 0; for(i = 0; i < LENGTH(tags); i++) { x += textw(tags[i]); @@ -363,17 +367,17 @@ buttonpress(XEvent *e) { if(CLEANMASK(ev->state) != MODKEY) return; if(ev->button == Button1) { - restack(getview(c)); + restack(c->view); movemouse(c); } else if(ev->button == Button2) { - if((floating != v->layout->arrange) && c->isfloating) + if((floating != c->view->layout->arrange) && c->isfloating) togglefloating(NULL); else zoom(NULL); } else if(ev->button == Button3 && !c->isfixed) { - restack(getview(c)); + restack(c->view); resizemouse(c); } } @@ -421,32 +425,6 @@ cleanup(void) { } void -compileregs(void) { - unsigned int i; - regex_t *reg; - - if(regs) - return; - regs = emallocz(LENGTH(rules) * sizeof(Regs)); - for(i = 0; i < LENGTH(rules); i++) { - if(rules[i].prop) { - reg = emallocz(sizeof(regex_t)); - if(regcomp(reg, rules[i].prop, REG_EXTENDED)) - free(reg); - else - regs[i].propregex = reg; - } - if(rules[i].tags) { - reg = emallocz(sizeof(regex_t)); - if(regcomp(reg, rules[i].tags, REG_EXTENDED)) - free(reg); - else - regs[i].tagregex = reg; - } - } -} - -void configure(Client *c) { XConfigureEvent ce; @@ -476,7 +454,7 @@ configurenotify(XEvent *e) { XFreePixmap(dpy, dc.drawable); dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(root, screen), bh, DefaultDepth(dpy, screen)); XResizeWindow(dpy, v->barwin, v->w, bh); - updatebarpos(v); + updatebarpos(selview); arrange(); } } @@ -488,7 +466,7 @@ configurerequest(XEvent *e) { XWindowChanges wc; if((c = getclient(ev->window))) { - View *v = getview(c); + View *v = c->view; if(ev->value_mask & CWBorderWidth) c->border = ev->border_width; if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) { @@ -560,21 +538,23 @@ drawbar(View *v) { Client *c; dc.x = 0; - for(c = stack; c && (!isvisible(c) || getview(c) != v); c = c->snext); + for(c = stack; c && (!isvisible(c) || c->view != v); c = c->snext); for(i = 0; i < LENGTH(tags); i++) { + if(&views[vtags[i]] != v) + continue; dc.w = textw(tags[i]); - if(seltags[i] && seltags[i] == v->id) { - drawtext(v, tags[i], dc.sel, isurgent(i)); - drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); + if(seltags[i]) { + drawtext(tags[i], dc.sel, isurgent(i)); + drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); } else { - drawtext(v, tags[i], dc.norm, isurgent(i)); - drawsquare(v, c && c->tags[i], isoccupied(i), isurgent(i), dc.norm); + drawtext(tags[i], dc.norm, isurgent(i)); + drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.norm); } dc.x += dc.w; } dc.w = blw; - drawtext(v, v->layout->symbol, dc.norm, False); + drawtext(v->layout->symbol, dc.norm, False); x = dc.x + dc.w; if(v == selview) { dc.w = textw(stext); @@ -583,25 +563,25 @@ drawbar(View *v) { dc.x = x; dc.w = v->w - x; } - drawtext(v, stext, dc.norm, False); + drawtext(stext, dc.norm, False); } else dc.x = v->w; if((dc.w = dc.x - x) > bh) { dc.x = x; if(c) { - drawtext(v, c->name, dc.sel, False); - drawsquare(v, False, c->isfloating, False, dc.sel); + drawtext(c->name, dc.sel, False); + drawsquare(False, c->isfloating, False, dc.sel); } else - drawtext(v, NULL, dc.norm, False); + drawtext(NULL, dc.norm, False); } XCopyArea(dpy, dc.drawable, v->barwin, dc.gc, 0, 0, v->w, bh, 0, 0); XSync(dpy, False); } void -drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { +drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; XGCValues gcv; XRectangle r = { dc.x, dc.y, dc.w, dc.h }; @@ -622,9 +602,8 @@ drawsquare(View *v, Bool filled, Bool empty, Bool invert, unsigned long col[ColL } void -drawtext(View *v, const char *text, unsigned long col[ColLast], Bool invert) { +drawtext(const char *text, unsigned long col[ColLast], Bool invert) { int x, y, w, h; - static char buf[256]; unsigned int len, olen; XRectangle r = { dc.x, dc.y, dc.w, dc.h }; @@ -700,7 +679,7 @@ expose(XEvent *e) { View *v; XExposeEvent *ev = &e->xexpose; - if(ev->count == 0 && (v = getviewbar(ev->window))) + if(ev->count == 0 && ((v = getviewbar(ev->window)))) drawbar(v); } @@ -718,13 +697,13 @@ void focus(Client *c) { View *v = selview; if(c) - selview = getview(c); + selview = c->view; else selview = viewat(); if(selview != v) drawbar(v); if(!c || (c && !isvisible(c))) - for(c = stack; c && (!isvisible(c) || getview(c) != selview); c = c->snext); + for(c = stack; c && (!isvisible(c) || c->view != selview); c = c->snext); if(sel && sel != c) { grabbuttons(sel, False); XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); @@ -738,7 +717,7 @@ focus(Client *c) { if(c) { XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - selview = getview(c); + selview = c->view; } else XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -764,7 +743,7 @@ focusnext(const char *arg) { for(c = clients; c && !isvisible(c); c = c->next); if(c) { focus(c); - restack(getview(c)); + restack(c->view); } } @@ -781,7 +760,7 @@ focusprev(const char *arg) { } if(c) { focus(c); - restack(getview(c)); + restack(c->view); } } @@ -813,16 +792,6 @@ getviewbar(Window barwin) { return NULL; } -View * -getview(Client *c) { - unsigned int i; - - for(i = 0; i < LENGTH(tags); i++) - if(c->tags[i]) - return &views[c->tags[i] - 1]; - return &views[0]; /* fallback */ -} - long getstate(Window w) { int format, status; @@ -934,10 +903,10 @@ grabkeys(void) { } unsigned int -idxoftag(const char *tag) { +idxoftag(const char *t) { unsigned int i; - for(i = 0; (i < LENGTH(tags)) && (tags[i] != tag); i++); + for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++); return (i < LENGTH(tags)) ? i : 0; } @@ -1078,7 +1047,7 @@ manage(Window w, XWindowAttributes *wa) { applyrules(c); - v = getview(c); + v = c->view; c->x = wa->x + v->x; c->y = wa->y + v->y; @@ -1147,21 +1116,6 @@ maprequest(XEvent *e) { manage(ev->window, &wa); } -View * -viewat() { - int i, x, y; - Window win; - unsigned int mask; - - XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); - for(i = 0; i < nviews; i++) { - if((x >= views[i].x && x < views[i].x + views[i].w) - && (y >= views[i].y && y < views[i].y + views[i].h)) - return &views[i]; - } - return NULL; -} - void movemouse(Client *c) { int x1, y1, ocx, ocy, di, nx, ny; @@ -1172,7 +1126,7 @@ movemouse(Client *c) { ocx = nx = c->x; ocy = ny = c->y; - v = getview(c); + v = c->view; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurMove], CurrentTime) != GrabSuccess) return; @@ -1211,7 +1165,7 @@ movemouse(Client *c) { Client * nexttiled(Client *c, View *v) { - for(; c && (c->isfloating || getview(c) != v || !isvisible(c)); c = c->next); + for(; c && (c->isfloating || c->view != v || !isvisible(c)); c = c->next); return c; } @@ -1236,7 +1190,7 @@ propertynotify(XEvent *e) { break; case XA_WM_HINTS: updatewmhints(c); - drawbar(getview(c)); + drawbar(c->view); break; } if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { @@ -1269,7 +1223,7 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { View *v; XWindowChanges wc; - v = getview(c); + v = c->view; if(sizehints) { /* set minimum possible */ if (w < 1) @@ -1340,7 +1294,7 @@ resizemouse(Client *c) { ocx = c->x; ocy = c->y; - v = getview(c); + v = c->view; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurResize], CurrentTime) != GrabSuccess) return; @@ -1406,7 +1360,7 @@ restack(View *v) { void run(void) { char *p; - char buf[sizeof stext]; + char sbuf[sizeof stext]; fd_set rd; int r, xfd; unsigned int len, offset; @@ -1418,7 +1372,7 @@ run(void) { readin = True; offset = 0; len = sizeof stext - 1; - buf[len] = stext[len] = '\0'; /* 0-terminator is never touched */ + sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */ while(running) { FD_ZERO(&rd); if(readin) @@ -1430,7 +1384,7 @@ run(void) { eprint("select failed\n"); } if(FD_ISSET(STDIN_FILENO, &rd)) { - switch((r = read(STDIN_FILENO, buf + offset, len - offset))) { + switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) { case -1: strncpy(stext, strerror(errno), len); readin = False; @@ -1440,15 +1394,15 @@ run(void) { readin = False; break; default: - for(p = buf + offset; r > 0; p++, r--, offset++) + for(p = sbuf + offset; r > 0; p++, r--, offset++) if(*p == '\n' || *p == '\0') { *p = '\0'; - strncpy(stext, buf, len); - p += r - 1; /* p is buf + offset + r - 1 */ + strncpy(stext, sbuf, len); + p += r - 1; /* p is sbuf + offset + r - 1 */ for(r = 0; *(p - r) && *(p - r) != '\n'; r++); offset = r; if(r) - memmove(buf, p - r + 1, r); + memmove(sbuf, p - r + 1, r); break; } break; @@ -1519,13 +1473,12 @@ setlayout(const char *arg) { if(sel) arrange(); else - drawbar(v); + drawbar(selview); } void setmwfact(const char *arg) { double delta; - View *v = selview; if(!domwfact) @@ -1572,7 +1525,7 @@ setup(void) { isxinerama = True; nviews = 2; /* aim Xinerama */ #endif - selview = views = emallocz(nviews * sizeof(View)); + views = emallocz(nviews * sizeof(View)); screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); @@ -1606,7 +1559,6 @@ nviews = 2; /* aim Xinerama */ for(i = 0; i < nviews; i++) { /* init geometry */ v = &views[i]; - v->id = i + 1; if(nviews != 1 && isxinerama) { @@ -1663,13 +1615,10 @@ v->h = DisplayHeight(dpy, screen); if(info) XFree(info); + selview = viewat(); + /* grab keys */ grabkeys(); - - /* init tags */ - compileregs(); - - selview = &views[0]; } void @@ -1703,8 +1652,8 @@ tag(const char *arg) { if(!sel) return; for(i = 0; i < LENGTH(tags); i++) - sel->tags[i] = (NULL == arg) ? selview->id : 0; - sel->tags[idxoftag(arg)] = selview->id; + sel->tags[i] = (NULL == arg); + sel->tags[idxoftag(arg)] = True; arrange(); } @@ -1800,7 +1749,7 @@ toggletag(const char *arg) { sel->tags[i] = !sel->tags[i]; for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++); if(j == LENGTH(tags)) - sel->tags[i] = selview->id; /* at least one tag must be enabled */ + sel->tags[i] = True; /* at least one tag must be enabled */ arrange(); } @@ -1812,7 +1761,7 @@ toggleview(const char *arg) { seltags[i] = !seltags[i]; for(j = 0; j < LENGTH(tags) && !seltags[j]; j++); if(j == LENGTH(tags)) - seltags[i] = selview->id; /* at least one tag must be viewed */ + seltags[i] = True; /* at least one tag must be viewed */ arrange(); } @@ -1950,6 +1899,47 @@ updatewmhints(Client *c) { } } +void +view(const char *arg) { + unsigned int i; + Bool tmp[LENGTH(tags)]; + + for(i = 0; i < LENGTH(tags); i++) + tmp[i] = (NULL == arg); + tmp[idxoftag(arg)] = True; + + if(memcmp(seltags, tmp, sizeof initags) != 0) { + memcpy(prevtags, seltags, sizeof initags); + memcpy(seltags, tmp, sizeof initags); + arrange(); + } +} + +View * +viewat() { + int i, x, y; + Window win; + unsigned int mask; + + XQueryPointer(dpy, root, &win, &win, &x, &y, &i, &i, &mask); + for(i = 0; i < nviews; i++) { + if((x >= views[i].x && x < views[i].x + views[i].w) + && (y >= views[i].y && y < views[i].y + views[i].h)) + return &views[i]; + } + return NULL; +} + +void +viewprevtag(const char *arg) { + static Bool tmp[LENGTH(tags)]; + + memcpy(tmp, seltags, sizeof initags); + memcpy(seltags, prevtags, sizeof initags); + memcpy(prevtags, tmp, sizeof initags); + arrange(); +} + /* There's no way to check accesses to destroyed windows, thus those cases are * ignored (especially on UnmapNotify's). Other types of errors call Xlibs * default error handler, which may call exit. */ @@ -1983,38 +1973,13 @@ xerrorstart(Display *dpy, XErrorEvent *ee) { } void -view(const char *arg) { - unsigned int i; - int tmp[LENGTH(tags)]; - - for(i = 0; i < LENGTH(tags); i++) - tmp[i] = (NULL == arg) ? selview->id : 0; - tmp[idxoftag(arg)] = selview->id; - if(memcmp(seltags, tmp, sizeof initags) != 0) { - memcpy(prevtags, seltags, sizeof initags); - memcpy(seltags, tmp, sizeof initags); - arrange(); - } -} - -void -viewprevtag(const char *arg) { - static Bool tmp[LENGTH(tags)]; - - memcpy(tmp, seltags, sizeof initags); - memcpy(seltags, prevtags, sizeof initags); - memcpy(prevtags, tmp, sizeof initags); - arrange(); -} - -void zoom(const char *arg) { Client *c = sel; if(!sel || !dozoom || sel->isfloating) return; - if(c == nexttiled(clients, getview(c))) - if(!(c = nexttiled(c->next, getview(c)))) + if(c == nexttiled(clients, c->view)) + if(!(c = nexttiled(c->next, c->view))) return; detach(c); attach(c); @@ -2022,21 +1987,6 @@ zoom(const char *arg) { arrange(); } -void -selectview(const char *arg) { - int i; - View *v; - - if(!arg) - return; - if(arg) - i = atoi(arg); - v = &views[i % nviews]; - XWarpPointer(dpy, None, root, 0, 0, 0, 0, v->wax+v->waw/2, v->way+v->wah/2); - focus(NULL); -} - - int main(int argc, char *argv[]) { if(argc == 2 && !strcmp("-v", argv[1]))