X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=dwm.c;h=421db610bed5a750ce16fc88ffb9a3bea8a10e8b;hb=da1b3fa4379acc7431eaee1331e755ef5335011b;hp=f4778476eb4ad19ba81f91f1b9df71eb5334645c;hpb=d5178292edebb0db2cf9f22aaf1a8effe7529aae;p=dwm.git diff --git a/dwm.c b/dwm.c index f477847..421db61 100644 --- a/dwm.c +++ b/dwm.c @@ -67,10 +67,10 @@ 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; Client *next; Client *prev; Client *snext; @@ -111,7 +111,7 @@ typedef struct { } Rule; struct View { - int id; + unsigned int id; int x, y, w, h, wax, way, wah, waw; double mwfact; Layout *layout; @@ -130,16 +130,18 @@ void cleanup(void); void configure(Client *c); void configurenotify(XEvent *e); void configurerequest(XEvent *e); +Bool conflicts(Client *c, unsigned int tidx); 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, ...); void expose(XEvent *e); +unsigned int firstag(View *v); void floating(View *v); /* default floating layout */ void focus(Client *c); void focusin(XEvent *e); @@ -147,13 +149,13 @@ void focusnext(const char *arg); void focusprev(const char *arg); Client *getclient(Window w); unsigned long getcolor(const char *colstr); -View *getviewbar(Window barwin); View *getview(Client *c); +View *getviewbar(Window barwin); 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); @@ -206,10 +208,7 @@ void selectview(const char *arg); /* variables */ 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; @@ -229,11 +228,12 @@ void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; Atom wmatom[WMLast], netatom[NetLast]; -Bool isxinerama = False; 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; @@ -241,24 +241,24 @@ Cursor cursor[CurLast]; Display *dpy; DC dc = {0}; View *views; +View *selview; Window root; /* configuration, allows nested code to access above variables */ #include "config.h" +#define TAGSZ (LENGTH(tags) * sizeof(Bool)) /* function implementations */ + void applyrules(Client *c) { - unsigned int i; - Bool matched_tag = False; + unsigned int i, idx; + 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++) { r = &rules[i]; if(strstr(c->name, r->prop) @@ -266,9 +266,9 @@ applyrules(Client *c) { || (ch.res_name && strstr(ch.res_name, r->prop))) { c->isfloating = r->isfloating; - if(r->tag) { - matched_tag = True; - c->tags[idxoftag(r->tag)] = selview->id; + if(r->tag && !conflicts(c, (idx = idxoftag(r->tag)))) { + c->tags[idx] = True; + matched = True; } } } @@ -276,12 +276,13 @@ applyrules(Client *c) { XFree(ch.res_class); if(ch.res_name) XFree(ch.res_name); - if(!matched_tag) - memcpy(c->tags, seltags, sizeof initags); + if(!matched) { + for(i = 0; i < LENGTH(tags); i++) + if(seltags[i] && vtags[i] == selview->id) + c->tags[i] = True; + } } - - void arrange(void) { unsigned int i; @@ -293,11 +294,11 @@ arrange(void) { else ban(c); + focus(NULL); for(i = 0; i < nviews; i++) { views[i].layout->arrange(&views[i]); restack(&views[i]); } - focus(NULL); } void @@ -328,11 +329,11 @@ 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++) { + if(&views[vtags[i]] != selview) + continue; x += textw(tags[i]); if(ev->x < x) { if(ev->button == Button1) { @@ -362,7 +363,7 @@ buttonpress(XEvent *e) { movemouse(c); } else if(ev->button == Button2) { - if((floating != v->layout->arrange) && c->isfloating) + if((floating != getview(c)->layout->arrange) && c->isfloating) togglefloating(NULL); else zoom(NULL); @@ -393,6 +394,7 @@ checkotherwm(void) { void cleanup(void) { unsigned int i; + close(STDIN_FILENO); while(stack) { unban(stack); @@ -445,7 +447,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(); } } @@ -495,6 +497,16 @@ configurerequest(XEvent *e) { XSync(dpy, False); } +Bool +conflicts(Client *c, unsigned int tidx) { + unsigned int i; + + for(i = 0; i < LENGTH(tags); i++) + if(c->tags[i] && vtags[i] != vtags[tidx]) + return True; /* conflict */ + return False; +} + void destroynotify(XEvent *e) { Client *c; @@ -531,19 +543,21 @@ drawbar(View *v) { dc.x = 0; for(c = stack; c && (!isvisible(c) || getview(c) != 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); @@ -552,25 +566,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 }; @@ -591,7 +605,7 @@ 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; unsigned int len, olen; XRectangle r = { dc.x, dc.y, dc.w, dc.h }; @@ -643,10 +657,8 @@ enternotify(XEvent *e) { Client *c; XCrossingEvent *ev = &e->xcrossing; - if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) { - if(!isxinerama || ev->window != root) - return; - } + if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; if((c = getclient(ev->window))) focus(c); else @@ -668,10 +680,20 @@ 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); } +unsigned int +firstag(View *v) { + unsigned int i; + + for(i = 0; i < LENGTH(tags); i++) + if(vtags[i] == v->id) + return i; + return 0; /* safe fallback */ +} + void floating(View *v) { /* default floating layout */ Client *c; @@ -685,13 +707,13 @@ floating(View *v) { /* default floating layout */ void focus(Client *c) { View *v = selview; + if(c) selview = getview(c); - else - selview = viewat(); if(selview != v) drawbar(v); if(!c || (c && !isvisible(c))) + /* TODO: isvisible might take getview(c) as constraint? */ for(c = stack; c && (!isvisible(c) || getview(c) != selview); c = c->snext); if(sel && sel != c) { grabbuttons(sel, False); @@ -772,23 +794,23 @@ getcolor(const char *colstr) { } View * -getviewbar(Window barwin) { +getview(Client *c) { unsigned int i; - for(i = 0; i < nviews; i++) - if(views[i].barwin == barwin) - return &views[i]; + for(i = 0; i < LENGTH(tags); i++) + if(c->tags[i]) + return &views[vtags[i]]; return NULL; } View * -getview(Client *c) { +getviewbar(Window barwin) { unsigned int i; - for(i = 0; i < LENGTH(tags); i++) - if(c->tags[i]) - return &views[c->tags[i] - 1]; - return &views[0]; /* fallback */ + for(i = 0; i < nviews; i++) + if(views[i].barwin == barwin) + return &views[i]; + return NULL; } long @@ -902,11 +924,11 @@ 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++); - return (i < LENGTH(tags)) ? i : 0; + for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++); + return (i < LENGTH(tags)) ? i : firstag(selview); } void @@ -1041,7 +1063,7 @@ manage(Window w, XWindowAttributes *wa) { XWindowChanges wc; c = emallocz(sizeof(Client)); - c->tags = emallocz(sizeof initags); + c->tags = emallocz(TAGSZ); c->win = w; applyrules(c); @@ -1081,7 +1103,7 @@ manage(Window w, XWindowAttributes *wa) { if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) for(t = clients; t && t->win != trans; t = t->next); if(t) - memcpy(c->tags, t->tags, sizeof initags); + memcpy(c->tags, t->tags, TAGSZ); if(!c->isfloating) c->isfloating = (rettrans == Success) || c->isfixed; attach(c); @@ -1472,13 +1494,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) @@ -1501,7 +1522,7 @@ setmwfact(const char *arg) { void setup(void) { - unsigned int i; + unsigned int i, j; View *v; XSetWindowAttributes wa; XineramaScreenInfo *info = NULL; @@ -1519,13 +1540,13 @@ setup(void) { cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); - if((isxinerama = XineramaIsActive(dpy))) + if(XineramaIsActive(dpy)) info = XineramaQueryScreens(dpy, &nviews); + #if defined(AIM_XINERAMA) -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); @@ -1551,17 +1572,24 @@ nviews = 2; /* aim Xinerama */ blw = i; } - seltags = emallocz(sizeof initags); - prevtags = emallocz(sizeof initags); - memcpy(seltags, initags, sizeof initags); - memcpy(prevtags, initags, sizeof initags); + seltags = emallocz(TAGSZ); + prevtags = emallocz(TAGSZ); + + /* check, if vtags need assistance, because there is only 1 view */ + if(nviews == 1) + for(i = 0; i < LENGTH(tags); i++) + vtags[i] = 0; for(i = 0; i < nviews; i++) { /* init geometry */ v = &views[i]; - v->id = i + 1; + v->id = i; + + /* select first tag of view */ + j = firstag(v); + seltags[j] = prevtags[j] = True; - if(nviews != 1 && isxinerama) { + if(info) { #if defined(AIM_XINERAMA) v->w = DisplayWidth(dpy, screen) / 2; @@ -1616,10 +1644,10 @@ v->h = DisplayHeight(dpy, screen); if(info) XFree(info); + selview = viewat(); + /* grab keys */ grabkeys(); - - selview = &views[0]; } void @@ -1653,8 +1681,10 @@ 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) && (vtags[i] == getview(sel)->id); + i = idxoftag(arg); + if(!conflicts(sel, i)) + sel->tags[idxoftag(arg)] = True; arrange(); } @@ -1694,8 +1724,6 @@ tile(View *v) { for(i = 0, c = mc = nexttiled(clients, v); c; c = nexttiled(c->next, v)) { if(i == 0) { /* master */ - nx = v->wax; - ny = v->way; nw = mw - 2 * c->border; nh = v->wah - 2 * c->border; } @@ -1747,10 +1775,12 @@ toggletag(const char *arg) { if(!sel) return; i = idxoftag(arg); + if(conflicts(sel, i)) + return; 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(); } @@ -1762,7 +1792,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(); } @@ -1902,15 +1932,33 @@ updatewmhints(Client *c) { void view(const char *arg) { - unsigned int i; - int tmp[LENGTH(tags)]; + unsigned int i, j; + Bool 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); + memcpy(tmp, seltags, TAGSZ); + if(arg == NULL) { + for(i = 0; i < LENGTH(tags); i++) + tmp[i] = (vtags[i] == selview->id); + } + else { + i = idxoftag(arg); + for(j = 0; j < LENGTH(tags); j++) + if(selview->id == vtags[i]) { + /* view tag of selview */ + if(selview->id == vtags[j]) + tmp[j] = False; + } + else { + /* only touch the view the focus should go */ + if(vtags[j] == vtags[i]) + tmp[j] = False; + } + selview = &views[vtags[i]]; + tmp[i] = True; + } + if(memcmp(seltags, tmp, TAGSZ) != 0) { + memcpy(prevtags, seltags, TAGSZ); + memcpy(seltags, tmp, TAGSZ); arrange(); } } @@ -1934,9 +1982,9 @@ 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); + memcpy(tmp, seltags, TAGSZ); + memcpy(seltags, prevtags, TAGSZ); + memcpy(prevtags, tmp, TAGSZ); arrange(); }