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
@@ -17,7 +17,7 @@
# 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
@@ -71,7 +71,6 @@ long flags;
unsigned int border, oldborder; Bool isbanned, isfixed, isfloating, isurgent; Bool *tags; - View *view; Client *next; Client *prev; Client *snext;@@ -120,7 +119,6 @@ Window barwin;
}; /* 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 @@ #include "config.h"
#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 @@ || (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); + if(r->tag && !conflicts(c, (idx = idxoftag(r->tag)))) { + c->tags[idx] = True; matched = True; } }@@ -286,8 +277,9 @@ XFree(ch.res_class);
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 @@ focus(c);
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 @@ XConfigureRequestEvent *ev = &e->xconfigurerequest;
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 @@ }
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 @@ int i, x;
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 @@ 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;@@ -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 @@ sel = 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 @@ if(!c)
for(c = clients; c && !isvisible(c); c = c->next); if(c) { focus(c); - restack(c->view); + restack(getview(c)); } }@@ -758,7 +769,7 @@ for(; c && !isvisible(c); c = c->prev);
} if(c) { focus(c); - restack(c->view); + restack(getview(c)); } }@@ -781,6 +792,16 @@ return color.pixel;
} 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 @@ c->win = w;
applyrules(c); - v = c->view; + v = getview(c); c->x = wa->x + v->x; c->y = wa->y + v->y;@@ -1124,7 +1145,7 @@ XEvent ev;
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 @@ }
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 @@ updatesizehints(c);
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 @@ XEvent ev;
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 @@
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 @@
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 @@
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 @@ }
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 @@ Client *c = sel;
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);