---- - dwm.c | 243 ++++++++++++++++++++++++++++++++++++++++++++-------------- - 1 file changed, 187 insertions(+), 56 deletions(-) - -diff --git a/dwm.c b/dwm.c -index 5e4d494..b93b071 100644 ---- a/dwm.c -+++ b/dwm.c -_AT_@ -20,6 +20,7 @@ - * - * To understand everything else, start reading main(). - */ -+#include <X11/X.h> - #include <errno.h> - #include <locale.h> - #include <signal.h> -_AT_@ -49,7 +50,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) -_AT_@ -62,7 +63,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ - enum { SchemeNorm, SchemeSel }; /* color schemes */ - enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, -- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -+ NetWMWindowTypeDialog, NetClientList, NetWMDesktop, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ - enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -_AT_@ -82,6 +83,7 @@ typedef struct { - const Arg arg; - } Button; - -+typedef struct Clientlist Clientlist; - typedef struct Monitor Monitor; - typedef struct Client Client; - struct Client { -_AT_@ -124,9 +126,8 @@ struct Monitor { - unsigned int tagset[2]; - int showbar; - int topbar; -- Client *clients; -+ Clientlist *cl; - Client *sel; -- Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -_AT_@ -141,12 +142,18 @@ typedef struct { - int monitor; - } Rule; - -+struct Clientlist { -+ Client *clients; -+ Client *stack; -+}; -+ - /* function declarations */ - static void applyrules(Client *c); - static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int 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_@ -184,7 +191,7 @@ static void maprequest(XEvent *e); - 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_@ -226,6 +233,7 @@ static void updatesizehints(Client *c); - static void updatestatus(void); - static void updatetitle(Client *c); - static void updatewindowtype(Client *c); -+static void updatewmdesktop(Window w, int tag); - static void updatewmhints(Client *c); - static void view(const Arg *arg); - static Client *wintoclient(Window w); -_AT_@ -268,6 +276,7 @@ static Display *dpy; - static Drw *drw; - static Monitor *mons, *selmon; - static Window root, wmcheckwin; -+static Clientlist *cl; - - /* configuration, allows nested code to access above variables */ - #include "config.h" -_AT_@ -300,7 +309,7 @@ applyrules(Client *c) - { - 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; - } -_AT_@ -382,9 +391,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_@ -396,6 +405,10 @@ void - arrangemon(Monitor *m) - { - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); -+ if (m->cl) -+ for (Client* c = m->cl->clients; c; c = c->next) -+ updatewmdesktop(c->win, c->tags); -+ - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); - } -_AT_@ -403,15 +416,49 @@ arrangemon(Monitor *m) - 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 |= tm->tagset[tm->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_@ -478,8 +525,8 @@ cleanup(void) - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) -- while (m->stack) -- unmanage(m->stack, 0); -+ while (m->cl->stack) -+ unmanage(m->cl->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); -_AT_@ -565,7 +612,7 @@ configurenotify(XEvent *e) - drw_resize(drw, sw, bh); - updatebars(); - 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->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -_AT_@ -611,7 +658,7 @@ configurerequest(XEvent *e) - 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 - configure(c); -_AT_@ -631,10 +678,31 @@ configurerequest(XEvent *e) - Monitor * - createmon(void) - { -- Monitor *m; -+ Monitor *m, *tm; -+ int i; - -+ /* bail out if the number of monitors exceeds the number of tags */ -+ for (i=1, tm=mons; tm; i++, tm=tm->next); -+ if (i > LENGTH(tags)) { -+ fprintf(stderr, "dwm: failed to add monitor, number of tags exceeded "); -+ return NULL; -+ } -+ /* find the first tag that isn't in use */ -+ for (i=0; i < LENGTH(tags); i++) { -+ for (tm=mons; tm && !(tm->tagset[tm->seltags] & (1<<i)); tm=tm->next); -+ if (!tm) -+ break; -+ } -+ /* reassign all tags to monitors since there's currently no free tag for the -+ * new monitor */ -+ if (i >= LENGTH(tags)) -+ for (i=0, tm=mons; tm; tm=tm->next, i++) { -+ tm->seltags ^= 1; -+ tm->tagset[tm->seltags] = (1<<i) & TAGMASK; -+ } - m = ecalloc(1, sizeof(Monitor)); -- m->tagset[0] = m->tagset[1] = 1; -+ m->cl = cl; -+ m->tagset[0] = m->tagset[1] = (1<<i) & TAGMASK; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -_AT_@ -660,7 +728,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_@ -669,11 +737,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_@ -709,7 +777,7 @@ drawbar(Monitor *m) - drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); - } - -- 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_@ -784,8 +852,8 @@ expose(XEvent *e) - 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); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { -_AT_@ -838,16 +906,16 @@ focusstack(const Arg *arg) - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - 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_@ -1107,12 +1175,12 @@ monocle(Monitor *m) - 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, 0); - } - -_AT_@ -1194,9 +1262,9 @@ movemouse(const Arg *arg) - } - - Client * --nexttiled(Client *c) -+nexttiled(Client *c, Monitor *m) - { -- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); -+ for (; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next); - return c; - } - -_AT_@ -1360,8 +1428,8 @@ restack(Monitor *m) - 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_@ -1414,11 +1482,9 @@ sendmon(Client *c, Monitor *m) - if (c->mon == m) - return; - unfocus(c, 1); -- 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_@ -1541,6 +1607,8 @@ setup(void) - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); -+ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist)))) -+ die("fatal: could not malloc() %u bytes ", sizeof(Clientlist)); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) -_AT_@ -1559,6 +1627,7 @@ setup(void) - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -+ netatom[NetWMDesktop] = XInternAtom(dpy, "_NET_WM_DESKTOP", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -_AT_@ -1616,7 +1685,7 @@ showhide(Client *c) - { - if (!c) - return; -- if (ISVISIBLE(c)) { -+ 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) -_AT_@ -1656,7 +1725,23 @@ spawn(const Arg *arg) - 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); -_AT_@ -1677,7 +1762,7 @@ tile(Monitor *m) - 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_@ -1685,7 +1770,7 @@ tile(Monitor *m) - 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), 0); -_AT_@ -1725,12 +1810,17 @@ togglefloating(const Arg *arg) - 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_@ -1740,12 +1830,27 @@ toggletag(const Arg *arg) - 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); -+ attachclients(selmon); - arrange(selmon); -+ focus(NULL); -+ -+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+ -+ if (newtagset) { -+ selmon->tagset[selmon->seltags] = newtagset; -+ attachclients(selmon); -+ arrange(selmon); -+ focus(NULL); -+ } - } - } - -_AT_@ -1844,7 +1949,7 @@ updateclientlist() - - 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); -_AT_@ -1874,8 +1979,10 @@ updategeom(void) - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); -- if (m) -+ if (m) { - m->next = createmon(); -+ attachclients(m->next); -+ } - else - mons = createmon(); - } -_AT_@ -1895,16 +2002,13 @@ updategeom(void) - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); -- while ((c = m->clients)) { -- dirty = 1; -- 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); - } - } -_AT_@ -2016,6 +2120,14 @@ updatewindowtype(Client *c) - c->isfloating = 1; - } - -+void updatewmdesktop(Window w, int tag) { -+ long data[] = { tag }; -+ int i=0; -+ while(*data >> (i+1)) { i++; } -+ data[0] = i; -+ XChangeProperty(dpy, w, netatom[NetWMDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); -+} -+ - void - updatewmhints(Client *c) - { -_AT_@ -2038,13 +2150,32 @@ updatewmhints(Client *c) - 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->sel = selmon->sel; -+ 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; -- focus(NULL); -+ attachclients(selmon); - arrange(selmon); -+ focus(NULL); - } - - Client * -_AT_@ -2054,7 +2185,7 @@ wintoclient(Window w) - 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_@ -2121,8 +2252,8 @@ zoom(const Arg *arg) - 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); - } --- -2.33.1 - diff --git a/dwm.suckless.org/patches/single_tagset/index.md b/dwm.suckless.org/patches/single_tagset/index.md index 2a1bfbb6..2528e65f 100644 --- a/dwm.suckless.org/patches/single_tagset/index.md +++ b/dwm.suckless.org/patches/single_tagset/index.md _AT_@ -18,7 +18,6 @@ Several deep changes needed to be made: Download -------- -* [dwm-single\_tagset-20211114-a786211.diff](dwm-single_tagset-20211114-a786211.diff) (Add _NET_WM_DESKTOP attribute) * [dwm-single\_tagset-20211015-a786211.diff](dwm-single_tagset-20211015-a786211.diff) * [dwm-single\_tagset-20210623-67d76bd.diff](dwm-single_tagset-20210623-67d76bd.diff) * [dwm-single\_tagset-6.2.diff](dwm-single_tagset-6.2.diff)Received on Tue Jan 18 2022 - 03:42:19 CET
This archive was generated by hypermail 2.3.0 : Tue Jan 18 2022 - 03:48:50 CET