URI: 
       made the basics of the tagging concept working -- if people want dynamic tags, that's even possible with this concept, the vtags[] array needs to be modified during runtime for this -- the new code is quite experimental, ugly and needs polishing - dwm - dynamic window manager
  HTML git clone https://git.parazyd.org/dwm
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 7bc272a4e4f463c673d12144b3a202db2345e7de
   DIR parent f1719ac2de2aba270c2460807eacae137d3aeadf
  HTML Author: anselm@anselm1 <unknown>
       Date:   Thu, 28 Feb 2008 21:38:53 +0000
       
       made the basics of the tagging concept working -- if people want dynamic tags, that's even possible with this concept, the vtags[] array needs to be modified during runtime for this -- the new code is quite experimental, ugly and needs polishing
       Diffstat:
         M config.mk                           |       2 +-
         M dwm.c                               |     145 ++++++++++++++++++++-----------
       
       2 files changed, 93 insertions(+), 54 deletions(-)
       ---
   DIR diff --git a/config.mk b/config.mk
       @@ -17,7 +17,7 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama
        # flags
        CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
        LDFLAGS = -s ${LIBS}
       -CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
       +CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" -DAIM_XINERAMA
        LDFLAGS = -g ${LIBS}
        
        # Solaris
   DIR diff --git a/dwm.c b/dwm.c
       @@ -71,7 +71,6 @@ struct Client {
                unsigned int border, oldborder;
                Bool isbanned, isfixed, isfloating, isurgent;
                Bool *tags;
       -        View *view;
                Client *next;
                Client *prev;
                Client *snext;
       @@ -120,7 +119,6 @@ struct View {
        };
        
        /* function declarations */
       -void addtag(Client *c, const char *t);
        void applyrules(Client *c);
        void arrange(void);
        void attach(Client *c);
       @@ -132,6 +130,7 @@ 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);
       @@ -142,6 +141,7 @@ 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);
       @@ -149,6 +149,7 @@ void focusnext(const char *arg);
        void focusprev(const char *arg);
        Client *getclient(Window w);
        unsigned long getcolor(const char *colstr);
       +View *getview(Client *c);
        View *getviewbar(Window barwin);
        long getstate(Window w);
        Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
       @@ -248,20 +249,10 @@ Window root;
        #define TAGSZ (LENGTH(tags) * sizeof(Bool))
        
        /* 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) {
       -        unsigned int i;
       +        unsigned int i, idx;
                Bool matched = False;
                Rule *r;
                XClassHint ch = { 0 };
       @@ -275,8 +266,8 @@ applyrules(Client *c) {
                        || (ch.res_name && strstr(ch.res_name, r->prop)))
                        {
                                c->isfloating = r->isfloating;
       -                        if(r->tag) {
       -                                addtag(c, r->tag);
       +                        if(r->tag && !conflicts(c, (idx = idxoftag(r->tag)))) {
       +                                c->tags[idx] = True;
                                        matched = True;
                                }
                        }
       @@ -286,8 +277,9 @@ applyrules(Client *c) {
                if(ch.res_name)
                        XFree(ch.res_name);
                if(!matched) {
       -                memcpy(c->tags, seltags, TAGSZ);
       -                c->view = selview;
       +                for(i = 0; i < LENGTH(tags); i++)
       +                        if(seltags[i] && vtags[i] == selview->id)
       +                                c->tags[i] = True;
                }
        }
        
       @@ -327,7 +319,7 @@ void
        ban(Client *c) {
                if(c->isbanned)
                        return;
       -        XMoveWindow(dpy, c->win, c->x + 3 * c->view->w, c->y);
       +        XMoveWindow(dpy, c->win, c->x + 3 * getview(c)->w, c->y);
                c->isbanned = True;
        }
        
       @@ -367,17 +359,17 @@ buttonpress(XEvent *e) {
                        if(CLEANMASK(ev->state) != MODKEY)
                                return;
                        if(ev->button == Button1) {
       -                        restack(c->view);
       +                        restack(getview(c));
                                movemouse(c);
                        }
                        else if(ev->button == Button2) {
       -                        if((floating != c->view->layout->arrange) && c->isfloating)
       +                        if((floating != getview(c)->layout->arrange) && c->isfloating)
                                        togglefloating(NULL);
                                else
                                        zoom(NULL);
                        }
                        else if(ev->button == Button3 && !c->isfixed) {
       -                        restack(c->view);
       +                        restack(getview(c));
                                resizemouse(c);
                        }
                }
       @@ -466,7 +458,7 @@ configurerequest(XEvent *e) {
                XWindowChanges wc;
        
                if((c = getclient(ev->window))) {
       -                View *v = c->view;
       +                View *v = getview(c);
                        if(ev->value_mask & CWBorderWidth)
                                c->border = ev->border_width;
                        if(c->isfixed || c->isfloating || (floating == v->layout->arrange)) {
       @@ -504,6 +496,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;
       @@ -538,7 +540,7 @@ drawbar(View *v) {
                Client *c;
        
                dc.x = 0;
       -        for(c = stack; c && (!isvisible(c) || c->view != v); c = c->snext);
       +        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;
       @@ -681,6 +683,16 @@ expose(XEvent *e) {
                        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;
       @@ -695,13 +707,12 @@ void
        focus(Client *c) {
                View *v = selview;
                if(c)
       -                selview = c->view;
       -        else
       -                selview = viewat();
       +                selview = getview(c);
                if(selview != v)
                        drawbar(v);
                if(!c || (c && !isvisible(c)))
       -                for(c = stack; c && (!isvisible(c) || c->view != selview); c = c->snext);
       +                /* 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);
                        XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
       @@ -715,7 +726,7 @@ focus(Client *c) {
                if(c) {
                        XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
                        XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
       -                selview = c->view;
       +                selview = getview(c);
                }
                else
                        XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
       @@ -741,7 +752,7 @@ focusnext(const char *arg) {
                        for(c = clients; c && !isvisible(c); c = c->next);
                if(c) {
                        focus(c);
       -                restack(c->view);
       +                restack(getview(c));
                }
        }
        
       @@ -758,7 +769,7 @@ focusprev(const char *arg) {
                }
                if(c) {
                        focus(c);
       -                restack(c->view);
       +                restack(getview(c));
                }
        }
        
       @@ -781,6 +792,16 @@ getcolor(const char *colstr) {
        }
        
        View *
       +getview(Client *c) {
       +        unsigned int i;
       +
       +        for(i = 0; i < LENGTH(tags); i++)
       +                if(c->tags[i])
       +                        return &views[vtags[i]];
       +        return NULL;
       +}
       +
       +View *
        getviewbar(Window barwin) {
                unsigned int i;
        
       @@ -905,7 +926,7 @@ idxoftag(const char *t) {
                unsigned int i;
        
                for(i = 0; (i < LENGTH(tags)) && (tags[i] != t); i++);
       -        return (i < LENGTH(tags)) ? i : 0;
       +        return (i < LENGTH(tags)) ? i : firstag(selview);
        }
        
        void
       @@ -1045,7 +1066,7 @@ manage(Window w, XWindowAttributes *wa) {
        
                applyrules(c);
        
       -        v = c->view;
       +        v = getview(c);
        
                c->x = wa->x + v->x;
                c->y = wa->y + v->y;
       @@ -1124,7 +1145,7 @@ movemouse(Client *c) {
        
                ocx = nx = c->x;
                ocy = ny = c->y;
       -        v = c->view;
       +        v = getview(c);
                if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
                                None, cursor[CurMove], CurrentTime) != GrabSuccess)
                        return;
       @@ -1163,7 +1184,7 @@ movemouse(Client *c) {
        
        Client *
        nexttiled(Client *c, View *v) {
       -        for(; c && (c->isfloating || c->view != v || !isvisible(c)); c = c->next);
       +        for(; c && (c->isfloating || getview(c) != v || !isvisible(c)); c = c->next);
                return c;
        }
        
       @@ -1188,7 +1209,7 @@ propertynotify(XEvent *e) {
                                break;
                        case XA_WM_HINTS:
                                updatewmhints(c);
       -                        drawbar(c->view);
       +                        drawbar(getview(c));
                                break;
                        }
                        if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
       @@ -1221,7 +1242,7 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
                View *v;
                XWindowChanges wc;
        
       -        v = c->view;
       +        v = getview(c);
                if(sizehints) {
                        /* set minimum possible */
                        if (w < 1)
       @@ -1292,7 +1313,7 @@ resizemouse(Client *c) {
        
                ocx = c->x;
                ocy = c->y;
       -        v = c->view;
       +        v = getview(c);
                if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
                                None, cursor[CurResize], CurrentTime) != GrabSuccess)
                        return;
       @@ -1560,14 +1581,11 @@ nviews = 2; /* aim Xinerama */
                for(i = 0; i < nviews; i++) {
                        /* init geometry */
                        v = &views[i];
       +                v->id = i;
        
       -                /* select first tag in each view */
       -                for(j = 0; j < LENGTH(tags); j++)
       -                        if(vtags[j] == i) {
       -                                seltags[j] = prevtags[j] = True; 
       -                                break;
       -                        }
       -
       +                /* select first tag of view */
       +                j = firstag(v);
       +                seltags[j] = prevtags[j] = True; 
        
                        if(info) {
        
       @@ -1661,8 +1679,10 @@ tag(const char *arg) {
                if(!sel)
                        return;
                for(i = 0; i < LENGTH(tags); i++)
       -                sel->tags[i] = (NULL == arg);
       -        sel->tags[idxoftag(arg)] = True;
       +                sel->tags[i] = (NULL == arg) && (vtags[i] == getview(sel)->id);
       +        i = idxoftag(arg);
       +        if(!conflicts(sel, i))
       +                sel->tags[idxoftag(arg)] = True;
                arrange();
        }
        
       @@ -1753,6 +1773,8 @@ 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))
       @@ -1908,13 +1930,30 @@ updatewmhints(Client *c) {
        
        void
        view(const char *arg) {
       -        unsigned int i;
       +        unsigned int i, j;
                Bool tmp[LENGTH(tags)];
        
       -        for(i = 0; i < LENGTH(tags); i++)
       -                tmp[i] = (NULL == arg);
       -        tmp[idxoftag(arg)] = True;
       -
       +        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);
       @@ -1985,8 +2024,8 @@ zoom(const char *arg) {
        
                if(!sel || !dozoom || sel->isfloating)
                        return;
       -        if(c == nexttiled(clients, c->view))
       -                if(!(c = nexttiled(c->next, c->view)))
       +        if(c == nexttiled(clients, getview(c)))
       +                if(!(c = nexttiled(c->next, getview(c))))
                                return;
                detach(c);
                attach(c);