sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit 6b795aac38dd2793e9139a332861a3aa04e36887
parent 16fe76f7934965a50deb93aca049769bf77ed697
Author: Jan Christoph Ebersbach <jceb@e-jc.de>
Date:   Sun,  9 Feb 2014 20:07:51 +0100

update single tagset patch

Diffstat:
Adwm.suckless.org/patches/dwm-6.1-single_tagset.diff | 567+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/single_tagset.md | 7++++---
2 files changed, 571 insertions(+), 3 deletions(-)

diff --git a/dwm.suckless.org/patches/dwm-6.1-single_tagset.diff b/dwm.suckless.org/patches/dwm-6.1-single_tagset.diff @@ -0,0 +1,567 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/single_tagset +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! + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:26.156117354 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:26.148117354 +0100 +@@ -48,7 +48,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 MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) +@@ -110,6 +110,7 @@ + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Clientlist Clientlist; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -123,9 +124,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]; +@@ -140,12 +140,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); +@@ -183,7 +189,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); +@@ -266,6 +272,7 @@ + static Fnt *fnt; + static Monitor *mons, *selmon; + static Window root; ++static Clientlist *cl; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -296,7 +303,7 @@ + { + c->isfloating = r->isfloating; + c->tags |= r->tags; +- for(m = mons; m && m->num != r->monitor; m = m->next); ++ for(m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next) ; + if(m) + c->mon = m; + } +@@ -377,9 +384,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); +@@ -396,14 +403,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 +@@ -466,8 +506,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); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while(mons) + cleanupmon(mons); +@@ -527,7 +567,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; + } +@@ -609,7 +649,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 +@@ -630,11 +670,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; +@@ -658,7 +705,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; + } + +@@ -666,11 +713,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; + } + } +@@ -696,7 +743,7 @@ + unsigned int i, occ = 0, urg = 0; + 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; +@@ -779,8 +826,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); +@@ -832,17 +879,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) { +@@ -1092,12 +1139,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); + } + +@@ -1175,8 +1222,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; + } + +@@ -1328,8 +1375,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; + } +@@ -1379,7 +1426,6 @@ + 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 */ +@@ -1501,6 +1547,8 @@ + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + bh = fnt->h + 2; ++ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist)); + drw = drw_create(dpy, screen, root, sw, sh); + drw_setfont(drw, fnt); + updategeom(); +@@ -1549,9 +1597,11 @@ + 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) ++ if(c->isfloating) ++ keepfloatingposition(c); + resize(c, c->x, c->y, c->w, c->h, False); + showhide(c->snext); + } +@@ -1585,7 +1635,22 @@ + + 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; ++ 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); +@@ -1604,7 +1669,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; + +@@ -1612,7 +1677,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); +@@ -1648,12 +1713,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); +@@ -1662,9 +1732,14 @@ + + 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; + focus(NULL); + arrange(selmon); +@@ -1703,6 +1778,7 @@ + XUngrabServer(dpy); + } + free(c); ++ attachclients(selmon); + focus(NULL); + updateclientlist(); + arrange(m); +@@ -1760,7 +1836,7 @@ + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for(m = mons; m; m = m->next) +- for(c = m->clients; c; c = c->next) ++ for(c = m->cl->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +@@ -1790,8 +1866,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(); + } +@@ -1812,17 +1890,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(c->mon == m) ++ c->mon = selmon; ++ } + cleanupmon(m); + } + } +@@ -1960,11 +2034,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); + } +@@ -1975,7 +2069,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; +@@ -2037,8 +2131,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); + } +Index: dwm/config.def.h +=================================================================== +--- dwm/config.def.h.orig 2014-02-09 15:24:26.156117354 +0100 ++++ dwm/config.def.h 2014-02-09 15:24:26.148117354 +0100 +@@ -54,6 +54,7 @@ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++#include "keepfloatingposition.c" + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +Index: dwm/keepfloatingposition.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/keepfloatingposition.c 2014-02-09 15:24:26.148117354 +0100 +@@ -0,0 +1,30 @@ ++static void ++keepfloatingposition(Client *c) { ++ Monitor *m; ++ int cmmx = c->mon->mx; ++ int cmmy = c->mon->my; ++ int cmmw = c->mon->mw; ++ int cmmh = c->mon->mh; ++ int mmx, mmy; ++ if(!(cmmx <= c->x && ++ cmmx + cmmw - 1 >= c->x && ++ cmmy <= c->y && ++ cmmy + cmmh - 1 >= c->y)) ++ for(m = mons; m; m = m->next) { ++ mmx = m->mx; ++ mmy = m->my; ++ if(mmx <= c->x && ++ mmx + m->mw - 1 >= c->x && ++ mmy <= c->y && ++ mmy + m->mh - 1 >= c->y) { ++ c->x = c->x - mmx + cmmx; ++ c->y = c->y - mmy + cmmy; ++ if(c->x + c->w + 2 * c->bw > cmmx + cmmw - 1) ++ c->x -= c->x + c->w + 2 * c->bw - cmmx - cmmw; ++ if(c->y + c->h + 2 * c->bw > cmmy + cmmh - 1) ++ c->y -= c->y + c->h + 2 * c->bw - cmmy - cmmh; ++ resizeclient(c, c->x, c->y, c->w, c->h); ++ break; ++ } ++ } ++} diff --git a/dwm.suckless.org/patches/single_tagset.md b/dwm.suckless.org/patches/single_tagset.md @@ -22,8 +22,9 @@ Download Please be aware that this patch probably breaks any other patch! Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-single_tagset.diff](dwm-6.1-single_tagset.diff) (16634b) (20140209) * [dwm-10e232f9ace7-single_tagset.diff](dwm-10e232f9ace7-single_tagset.diff) (14748b) (20120406) * [dwm-6.0-single_tagset.diff](dwm-6.0-single_tagset.diff) (14417b) (20120406) @@ -32,7 +33,7 @@ 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) + * [focusmaster](https://raw.github.com/jceb/dwm-patches/master/patches/focusmaster.patch) * [moveresize](moveresize) * [noborder](noborder) * [pertag](pertag) @@ -43,7 +44,7 @@ This is a special version of the patch that was created with following patches b * [tagall](tagall) * [zoomswap](zoomswap) -[dwm-6.0-single_tagset_all.diff](https://bitbucket.org/jceb81/dwm-patches/raw/cc88093b8acb/single_tagset_all.patch) +[dwm-6.1-single_tagset_all.diff](https://raw.github.com/jceb/dwm-patches/master/patches/single_tagset_all.patch) Authors -------