This probably isn't suitable for mainstream dwm since most people don't have
that much multitagging going on; with my "push/pop" approach I tend to use
more multitagging so keeping a consistent order is helpful.

Background: This deals with ensuring that multitagged clients will keep the
same order when viewed via different tags. It doesn't do anything to stabilise
the order when viewing more than one tag at once, but for me I only use that
to add in single windows like, eg, build windows or debuggers, so the more
general problem of full consistency doesn't occur in actual practice.

Key points: (1) the tags array on a client is Bool, so we have 4 bytes used, so
making an explicit int doesn't increase space reqs.
(2) Any tagging operation eventually calls arrange(), which does at least one
walk through full client list, so adding an additional scan here and there 
doesn't
change asymptotic complexity.

So if we use c->tags[i]==0 to mean "hasn't got this tag" and c->tags[i]==k>0
to mean "when viewing tag i, this client comes at position k" then we just need
to do a bit more bookkeeping than for Bools, but otherwise it's pretty minimal.
Anyway, just putting this out there to show it's possible, but whilst I'll keep 
using
this in my personal dwm I don't intend to keep sending to list.

cheers, dave tweed






                
___________________________________________________________ 
Try the all-new Yahoo! Mail. "The New Version is radically easier to use" – The 
Wall Street Journal 
http://uk.docs.yahoo.com/nowyoucan.html
diff -u dwm-2.3/client.c dwm-2.3.modified/client.c
--- dwm-2.3/client.c	2006-11-24 14:46:27.000000000 +0000
+++ dwm-2.3.modified/client.c	2006-11-27 11:51:41.000000000 +0000
@@ -200,7 +200,7 @@
 	XSetWindowAttributes twa;
 
 	c = emallocz(sizeof(Client));
-	c->tags = emallocz(ntags * sizeof(Bool));
+	c->tags = emallocz(ntags * sizeof(int));
 	c->win = w;
 	c->border = 0;
 	c->x = c->tx = wa->x;
diff -u dwm-2.3/dwm.h dwm-2.3.modified/dwm.h
--- dwm-2.3/dwm.h	2006-11-24 14:46:27.000000000 +0000
+++ dwm-2.3.modified/dwm.h	2006-11-27 18:57:33.000000000 +0000
@@ -84,7 +84,7 @@
 	long flags; 
 	unsigned int border;
 	Bool isfloat, isfixed, ismax;
-	Bool *tags;
+	int *tags;
 	Client *next;
 	Client *prev;
 	Client *snext;
@@ -148,6 +148,7 @@
 extern void settags(Client *c, Client *trans);	/* sets tags of c */
 extern void tag(Arg *arg);			/* tags c with arg's index */
 extern void toggletag(Arg *arg);		/* toggles c tags with arg's index */
+extern void updateClientTagWeights(int viewedTag,int startValue);
 
 /* util.c */
 extern void *emallocz(unsigned int size);	/* allocates zero-initialized memory, exits on error */
diff -u dwm-2.3/tag.c dwm-2.3.modified/tag.c
--- dwm-2.3/tag.c	2006-11-24 14:46:27.000000000 +0000
+++ dwm-2.3.modified/tag.c	2006-11-28 08:46:51.000000000 +0000
@@ -31,6 +31,32 @@
 
 /* extern */
 
+int
+fstFreeIdxOnTag(int tag)
+{
+	int highest=1;
+	Client *c;
+	for(c=clients;c;c=c->next){
+		if(c->tags[tag]>highest){
+			highest=c->tags[tag];
+		}
+	}
+	return highest+1;
+}
+
+/*move through viewedTag, keeping order but renumbering from startValue*/
+void
+updateClientTagWeights(int viewedTag,int startValue)
+{
+	Client *c;
+	int tag=startValue;
+	for(c = clients; c; c = c->next){
+		if(!c->isfloat && c->tags[viewedTag]>0){
+			c->tags[viewedTag]=tag++;
+		}
+	}
+}
+
 Client *
 getnext(Client *c) {
 	for(; c && !isvisible(c); c = c->next);
@@ -92,7 +118,8 @@
 				for(j = 0; rreg[i].tregex && j < ntags; j++) {
 					if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
 						matched = True;
-						c->tags[j] = True;
+						updateClientTagWeights(j,2);
+						c->tags[j]=1;
 					}
 				}
 			}
@@ -101,9 +128,12 @@
 		if(ch.res_name)
 			XFree(ch.res_name);
 	}
-	if(!matched)
+	if(!matched) /*tags was emallocz()'d so values init to 0*/
 		for(i = 0; i < ntags; i++)
-			c->tags[i] = seltag[i];
+			if(seltag[i]){
+				updateClientTagWeights(i,2);
+				c->tags[i]=1;
+			}
 }
 
 void
@@ -113,8 +143,8 @@
 	if(!sel)
 		return;
 	for(i = 0; i < ntags; i++)
-		sel->tags[i] = False;
-	sel->tags[arg->i] = True;
+		sel->tags[i] = 0;
+	sel->tags[arg->i] = fstFreeIdxOnTag(arg->i);/*add to end on arg->i*/
 	arrange();
 }
 
@@ -124,9 +154,14 @@
 
 	if(!sel)
 		return;
-	sel->tags[arg->i] = !sel->tags[arg->i];
-	for(i = 0; i < ntags && !sel->tags[i]; i++);
-	if(i == ntags)
-		sel->tags[arg->i] = True;
+	if(sel->tags[arg->i]){
+		 int origValue=sel->tags[arg->i];
+		 sel->tags[arg->i]=0;
+		 for(i = 0; i < ntags && !sel->tags[i]; i++);
+		 if(i == ntags)
+			  sel->tags[arg->i] = origValue;
+	}else{
+		 sel->tags[arg->i]=fstFreeIdxOnTag(arg->i);
+	}
 	arrange();
 }
diff -u dwm-2.3/view.c dwm-2.3.modified/view.c
--- dwm-2.3/view.c	2006-11-24 14:46:27.000000000 +0000
+++ dwm-2.3.modified/view.c	2006-11-28 08:50:47.000000000 +0000
@@ -5,6 +5,18 @@
 
 /* static */
 
+int
+highestTagUsed()
+{
+	int i;
+	for(i=ntags-1;i>=0;--i){
+		if(seltag[i]){
+			return i;
+		}
+	}
+	return 0; /*should never happen*/
+}
+
 static Client *
 nexttiled(Client *c) {
 	for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
@@ -67,11 +79,44 @@
 	restack();
 }
 
+typedef Client* (*MinFP)(int); /*modification*/
+
+static Client *
+stdorder(int sortTag) {
+	Client *c, *min;
+
+	if((clients && clients->isfloat) || arrange == dofloat)
+		return clients; /* don't touch floating order */
+	for(min = c = clients; c; c = c->next)
+		if(c->tags[sortTag] < min->tags[sortTag])/*reverse order works better*/
+			min = c;
+	return min;
+}
+
+static void
+reorder(MinFP fp,int sortTag) {
+	Client *c, *newclients, *tail;
+
+	newclients = tail = NULL;
+	while((c = (*fp)(sortTag))) {
+		detach(c);
+		if(tail) {
+			c->prev = tail;
+			tail->next = c;
+			tail = c;
+		}
+		else
+			tail = newclients = c;
+	}
+	clients = newclients;
+}
+
 void
 dotile(void) {
 	unsigned int i, n, mpx, stackw, th;
 	Client *c;
-
+	int highestTag=highestTagUsed();
+	reorder(&stdorder,highestTag);
 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
 		n++;
 	mpx = (waw * master) / 1000;
@@ -121,7 +166,7 @@
 void
 focusnext(Arg *arg) {
 	Client *c;
-   
+	
 	if(!sel)
 		return;
 	if(!(c = getnext(sel->next)))
@@ -263,6 +308,8 @@
 		clients->prev = c;
 	c->next = clients;
 	clients = c;
+	/*DST: update weights under the selected tag but needn't reorder*/
+	updateClientTagWeights(highestTagUsed(),1);
 	focus(c);
 	arrange();
 }

Reply via email to