changeset: 895:ac4f88761973
tag: tip
user: Jan Christoph Ebersbach <jceb_AT_e-jc.de>
date: Sun Mar 18 21:50:30 2012 +0100
files: dwm.suckless.org/patches/dwm-6.0-single_tagset.diff dwm.suckless.org/patches/dwm-6.0-single_tagset_all.diff dwm.suckless.org/patches/single_tagset.md
description:
add single tagset patch
diff -r 41ea3edaafcf -r ac4f88761973 dwm.suckless.org/patches/dwm-6.0-single_tagset.diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/dwm-6.0-single_tagset.diff Sun Mar 18 21:50:30 2012 +0100
_AT_@ -0,0 +1,496 @@
+Author: Jan Christoph Ebersbach <jceb_AT_e-jc.de>
+URL: no URL yet
+This patch addresses the multi-monitor setup. Instead of having separate tags
+for every monitor there is just one list of tags for all monitors. Instead of
+moving windows from one monitor to the other, the desired tag from the
+other monitor can just be selected and all windows will be drawn on the
+current monitor.
+
+Several deep changes needed to be made:
+1. Macro ISVISIBLE expects a second parameter, the monitor
+2. Monitor->clients and Monitor->stack were moved to the global variable
+ Clientlist cl. All monitors refer to this one list.
+3. A new method attachclients was added. When changing between tags this
+ function ensures that all clients are pointing to the right monitor.
+
+Please be aware that this patch probably breaks any other patch!
+
+diff -r 627ba72d3465 dwm.c
+--- a/dwm.c Sun Mar 18 17:23:36 2012 +0100
++++ b/dwm.c Sun Mar 18 20:44:53 2012 +0100
+_AT_@ -45,7 +45,7 @@
+ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+ #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
+-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
++#define ISVISIBLE(C, M) ((C->tags & M->tagset[M->seltags]))
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MAX(A, B) ((A) > (B) ? (A) : (B))
+ #define MIN(A, B) ((A) < (B) ? (A) : (B))
+_AT_@ -124,6 +124,7 @@
+ void (*arrange)(Monitor *);
+ } Layout;
+
++typedef struct Clientlist Clientlist;
+ struct Monitor {
+ char ltsymbol[16];
+ float mfact;
+_AT_@ -137,9 +138,8 @@
+ unsigned int tagset[2];
+ Bool showbar;
+ Bool topbar;
+- Client *clients;
++ Clientlist *cl;
+ Client *sel;
+- Client *stack;
+ Monitor *next;
+ Window barwin;
+ const Layout *lt[2];
+_AT_@ -154,12 +154,18 @@
+ int monitor;
+ } Rule;
+
++struct Clientlist {
++ Client *clients;
++ Client *stack;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
+ static void arrange(Monitor *m);
+ static void arrangemon(Monitor *m);
+ static void attach(Client *c);
++static void attachclients(Monitor *m);
+ static void attachstack(Client *c);
+ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+_AT_@ -202,7 +208,7 @@
+ static void monocle(Monitor *m);
+ static void motionnotify(XEvent *e);
+ static void movemouse(const Arg *arg);
+-static Client *nexttiled(Client *c);
++static Client *nexttiled(Client *c, Monitor *m);
+ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
+_AT_@ -283,6 +289,7 @@
+ static DC dc;
+ static Monitor *mons = NULL, *selmon = NULL;
+ static Window root;
++static Clientlist *cl;
+
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+_AT_@ -394,9 +401,9 @@
+ void
+ arrange(Monitor *m) {
+ if(m)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ else for(m = mons; m; m = m->next)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ if(m) {
+ arrangemon(m);
+ restack(m);
+_AT_@ -413,14 +420,47 @@
+
+ void
+ attach(Client *c) {
+- c->next = c->mon->clients;
+- c->mon->clients = c;
++ c->next = c->mon->cl->clients;
++ c->mon->cl->clients = c;
++}
++
++void
++attachclients(Monitor *m) {
++ /* attach clients to the specified monitor */
++ Monitor *tm;
++ Client *c;
++ unsigned int utags = 0;
++ Bool rmons = False;
++ if(!m)
++ return;
++
++ /* collect information about the tags in use */
++ for(tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ utags |= m->tagset[m->seltags];
++
++ for(c = m->cl->clients; c; c = c->next)
++ if(ISVISIBLE(c, m)) {
++ /* if client is also visible on other tags that are displayed on
++ * other monitors, remove these tags */
++ if(c->tags & utags) {
++ c->tags = c->tags & m->tagset[m->seltags];
++ rmons = True;
++ }
++ unfocus(c, True);
++ c->mon = m;
++ }
++
++ if(rmons)
++ for(tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ arrange(tm);
+ }
+
+ void
+ attachstack(Client *c) {
+- c->snext = c->mon->stack;
+- c->mon->stack = c;
++ c->snext = c->mon->cl->stack;
++ c->mon->cl->stack = c;
+ }
+
+ void
+_AT_@ -483,8 +523,8 @@
+ view(&a);
+ selmon->lt[selmon->sellt] = &foo;
+ for(m = mons; m; m = m->next)
+- while(m->stack)
+- unmanage(m->stack, False);
++ while(m->cl->stack)
++ unmanage(m->cl->stack, False);
+ if(dc.font.set)
+ XFreeFontSet(dpy, dc.font.set);
+ else
+_AT_@ -541,7 +581,7 @@
+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
+ }
+ else if(cme->message_type == netatom[NetActiveWindow]) {
+- if(!ISVISIBLE(c)) {
++ if(!ISVISIBLE(c, c->mon)) {
+ c->mon->seltags ^= 1;
+ c->mon->tagset[c->mon->seltags] = c->tags;
+ }
+_AT_@ -624,7 +664,7 @@
+ c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
+ if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
+ configure(c);
+- if(ISVISIBLE(c))
++ if(ISVISIBLE(c, m))
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
+ }
+ else
+_AT_@ -645,11 +685,18 @@
+
+ Monitor *
+ createmon(void) {
+- Monitor *m;
++ Monitor *m, *tm;
++ unsigned int i;
+
+ if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
+- m->tagset[0] = m->tagset[1] = 1;
++ m->cl = cl;
++ /* reassing tags when creating a new monitor */
++ for(i=1, tm = mons; tm; tm = tm->next, i++) {
++ tm->seltags ^= 1;
++ tm->tagset[tm->seltags] = i;
++ }
++ m->tagset[0] = m->tagset[1] = i;
+ m->mfact = mfact;
+ m->nmaster = nmaster;
+ m->showbar = showbar;
+_AT_@ -673,7 +720,7 @@
+ detach(Client *c) {
+ Client **tc;
+
+- for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
++ for(tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
+ *tc = c->next;
+ }
+
+_AT_@ -681,11 +728,11 @@
+ detachstack(Client *c) {
+ Client **tc, *t;
+
+- for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
++ for(tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
+ *tc = c->snext;
+
+ if(c == c->mon->sel) {
+- for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
++ for(t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
+ c->mon->sel = t;
+ }
+ }
+_AT_@ -722,7 +769,7 @@
+ unsigned long *col;
+ Client *c;
+
+- for(c = m->clients; c; c = c->next) {
++ for(c = m->cl->clients; c; c = c->next) {
+ occ |= c->tags;
+ if(c->isurgent)
+ urg |= c->tags;
+_AT_@ -842,8 +889,8 @@
+
+ void
+ focus(Client *c) {
+- if(!c || !ISVISIBLE(c))
+- for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
++ if(!c || !ISVISIBLE(c, selmon))
++ for(c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
+ /* was if(selmon->sel) */
+ if(selmon->sel && selmon->sel != c)
+ unfocus(selmon->sel, False);
+_AT_@ -892,17 +939,17 @@
+ if(!selmon->sel)
+ return;
+ if(arg->i > 0) {
+- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
++ for(c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
+ if(!c)
+- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
++ for(c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
+ }
+ else {
+- for(i = selmon->clients; i != selmon->sel; i = i->next)
+- if(ISVISIBLE(i))
++ for(i = selmon->cl->clients; i != selmon->sel; i = i->next)
++ if(ISVISIBLE(i, selmon))
+ c = i;
+ if(!c)
+ for(; i; i = i->next)
+- if(ISVISIBLE(i))
++ if(ISVISIBLE(i, selmon))
+ c = i;
+ }
+ if(c) {
+_AT_@ -1194,12 +1241,12 @@
+ unsigned int n = 0;
+ Client *c;
+
+- for(c = m->clients; c; c = c->next)
+- if(ISVISIBLE(c))
++ for(c = m->cl->clients; c; c = c->next)
++ if(ISVISIBLE(c, m))
+ n++;
+ if(n > 0) /* override layout symbol */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+- for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
++ for(c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m))
+ resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
+ }
+
+_AT_@ -1275,8 +1322,8 @@
+ }
+
+ Client *
+-nexttiled(Client *c) {
+- for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
++nexttiled(Client *c, Monitor *m) {
++ for(; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
+ return c;
+ }
+
+_AT_@ -1426,8 +1473,8 @@
+ if(m->lt[m->sellt]->arrange) {
+ wc.stack_mode = Below;
+ wc.sibling = m->barwin;
+- for(c = m->stack; c; c = c->snext)
+- if(!c->isfloating && ISVISIBLE(c)) {
++ for(c = m->cl->stack; c; c = c->snext)
++ if(!c->isfloating && ISVISIBLE(c, m)) {
+ XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
+ wc.sibling = c->win;
+ }
+_AT_@ -1477,11 +1524,9 @@
+ if(c->mon == m)
+ return;
+ unfocus(c, True);
+- detach(c);
+ detachstack(c);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+- attach(c);
+ attachstack(c);
+ focus(NULL);
+ arrange(NULL);
+_AT_@ -1595,6 +1640,8 @@
+ sw = DisplayWidth(dpy, screen);
+ sh = DisplayHeight(dpy, screen);
+ bh = dc.h = dc.font.height + 2;
++ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist));
+ updategeom();
+ /* init atoms */
+ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
+_AT_@ -1643,7 +1690,7 @@
+ showhide(Client *c) {
+ if(!c)
+ return;
+- if(ISVISIBLE(c)) { /* show clients top down */
++ if(ISVISIBLE(c, c->mon)) { /* show clients top down */
+ XMoveWindow(dpy, c->win, c->x, c->y);
+ if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
+ resize(c, c->x, c->y, c->w, c->h, False);
+_AT_@ -1677,7 +1724,23 @@
+
+ void
+ tag(const Arg *arg) {
++ Monitor *m;
++ unsigned int newtags;
+ if(selmon->sel && arg->ui & TAGMASK) {
++ newtags = arg->ui & TAGMASK;
++ for(m = mons; m; m = m->next)
++ /* if tag is visible on another monitor, move client to the new monitor */
++ if(m != selmon && m->tagset[m->seltags] & newtags) {
++ /* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
++ if(newtags & selmon->tagset[selmon->seltags])
++ return;
++ /* TODO sendmon? */
++ selmon->sel->tags = newtags;
++ selmon->sel->mon = m;
++ arrange(m);
++ break;
++ }
++ /* workaround in case just one monitor is connected */
+ selmon->sel->tags = arg->ui & TAGMASK;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1707,7 +1770,7 @@
+ unsigned int i, n, h, mw, my, ty;
+ Client *c;
+
+- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++ for(n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
+ if(n == 0)
+ return;
+
+_AT_@ -1715,7 +1778,7 @@
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ else
+ mw = m->ww;
+- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ for(i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
+ if(i < m->nmaster) {
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False);
+_AT_@ -1749,12 +1812,17 @@
+
+ void
+ toggletag(const Arg *arg) {
++ Monitor *m;
+ unsigned int newtags;
+
+ if(!selmon->sel)
+ return;
+ newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
+ if(newtags) {
++ /* prevent adding tags that are in use on other monitors */
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtags & m->tagset[m->seltags])
++ return;
+ selmon->sel->tags = newtags;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1763,10 +1831,16 @@
+
+ void
+ toggleview(const Arg *arg) {
++ Monitor *m;
+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+
+ if(newtagset) {
++ /* prevent displaying the same tags on multiple monitors */
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtagset & m->tagset[m->seltags])
++ return;
+ selmon->tagset[selmon->seltags] = newtagset;
++ attachclients(selmon);
+ focus(NULL);
+ arrange(selmon);
+ }
+_AT_@ -1875,8 +1949,10 @@
+ if(n <= nn) {
+ for(i = 0; i < (nn - n); i++) { /* new monitors available */
+ for(m = mons; m && m->next; m = m->next);
+- if(m)
++ if(m) {
+ m->next = createmon();
++ attachclients(m->next);
++ }
+ else
+ mons = createmon();
+ }
+_AT_@ -1897,17 +1973,13 @@
+ else { /* less monitors available nn < n */
+ for(i = nn; i < n; i++) {
+ for(m = mons; m && m->next; m = m->next);
+- while(m->clients) {
+- dirty = True;
+- c = m->clients;
+- m->clients = c->next;
+- detachstack(c);
+- c->mon = mons;
+- attach(c);
+- attachstack(c);
+- }
+ if(m == selmon)
+ selmon = mons;
++ for(c = m->cl->clients; c; c = c->next) {
++ dirty = True;
++ if(ISVISIBLE(c, m))
++ c->mon = selmon;
++ }
+ cleanupmon(m);
+ }
+ }
+_AT_@ -2046,11 +2118,31 @@
+
+ void
+ view(const Arg *arg) {
++ Monitor *m;
++ unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
+ if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ return;
++
++ /* swap tags when trying to display a tag from another monitor */
++ if(arg->ui & TAGMASK)
++ newtagset = arg->ui & TAGMASK;
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtagset & m->tagset[m->seltags]) {
++ /* prevent displaying all tags (MODKEY-0) when multiple monitors
++ * are connected */
++ if(newtagset & selmon->tagset[selmon->seltags])
++ return;
++ m->seltags ^= 1;
++ m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
++ attachclients(m);
++ arrange(m);
++ break;
++ }
++
+ selmon->seltags ^= 1; /* toggle sel tagset */
+ if(arg->ui & TAGMASK)
+ selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
++ attachclients(selmon);
+ focus(NULL);
+ arrange(selmon);
+ }
+_AT_@ -2061,7 +2153,7 @@
+ Monitor *m;
+
+ for(m = mons; m; m = m->next)
+- for(c = m->clients; c; c = c->next)
++ for(c = m->cl->clients; c; c = c->next)
+ if(c->win == w)
+ return c;
+ return NULL;
+_AT_@ -2123,8 +2215,8 @@
+ if(!selmon->lt[selmon->sellt]->arrange
+ || (selmon->sel && selmon->sel->isfloating))
+ return;
+- if(c == nexttiled(selmon->clients))
+- if(!c || !(c = nexttiled(c->next)))
++ if(c == nexttiled(selmon->cl->clients, selmon))
++ if(!c || !(c = nexttiled(c->next, selmon)))
+ return;
+ pop(c);
+ }
diff -r 41ea3edaafcf -r ac4f88761973 dwm.suckless.org/patches/dwm-6.0-single_tagset_all.diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/dwm-6.0-single_tagset_all.diff Sun Mar 18 21:50:30 2012 +0100
_AT_@ -0,0 +1,606 @@
+Author: Jan Christoph Ebersbach <jceb_AT_e-jc.de>
+URL: no URL yet
+This patch addresses the multi-monitor setup. Instead of having separate tags
+for every monitor there is just one list of tags for all monitors. Instead of
+moving windows from one monitor to the other, the desired tag from the
+other monitor can just be selected and all windows will be drawn on the
+current monitor.
+
+Several deep changes needed to be made:
+1. Macro ISVISIBLE expects a second parameter, the monitor
+2. Monitor->clients and Monitor->stack were moved to the global variable
+ Clientlist cl. All monitors refer to this one list.
+3. A new method attachclients was added. When changing between tags this
+ function ensures that all clients are pointing to the right monitor.
+
+Please be aware that this patch probably breaks any other patch!
+
+diff -r 454a5dd61441 dwm.c
+--- a/dwm.c Sun Mar 18 20:45:06 2012 +0100
++++ b/dwm.c Sun Mar 18 21:10:25 2012 +0100
+_AT_@ -45,7 +45,7 @@
+ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+ #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
+-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
++#define ISVISIBLE(C, M) ((C->tags & M->tagset[M->seltags]))
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MAX(A, B) ((A) > (B) ? (A) : (B))
+ #define MIN(A, B) ((A) < (B) ? (A) : (B))
+_AT_@ -126,6 +126,7 @@
+ } Layout;
+
+ typedef struct Pertag Pertag;
++typedef struct Clientlist Clientlist;
+ struct Monitor {
+ char ltsymbol[16];
+ float mfact;
+_AT_@ -139,9 +140,8 @@
+ unsigned int tagset[2];
+ Bool showbar;
+ Bool topbar;
+- Client *clients;
++ Clientlist *cl;
+ Client *sel;
+- Client *stack;
+ Monitor *next;
+ Window barwin;
+ const Layout *lt[2];
+_AT_@ -157,6 +157,11 @@
+ int monitor;
+ } Rule;
+
++struct Clientlist {
++ Client *clients;
++ Client *stack;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
+_AT_@ -164,6 +169,7 @@
+ static void arrangemon(Monitor *m);
+ static void attach(Client *c);
+ static void attachabove(Client *c);
++static void attachclients(Monitor *m);
+ static void attachstack(Client *c);
+ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+_AT_@ -206,7 +212,7 @@
+ static void monocle(Monitor *m);
+ static void motionnotify(XEvent *e);
+ static void movemouse(const Arg *arg);
+-static Client *nexttiled(Client *c);
++static Client *nexttiled(Client *c, Monitor *m);
+ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
+_AT_@ -290,6 +296,7 @@
+ static DC dc;
+ static Monitor *mons = NULL, *selmon = NULL;
+ static Window root;
++static Clientlist *cl;
+
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+_AT_@ -410,9 +417,9 @@
+ void
+ arrange(Monitor *m) {
+ if(m)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ else for(m = mons; m; m = m->next)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ if(m) {
+ arrangemon(m);
+ restack(m);
+_AT_@ -429,27 +436,60 @@
+
+ void
+ attach(Client *c) {
+- c->next = c->mon->clients;
+- c->mon->clients = c;
++ c->next = c->mon->cl->clients;
++ c->mon->cl->clients = c;
+ }
+
+ void
+ attachabove(Client *c) {
+- if(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating) {
++ if(c->mon->sel == NULL || c->mon->sel == c->mon->cl->clients || c->mon->sel->isfloating) {
+ attach(c);
+ return;
+ }
+
+ Client *at;
+- for(at = c->mon->clients; at->next != c->mon->sel; at = at->next);
++ for(at = c->mon->cl->clients; at->next != c->mon->sel; at = at->next);
+ c->next = at->next;
+ at->next = c;
+ }
+
+ void
++attachclients(Monitor *m) {
++ /* attach clients to the specified monitor */
++ Monitor *tm;
++ Client *c;
++ unsigned int utags = 0;
++ Bool rmons = False;
++ if(!m)
++ return;
++
++ /* collect information about the tags in use */
++ for(tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ utags |= m->tagset[m->seltags];
++
++ for(c = m->cl->clients; c; c = c->next)
++ if(ISVISIBLE(c, m)) {
++ /* if client is also visible on other tags that are displayed on
++ * other monitors, remove these tags */
++ if(c->tags & utags) {
++ c->tags = c->tags & m->tagset[m->seltags];
++ rmons = True;
++ }
++ unfocus(c, True);
++ c->mon = m;
++ }
++
++ if(rmons)
++ for(tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ arrange(tm);
++}
++
++void
+ attachstack(Client *c) {
+- c->snext = c->mon->stack;
+- c->mon->stack = c;
++ c->snext = c->mon->cl->stack;
++ c->mon->cl->stack = c;
+ }
+
+ void
+_AT_@ -512,8 +552,8 @@
+ view(&a);
+ selmon->lt[selmon->sellt] = &foo;
+ for(m = mons; m; m = m->next)
+- while(m->stack)
+- unmanage(m->stack, False);
++ while(m->cl->stack)
++ unmanage(m->cl->stack, False);
+ if(dc.font.set)
+ XFreeFontSet(dpy, dc.font.set);
+ else
+_AT_@ -570,7 +610,7 @@
+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
+ }
+ else if(cme->message_type == netatom[NetActiveWindow]) {
+- if(!ISVISIBLE(c)) {
++ if(!ISVISIBLE(c, c->mon)) {
+ c->mon->seltags ^= 1;
+ c->mon->tagset[c->mon->seltags] = c->tags;
+ }
+_AT_@ -653,7 +693,7 @@
+ c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
+ if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
+ configure(c);
+- if(ISVISIBLE(c))
++ if(ISVISIBLE(c, m))
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
+ }
+ else
+_AT_@ -674,12 +714,18 @@
+
+ Monitor *
+ createmon(void) {
+- Monitor *m;
++ Monitor *m, *tm;
+ int i;
+
+ if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
+- m->tagset[0] = m->tagset[1] = 1;
++ m->cl = cl;
++ /* reassing tags when creating a new monitor */
++ for(i=1, tm = mons; tm; tm = tm->next, i++) {
++ tm->seltags ^= 1;
++ tm->tagset[tm->seltags] = i;
++ }
++ m->tagset[0] = m->tagset[1] = i;
+ m->mfact = mfact;
+ m->nmaster = nmaster;
+ m->showbar = showbar;
+_AT_@ -721,7 +767,7 @@
+ detach(Client *c) {
+ Client **tc;
+
+- for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
++ for(tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
+ *tc = c->next;
+ }
+
+_AT_@ -729,11 +775,11 @@
+ detachstack(Client *c) {
+ Client **tc, *t;
+
+- for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
++ for(tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
+ *tc = c->snext;
+
+ if(c == c->mon->sel) {
+- for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
++ for(t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
+ c->mon->sel = t;
+ }
+ }
+_AT_@ -770,7 +816,7 @@
+ unsigned long *col;
+ Client *c;
+
+- for(c = m->clients; c; c = c->next) {
++ for(c = m->cl->clients; c; c = c->next) {
+ occ |= c->tags;
+ if(c->isurgent)
+ urg |= c->tags;
+_AT_@ -886,8 +932,8 @@
+
+ void
+ focus(Client *c) {
+- if(!c || !ISVISIBLE(c))
+- for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
++ if(!c || !ISVISIBLE(c, selmon))
++ for(c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
+ /* was if(selmon->sel) */
+ if(selmon->sel && selmon->sel != c)
+ unfocus(selmon->sel, False);
+_AT_@ -939,17 +985,17 @@
+ if(!selmon->sel)
+ return;
+ if(arg->i > 0) {
+- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
++ for(c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
+ if(!c)
+- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
++ for(c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
+ }
+ else {
+- for(i = selmon->clients; i != selmon->sel; i = i->next)
+- if(ISVISIBLE(i))
++ for(i = selmon->cl->clients; i != selmon->sel; i = i->next)
++ if(ISVISIBLE(i, selmon))
+ c = i;
+ if(!c)
+ for(; i; i = i->next)
+- if(ISVISIBLE(i))
++ if(ISVISIBLE(i, selmon))
+ c = i;
+ }
+ if(c) {
+_AT_@ -1254,12 +1300,12 @@
+ unsigned int n = 0, r = 0;
+ Client *c;
+
+- for(c = m->clients; c; c = c->next)
+- if(ISVISIBLE(c))
++ for(c = m->cl->clients; c; c = c->next)
++ if(ISVISIBLE(c, m))
+ n++;
+ if(n > 0) /* override layout symbol */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+- for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
++ for(c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m)) {
+ /* remove border when in monocle layout */
+ if(c->bw) {
+ c->oldbw = c->bw;
+_AT_@ -1344,8 +1390,8 @@
+ }
+
+ Client *
+-nexttiled(Client *c) {
+- for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
++nexttiled(Client *c, Monitor *m) {
++ for(; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
+ return c;
+ }
+
+_AT_@ -1495,8 +1541,8 @@
+ if(m->lt[m->sellt]->arrange) {
+ wc.stack_mode = Below;
+ wc.sibling = m->barwin;
+- for(c = m->stack; c; c = c->snext)
+- if(!c->isfloating && ISVISIBLE(c)) {
++ for(c = m->cl->stack; c; c = c->snext)
++ if(!c->isfloating && ISVISIBLE(c, m)) {
+ XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
+ wc.sibling = c->win;
+ }
+_AT_@ -1546,11 +1592,9 @@
+ if(c->mon == m)
+ return;
+ unfocus(c, True);
+- detach(c);
+ detachstack(c);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+- attachabove(c);
+ attachstack(c);
+ focus(NULL);
+ arrange(NULL);
+_AT_@ -1667,6 +1711,8 @@
+ sw = DisplayWidth(dpy, screen);
+ sh = DisplayHeight(dpy, screen);
+ bh = dc.h = dc.font.height + 2;
++ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist));
+ updategeom();
+ /* init atoms */
+ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
+_AT_@ -1717,7 +1763,7 @@
+ showhide(Client *c) {
+ if(!c)
+ return;
+- if(ISVISIBLE(c)) { /* show clients top down */
++ if(ISVISIBLE(c, c->mon)) { /* show clients top down */
+ XMoveWindow(dpy, c->win, c->x, c->y);
+ if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
+ resize(c, c->x, c->y, c->w, c->h, False);
+_AT_@ -1751,7 +1797,23 @@
+
+ void
+ tag(const Arg *arg) {
++ Monitor *m;
++ unsigned int newtags;
+ if(selmon->sel && arg->ui & TAGMASK) {
++ newtags = arg->ui & TAGMASK;
++ for(m = mons; m; m = m->next)
++ /* if tag is visible on another monitor, move client to the new monitor */
++ if(m != selmon && m->tagset[m->seltags] & newtags) {
++ /* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
++ if(newtags & selmon->tagset[selmon->seltags])
++ return;
++ /* TODO sendmon? */
++ selmon->sel->tags = newtags;
++ selmon->sel->mon = m;
++ arrange(m);
++ break;
++ }
++ /* workaround in case just one monitor is connected */
+ selmon->sel->tags = arg->ui & TAGMASK;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1781,7 +1843,7 @@
+ unsigned int i, n, h, mw, my, ty, r;
+ Client *c;
+
+- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++ for(n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
+ if(n == 0)
+ return;
+
+_AT_@ -1789,7 +1851,7 @@
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ else
+ mw = m->ww;
+- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, r = 0) {
++ for(i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++, r = 0) {
+ if(n == 1) {
+ if (c->bw) {
+ /* remove border when only one window is on the current tag */
+_AT_@ -1860,12 +1922,17 @@
+
+ void
+ toggletag(const Arg *arg) {
++ Monitor *m;
+ unsigned int newtags;
+
+ if(!selmon->sel)
+ return;
+ newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
+ if(newtags) {
++ /* prevent adding tags that are in use on other monitors */
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtags & m->tagset[m->seltags])
++ return;
+ selmon->sel->tags = newtags;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1874,10 +1941,15 @@
+
+ void
+ toggleview(const Arg *arg) {
++ Monitor *m;
+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+ int i;
+
+ if(newtagset) {
++ /* prevent displaying the same tags on multiple monitors */
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtagset & m->tagset[m->seltags])
++ return;
+ if(newtagset == ~0) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = 0;
+_AT_@ -1896,6 +1968,7 @@
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
++ attachclients(selmon);
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+ focus(NULL);
+_AT_@ -2010,8 +2083,10 @@
+ if(n <= nn) {
+ for(i = 0; i < (nn - n); i++) { /* new monitors available */
+ for(m = mons; m && m->next; m = m->next);
+- if(m)
++ if(m) {
+ m->next = createmon();
++ attachclients(m->next);
++ }
+ else
+ mons = createmon();
+ }
+_AT_@ -2032,17 +2107,13 @@
+ else { /* less monitors available nn < n */
+ for(i = nn; i < n; i++) {
+ for(m = mons; m && m->next; m = m->next);
+- while(m->clients) {
+- dirty = True;
+- c = m->clients;
+- m->clients = c->next;
+- detachstack(c);
+- c->mon = mons;
+- attachabove(c);
+- attachstack(c);
+- }
+ if(m == selmon)
+ selmon = mons;
++ for(c = m->cl->clients; c; c = c->next) {
++ dirty = True;
++ if(ISVISIBLE(c, m))
++ c->mon = selmon;
++ }
+ cleanupmon(m);
+ }
+ }
+_AT_@ -2183,11 +2254,30 @@
+
+ void
+ view(const Arg *arg) {
++ Monitor *m;
++ unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
+ int i;
+ unsigned int tmptag;
+
+ if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ return;
++
++ /* swap tags when trying to display a tag from another monitor */
++ if(arg->ui & TAGMASK)
++ newtagset = arg->ui & TAGMASK;
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtagset & m->tagset[m->seltags]) {
++ /* prevent displaying all tags (MODKEY-0) when multiple monitors
++ * are connected */
++ if(newtagset & selmon->tagset[selmon->seltags])
++ return;
++ m->seltags ^= 1;
++ m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
++ attachclients(m);
++ arrange(m);
++ break;
++ }
++
+ selmon->seltags ^= 1; /* toggle sel tagset */
+ if(arg->ui & TAGMASK) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+_AT_@ -2208,6 +2298,7 @@
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
++ attachclients(selmon);
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+ focus(NULL);
+_AT_@ -2220,7 +2311,7 @@
+ Monitor *m;
+
+ for(m = mons; m; m = m->next)
+- for(c = m->clients; c; c = c->next)
++ for(c = m->cl->clients; c; c = c->next)
+ if(c->win == w)
+ return c;
+ return NULL;
+_AT_@ -2278,19 +2369,19 @@
+ void
+ zoom(const Arg *arg) {
+ Client *c = selmon->sel;
+- prevclient = selmon->clients;
++ prevclient = selmon->cl->clients;
+ Client *at, *tmp;
+
+ if(!selmon->lt[selmon->sellt]->arrange
+ || (selmon->sel && selmon->sel->isfloating))
+ return;
+- if(c == nexttiled(selmon->clients))
+- if(!c || !(c = nexttiled(prevzoom))) {
++ if(c == nexttiled(selmon->cl->clients, selmon))
++ if(!c || !(c = nexttiled(prevzoom, selmon))) {
+ c = selmon->sel;
+- if(!c || !(c = nexttiled(c->next)))
++ if(!c || !(c = nexttiled(c->next, selmon)))
+ return;
+ }
+- for(at = selmon->clients; at && at->next && at != c && at->next != c; at = nexttiled(at->next)) ;
++ for(at = selmon->cl->clients; at && at->next && at != c && at->next != c; at = nexttiled(at->next, selmon)) ;
+ pop(c);
+ /* swap windows instead of pushing the previous one down */
+ if(at && at != c) {
+diff -r 454a5dd61441 focusmaster.c
+--- a/focusmaster.c Sun Mar 18 20:45:06 2012 +0100
++++ b/focusmaster.c Sun Mar 18 21:10:25 2012 +0100
+_AT_@ -1,4 +1,4 @@
+ static void
+ focusmaster(const Arg *arg) {
+- focus(selmon->clients);
++ focus(selmon->cl->clients);
+ }
+diff -r 454a5dd61441 push.c
+--- a/push.c Sun Mar 18 20:45:06 2012 +0100
++++ b/push.c Sun Mar 18 21:10:25 2012 +0100
+_AT_@ -2,8 +2,8 @@
+ prevtiled(Client *c) {
+ Client *p, *r;
+
+- for(p = selmon->clients, r = NULL; p && p != c; p = p->next)
+- if(!p->isfloating && ISVISIBLE(p))
++ for(p = selmon->cl->clients, r = NULL; p && p != c; p = p->next)
++ if(!p->isfloating && ISVISIBLE(p, selmon))
+ r = p;
+ return r;
+ }
+_AT_@ -19,10 +19,10 @@
+ /* attach before c */
+ detach(sel);
+ sel->next = c;
+- if(selmon->clients == c)
+- selmon->clients = sel;
++ if(selmon->cl->clients == c)
++ selmon->cl->clients = sel;
+ else {
+- for(c = selmon->clients; c->next != sel->next; c = c->next);
++ for(c = selmon->cl->clients; c->next != sel->next; c = c->next);
+ c->next = sel;
+ }
+ } else {
+_AT_@ -43,7 +43,7 @@
+
+ if(!sel || sel->isfloating)
+ return;
+- if((c = nexttiled(sel->next))) {
++ if((c = nexttiled(sel->next, selmon))) {
+ /* attach after c */
+ detach(sel);
+ sel->next = c->next;
+diff -r 454a5dd61441 tagall.c
+--- a/tagall.c Sun Mar 18 20:45:06 2012 +0100
++++ b/tagall.c Sun Mar 18 21:10:25 2012 +0100
+_AT_@ -1,6 +1,6 @@
+ void
+ tagall(const Arg *arg) {
+- if (!selmon->clients)
++ if (!selmon->cl->clients)
+ return;
+ /* if parameter starts with F, just move floating windows */
+ int floating_only = (char *)arg->v && ((char *)arg->v)[0] == 'F' ? 1 : 0;
+_AT_@ -8,7 +8,7 @@
+ int j;
+ Client* c;
+ if(tag >= 0 && tag < LENGTH(tags))
+- for(c = selmon->clients; c; c = c->next)
++ for(c = selmon->cl->clients; c; c = c->next)
+ {
+ if(!floating_only || c->isfloating)
+ for(j = 0; j < LENGTH(tags); j++)
diff -r 41ea3edaafcf -r ac4f88761973 dwm.suckless.org/patches/single_tagset.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/single_tagset.md Sun Mar 18 21:50:30 2012 +0100
_AT_@ -0,0 +1,44 @@
+single tagset
+=============
+
+Description
+-----------
+
+This patch addresses the multi-monitor setup. Instead of having separate tags
+for every monitor there is just one list of tags for all monitors. Instead of
+moving windows from one monitor to the other, the desired tag from the
+other monitor can just be selected and all windows will be drawn on the
+current monitor.
+
+Several deep changes needed to be made:
+1. Macro ISVISIBLE expects a second parameter, the monitor
+2. Monitor->clients and Monitor->stack were moved to the global variable
+ Clientlist cl. All monitors refer to this one list.
+3. A new method attachclients was added. When changing between tags this
+ function ensures that all clients are pointing to the right monitor.
+
+Please be aware that this patch probably breaks any other patch!
+
+* [dwm-6.0-single_tagset.diff](dwm-6.0-single_tagset.diff) (14K) (20120318)
+
+Special Version
+---------------
+This is a special version of the patch that was created with following patches being applied:
+* [attachabove](attachabove)
+* [float_border_color](float_border_color)
+* [focusmaster](
https://bitbucket.org/jceb81/dwm-patches/src/90fb0feedff9/focusmaster.patch)
+* [moveresize](moveresize)
+* [noborder](noborder)
+* [pertag](pertag)
+* [push](push)
+* [save_floats](save_floats)
+* [statusallmons](statusallmons)
+* [swapfocus](swapfocus)
+* [tagall](tagall)
+* [zoomswap](zoomswap)
+
+[dwm-6.0-single_tagset_all.diff](dwm-6.0-single_tagset_all.diff) (18K) (20120318)
+
+Authors
+-------
+ * Jan Christoph Ebersbach - <jceb_AT_e-jc.de>
Received on Sun Mar 18 2012 - 21:50:36 CET