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.htmldiff -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();
}