From a3a859b4e93d65fd22619449d18e0437d5c2774b Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:13:03 +0100 Subject: [PATCH 01/16] added isdestroyed flag to unmanage --- dwm.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/dwm.c b/dwm.c index 7a4600f..a2c1e00 100644 --- a/dwm.c +++ b/dwm.c @@ -218,7 +218,7 @@ static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c); -static void unmanage(Client *c); +static void unmanage(Client *c, Bool isdestroyed); static void unmapnotify(XEvent *e); static void updategeom(void); static void updatebarpos(Monitor *m); @@ -466,7 +466,7 @@ cleanup(void) { selmon->lt[selmon->sellt] = &foo; for(m = mons; m; m = m->next) while(m->stack) - unmanage(m->stack); + unmanage(m->stack, False); if(dc.font.set) XFreeFontSet(dpy, dc.font.set); else @@ -595,7 +595,7 @@ destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; if((c = wintoclient(ev->window))) - unmanage(c); + unmanage(c, True); } void @@ -1626,24 +1626,25 @@ unfocus(Client *c) { } void -unmanage(Client *c) { +unmanage(Client *c, Bool isdestroyed) { XWindowChanges wc; - wc.border_width = c->oldbw; /* The server grab construct avoids race conditions. */ - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ detach(c); detachstack(c); - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); + if(!isdestroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } free(c); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); focus(NULL); - arrange(); } void @@ -1652,7 +1653,7 @@ unmapnotify(XEvent *e) { XUnmapEvent *ev = &e->xunmap; if((c = wintoclient(ev->window))) - unmanage(c); + unmanage(c, False); } void -- 2.20.1 From 7fe81359d46df4b3173c233a7787d81ce322c827 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:16:54 +0100 Subject: [PATCH 02/16] sync when a client is being killed --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index a2c1e00..5ea74cb 100644 --- a/dwm.c +++ b/dwm.c @@ -1041,6 +1041,7 @@ killclient(const Arg *arg) { } else XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); } void -- 2.20.1 From eb260b1a414fb82fc01d3638e3e77495297c45d5 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:18:05 +0100 Subject: [PATCH 03/16] renaming isdestroyed into destroyed --- dwm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 5ea74cb..413e795 100644 --- a/dwm.c +++ b/dwm.c @@ -218,7 +218,7 @@ static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c); -static void unmanage(Client *c, Bool isdestroyed); +static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); static void updategeom(void); static void updatebarpos(Monitor *m); @@ -1627,13 +1627,13 @@ unfocus(Client *c) { } void -unmanage(Client *c, Bool isdestroyed) { +unmanage(Client *c, Bool destroyed) { XWindowChanges wc; /* The server grab construct avoids race conditions. */ detach(c); detachstack(c); - if(!isdestroyed) { + if(!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); XSetErrorHandler(xerrordummy); -- 2.20.1 From 01056b66369f650d02145f27d1399141f93015df Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:30:18 +0100 Subject: [PATCH 04/16] hard-core destruction --- dwm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 413e795..cb296b5 100644 --- a/dwm.c +++ b/dwm.c @@ -1039,9 +1039,15 @@ killclient(const Arg *arg) { ev.xclient.data.l[1] = CurrentTime; XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev); } - else + else { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } } void -- 2.20.1 From 956a430054d5bb1869289475f4f7989552489f77 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 8 Sep 2009 13:33:58 +0100 Subject: [PATCH 05/16] update --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index cb296b5..7d19b07 100644 --- a/dwm.c +++ b/dwm.c @@ -1652,6 +1652,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); + arrange(); } void -- 2.20.1 From c3feffa1e25da4c39a31d7ae76637bacb0444042 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 15 Sep 2009 13:50:41 +0100 Subject: [PATCH 06/16] applied Tony Lainson's config.def.h patch --- config.def.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index cca37df..cca63f7 100644 --- a/config.def.h +++ b/config.def.h @@ -24,7 +24,7 @@ static const Rule rules[] = { /* layout(s) */ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const Bool resizehints = True; /* False means respect size hints in tiled resizals */ +static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ static const Layout layouts[] = { /* symbol arrange function */ @@ -84,8 +84,7 @@ static Key keys[] = { }; /* button definitions */ -/* click can be a tag number (starting at 0), - * ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static Button buttons[] = { /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, -- 2.20.1 From e7300e0f6f10900b50d15ea3ae8949049431e38b Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Wed, 16 Sep 2009 15:59:54 +0100 Subject: [PATCH 07/16] implemented dynamic layout symbol stuff --- dwm.1 | 15 +++++++-------- dwm.c | 37 ++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/dwm.1 b/dwm.1 index 5f3cc2c..7ed8ead 100644 --- a/dwm.1 +++ b/dwm.1 @@ -20,14 +20,13 @@ Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P Each screen contains a small status bar which displays all available tags, the -layout, the number of visible windows, the title of the focused window, and the -text read from the root window name property, if the screen is focused. A -floating window is indicated with an empty square and a maximised floating -window is indicated with a filled square before the windows title. The -selected tags are indicated with a different color. The tags of the focused -window are indicated with a filled square in the top left corner. The tags -which are applied to one or more windows are indicated with an empty square in -the top left corner. +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS diff --git a/dwm.c b/dwm.c index 7d19b07..1cb07d3 100644 --- a/dwm.c +++ b/dwm.c @@ -121,6 +121,7 @@ typedef struct { } Layout; struct Monitor { + const char *ltsymbol; float mfact; int num; int by; /* bar geometry */ @@ -238,7 +239,7 @@ static void zoom(const Arg *arg); /* variables */ static const char broken[] = "broken"; -static char stext[256], ntext[8]; +static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ @@ -384,6 +385,7 @@ arrange(void) { showhide(m->stack); focus(NULL); for(m = mons; m; m = m->next) { + m->ltsymbol = m->lt[m->sellt]->symbol; if(m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); restack(m); @@ -649,13 +651,11 @@ dirtomon(int dir) { void drawbar(Monitor *m) { int x; - unsigned int i, n = 0, occ = 0, urg = 0; + unsigned int i, occ = 0, urg = 0; unsigned long *col; Client *c; for(c = m->clients; c; c = c->next) { - if(ISVISIBLE(c)) - n++; occ |= c->tags; if(c->isurgent) urg |= c->tags; @@ -669,15 +669,10 @@ drawbar(Monitor *m) { occ & 1 << i, urg & 1 << i, col); dc.x += dc.w; } - if(blw > 0) { - dc.w = blw; - drawtext(m->lt[m->sellt]->symbol, dc.norm, False); - dc.x += dc.w; - } - snprintf(ntext, sizeof ntext, "%u", n); - dc.w = TEXTW(ntext); - drawtext(ntext, dc.norm, False); - x = (dc.x += dc.w); + dc.w = blw = TEXTW(m->ltsymbol); + drawtext(m->ltsymbol, dc.norm, False); + dc.x += dc.w; + x = dc.x; if(m == selmon) { /* status is only drawn on selected monitor */ dc.w = TEXTW(stext); dc.x = m->ww - dc.w; @@ -1137,8 +1132,17 @@ maprequest(XEvent *e) { void monocle(Monitor *m) { + static char ntext[8]; + unsigned int n = 0; Client *c; + for(c = m->clients; c; c = c->next) + if(ISVISIBLE(c)) + n++; + if(n > 0) { /* override layout symbol */ + snprintf(ntext, sizeof ntext, "[%d]", n); + m->ltsymbol = ntext; + } for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); } @@ -1431,8 +1435,6 @@ setmfact(const Arg *arg) { void setup(void) { - unsigned int i; - int w; XSetWindowAttributes wa; /* clean up any zombies immediately */ @@ -1469,10 +1471,6 @@ setup(void) { if(!dc.font.set) XSetFont(dpy, dc.gc, dc.font.xfont->fid); /* init bars */ - for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { - w = TEXTW(layouts[i].symbol); - blw = MAX(blw, w); - } updatebars(); updatestatus(); /* EWMH support per view */ @@ -1752,6 +1750,7 @@ updategeom(void) { m->topbar = topbar; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; + m->ltsymbol = layouts[0].symbol; updatebarpos(m); } /* reassign left over clients of disappeared monitors */ -- 2.20.1 From 82ec7a7ed4f3ba376faadfc2aca783b24618575f Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Fri, 18 Sep 2009 21:18:00 +0100 Subject: [PATCH 08/16] new experimental updategeom() additions that should avoid several problems with Xinerama, this is EXPERIMENTAL and might break something, the algorithms in use are quite complex and cumbersome, patches and comments welcome --- dwm.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/dwm.c b/dwm.c index 1cb07d3..2b4d6b0 100644 --- a/dwm.c +++ b/dwm.c @@ -221,7 +221,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); -static void updategeom(void); +static Bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updatenumlockmask(void); @@ -535,14 +535,15 @@ configurenotify(XEvent *e) { if(ev->window == root) { sw = ev->width; sh = ev->height; - updategeom(); - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); - updatebars(); - for(m = mons; m; m = m->next) - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - arrange(); + if(updategeom()) { + if(dc.drawable != 0) + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + updatebars(); + for(m = mons; m; m = m->next) + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + arrange(); + } } } @@ -1692,26 +1693,73 @@ updatebarpos(Monitor *m) { m->by = -bh; } -void +Bool updategeom(void) { - int i, n = 1; + int i, j, nn = 1, n = 1; Client *c; Monitor *newmons = NULL, *m = NULL, *tm; #ifdef XINERAMA - int nn; XineramaScreenInfo *info = NULL; + Bool *flags = NULL; if(XineramaIsActive(dpy)) info = XineramaQueryScreens(dpy, &n); - for(i = 1, nn = n; i < n; i++) - if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org - && info[i - 1].width == info[i].width && info[i - 1].height == info[i].height) - --nn; - n = nn; /* we only consider unique geometries as separate screens */ + flags = (Bool *)malloc(sizeof(Bool) * n); + for(i = 0; i < n; i++) + flags[i] = False; + /* next double-loop seeks any combination of retrieved Xinerama info + * with existing monitors, this is used to avoid unnecessary + * re-allocations of monitor structs */ + for(i = 0, nn = n; i < n; i++) + for(j = 0, m = mons; m; m = m->next, j++) + if(!flags[j]) { + if((flags[j] = ( + info[i].x_org == m->mx + && info[i].y_org == m->my + && info[i].width == m->mw + && info[i].height == m->mh) + )) + --nn; + } + if(nn == 0) { /* no need to re-allocate monitors */ + j = 0; + for(i = 0, m = mons; m; m = m->next, i++) { + m->num = info[i].screen_number; + if(info[i].x_org != m->mx + || info[i].y_org != m->my + || info[i].width != m->mw + || info[i].height != m->mh) + { + m->mx = m->wx = info[i].x_org; + m->my = m->wy = info[i].y_org; + m->mw = m->ww = info[i].width; + m->mh = m->wh = info[i].height; + updatebarpos(m); + j++; + } + } + XFree(info); + free(flags); + return j > 0; + } + /* next algorithm only considers unique geometries as separate screens */ + for(i = 0; i < n; i++) + flags[i] = False; /* used for ignoring certain monitors */ + for(i = 0, nn = n; i < n; i++) + for(j = 0; j < n; j++) + if(i != j && !flags[i]) { + if((flags[i] = ( + info[i].x_org == info[j].x_org + && info[i].y_org == info[j].y_org + && info[i].width == info[j].width + && info[i].height == info[j].height) + )) + --nn; + } #endif /* XINERAMA */ /* allocate monitor(s) for the new geometry setup */ - for(i = 0; i < n; i++) { + for(i = 0; i < nn; i++) { if(!(m = (Monitor *)malloc(sizeof(Monitor)))) die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); m->next = newmons; @@ -1720,14 +1768,18 @@ updategeom(void) { /* initialise monitor(s) */ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - for(i = 0, m = newmons; m; m = m->next, i++) { - m->num = info[i].screen_number; - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; + for(i = 0, m = newmons; m && i < n; i++) { + if(!flags[i]) { /* only use screens that aren't dublettes */ + m->num = info[i].screen_number; + m->mx = m->wx = info[i].x_org; + m->my = m->wy = info[i].y_org; + m->mw = m->ww = info[i].width; + m->mh = m->wh = info[i].height; + m = m->next; + } } XFree(info); + free(flags); } else #endif /* XINERAMA */ @@ -1767,6 +1819,7 @@ updategeom(void) { cleanupmons(); selmon = mons = newmons; selmon = wintomon(root); + return True; } void -- 2.20.1 From f0a4845e7dec3a4c7316311fcf1108148bb29730 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 19 Sep 2009 11:52:16 +0100 Subject: [PATCH 09/16] added TODO to updategeom in order to implement a decent version of it soon --- dwm.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dwm.c b/dwm.c index 2b4d6b0..7363396 100644 --- a/dwm.c +++ b/dwm.c @@ -1699,6 +1699,40 @@ updategeom(void) { Client *c; Monitor *newmons = NULL, *m = NULL, *tm; + /* TODO: + * This function needs to be seriously re-designed: + * + * #ifdef XINERAMA + * 1. Determine number of already existing monitors n + * 2. Determine number of monitors Xinerama reports nn + * 3. if(n <= nn) { + * if(n < nn) { + * append nn-n monitors to current struct + * flag dirty + * } + * for(i = 0; i < nn; i++) { + * if(oldgeom != newgeom) { + * apply newgeom; + * flag dirty; + * } + * } + * } + * else { + * detach all clients + * destroy current monitor struct + * create new monitor struct + * attach all clients to first monitor + * flag dirty; + * } + * return dirty flag to caller + * if dirty is seen by caller: + * re-arrange bars/pixmaps + * arrange() + * #else + * don't share between XINERAMA and non-XINERAMA handling if it gets + * too ugly + * #endif + */ #ifdef XINERAMA XineramaScreenInfo *info = NULL; Bool *flags = NULL; -- 2.20.1 From 07ad2981337c9154fe84078454e646771b5a3425 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Mon, 21 Sep 2009 19:51:17 +0100 Subject: [PATCH 10/16] implemented different version of updategeom --- config.mk | 8 +- dwm.c | 234 ++++++++++++++++++++---------------------------------- 2 files changed, 89 insertions(+), 153 deletions(-) diff --git a/config.mk b/config.mk index 086424d..2b93435 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} # flags CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -#LDFLAGS = -g ${LIBS} -LDFLAGS = -s ${LIBS} +CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -g ${LIBS} +#LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" diff --git a/dwm.c b/dwm.c index 7363396..8ddc072 100644 --- a/dwm.c +++ b/dwm.c @@ -163,6 +163,7 @@ static void clearurgent(Client *c); static void configure(Client *c); static void configurenotify(XEvent *e); static void configurerequest(XEvent *e); +static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); @@ -592,6 +593,22 @@ configurerequest(XEvent *e) { XSync(dpy, False); } +Monitor * +createmon(void) { + Monitor *m; + + 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->mfact = mfact; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + m->ltsymbol = layouts[0].symbol; + return m; +} + void destroynotify(XEvent *e) { Client *c; @@ -1005,6 +1022,19 @@ isprotodel(Client *c) { return ret; } +#ifdef XINERAMA +static Bool +isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) { + unsigned int i; + + for(i = 0; i < len; i++) + if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org + && unique[i].width == info->width && unique[i].height == info->height) + return False; + return True; +} +#endif /* XINERAMA */ + void keypress(XEvent *e) { unsigned int i; @@ -1695,165 +1725,71 @@ updatebarpos(Monitor *m) { Bool updategeom(void) { - int i, j, nn = 1, n = 1; - Client *c; - Monitor *newmons = NULL, *m = NULL, *tm; - - /* TODO: - * This function needs to be seriously re-designed: - * - * #ifdef XINERAMA - * 1. Determine number of already existing monitors n - * 2. Determine number of monitors Xinerama reports nn - * 3. if(n <= nn) { - * if(n < nn) { - * append nn-n monitors to current struct - * flag dirty - * } - * for(i = 0; i < nn; i++) { - * if(oldgeom != newgeom) { - * apply newgeom; - * flag dirty; - * } - * } - * } - * else { - * detach all clients - * destroy current monitor struct - * create new monitor struct - * attach all clients to first monitor - * flag dirty; - * } - * return dirty flag to caller - * if dirty is seen by caller: - * re-arrange bars/pixmaps - * arrange() - * #else - * don't share between XINERAMA and non-XINERAMA handling if it gets - * too ugly - * #endif - */ -#ifdef XINERAMA - XineramaScreenInfo *info = NULL; - Bool *flags = NULL; - - if(XineramaIsActive(dpy)) - info = XineramaQueryScreens(dpy, &n); - flags = (Bool *)malloc(sizeof(Bool) * n); - for(i = 0; i < n; i++) - flags[i] = False; - /* next double-loop seeks any combination of retrieved Xinerama info - * with existing monitors, this is used to avoid unnecessary - * re-allocations of monitor structs */ - for(i = 0, nn = n; i < n; i++) - for(j = 0, m = mons; m; m = m->next, j++) - if(!flags[j]) { - if((flags[j] = ( - info[i].x_org == m->mx - && info[i].y_org == m->my - && info[i].width == m->mw - && info[i].height == m->mh) - )) - --nn; - } - if(nn == 0) { /* no need to re-allocate monitors */ - j = 0; - for(i = 0, m = mons; m; m = m->next, i++) { - m->num = info[i].screen_number; - if(info[i].x_org != m->mx - || info[i].y_org != m->my - || info[i].width != m->mw - || info[i].height != m->mh) - { - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; - updatebarpos(m); - j++; - } - } - XFree(info); - free(flags); - return j > 0; - } - /* next algorithm only considers unique geometries as separate screens */ - for(i = 0; i < n; i++) - flags[i] = False; /* used for ignoring certain monitors */ - for(i = 0, nn = n; i < n; i++) - for(j = 0; j < n; j++) - if(i != j && !flags[i]) { - if((flags[i] = ( - info[i].x_org == info[j].x_org - && info[i].y_org == info[j].y_org - && info[i].width == info[j].width - && info[i].height == info[j].height) - )) - --nn; - } -#endif /* XINERAMA */ - /* allocate monitor(s) for the new geometry setup */ - for(i = 0; i < nn; i++) { - if(!(m = (Monitor *)malloc(sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); - m->next = newmons; - newmons = m; - } - /* initialise monitor(s) */ + Bool dirty = False; + #ifdef XINERAMA if(XineramaIsActive(dpy)) { - for(i = 0, m = newmons; m && i < n; i++) { - if(!flags[i]) { /* only use screens that aren't dublettes */ - m->num = info[i].screen_number; - m->mx = m->wx = info[i].x_org; - m->my = m->wy = info[i].y_org; - m->mw = m->ww = info[i].width; - m->mh = m->wh = info[i].height; - m = m->next; + int i, j, n, nn; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + info = XineramaQueryScreens(dpy, &nn); + for(n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) + die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); + for(i = 0, j = 0; i < nn; i++) + if(isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + if(n <= nn) { + for(i = 0; i < (nn - n); i++) { /* new monitors available */ + for(m = mons; m && m->next; m = m->next); + if(m) + m->next = createmon(); + else + mons = createmon(); } + for(i = 0, m = mons; i < nn && m; m = m->next, i++) + if(i >= n + || (unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh)) + { + dirty = True; + m->num = unique[i].screen_number; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } } - XFree(info); - free(flags); + else { /* less monitors available */ + cleanup(); + setup(); + } + free(unique); } else #endif /* XINERAMA */ /* default monitor setup */ { - m->num = 0; - m->mx = m->wx = 0; - m->my = m->wy = 0; - m->mw = m->ww = sw; - m->mh = m->wh = sh; - } - /* bar geometry setup */ - for(m = newmons; m; m = m->next) { - m->sel = m->stack = m->clients = NULL; - m->seltags = 0; - m->sellt = 0; - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->showbar = showbar; - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - m->ltsymbol = layouts[0].symbol; - updatebarpos(m); - } - /* reassign left over clients of disappeared monitors */ - for(tm = mons; tm; tm = tm->next) - while(tm->clients) { - c = tm->clients; - tm->clients = c->next; - detachstack(c); - c->mon = newmons; - attach(c); - attachstack(c); + if(!mons) + mons = createmon(); + if(mons->mw != sw || mons->mh != sh) { + dirty = True; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); } - /* select focused monitor */ - cleanupmons(); - selmon = mons = newmons; - selmon = wintomon(root); - return True; + } + if(dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; } void -- 2.20.1 From 6f55de83100547e6f78ebc276dfdbca5ee2581d9 Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 09:16:48 +0100 Subject: [PATCH 11/16] added missing scan --- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 8ddc072..0d2f670 100644 --- a/dwm.c +++ b/dwm.c @@ -1769,6 +1769,7 @@ updategeom(void) { else { /* less monitors available */ cleanup(); setup(); + scan(); } free(unique); } -- 2.20.1 From c45d46ad9a44b9897c8c12eacb60b5cbdd31be7c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 09:53:11 +0100 Subject: [PATCH 12/16] use buffer instead of pointer for mon->ltsymbol --- dwm.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/dwm.c b/dwm.c index 0d2f670..48f50da 100644 --- a/dwm.c +++ b/dwm.c @@ -121,7 +121,7 @@ typedef struct { } Layout; struct Monitor { - const char *ltsymbol; + char ltsymbol[16]; float mfact; int num; int by; /* bar geometry */ @@ -386,7 +386,7 @@ arrange(void) { showhide(m->stack); focus(NULL); for(m = mons; m; m = m->next) { - m->ltsymbol = m->lt[m->sellt]->symbol; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); if(m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); restack(m); @@ -605,7 +605,7 @@ createmon(void) { m->topbar = topbar; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; - m->ltsymbol = layouts[0].symbol; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); return m; } @@ -1163,17 +1163,14 @@ maprequest(XEvent *e) { void monocle(Monitor *m) { - static char ntext[8]; unsigned int n = 0; Client *c; for(c = m->clients; c; c = c->next) if(ISVISIBLE(c)) n++; - if(n > 0) { /* override layout symbol */ - snprintf(ntext, sizeof ntext, "[%d]", n); - m->ltsymbol = ntext; - } + if(n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); } -- 2.20.1 From 30fed9a211e524f2b1d7387fc62468c2225ab93d Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 20:33:42 +0100 Subject: [PATCH 13/16] implemented nn < n case, k-zed please recheck --- dwm.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/dwm.c b/dwm.c index 48f50da..5199e71 100644 --- a/dwm.c +++ b/dwm.c @@ -158,7 +158,7 @@ static void attachstack(Client *c); static void buttonpress(XEvent *e); static void checkotherwm(void); static void cleanup(void); -static void cleanupmons(void); +static void cleanupmon(Monitor *mon); static void clearurgent(Client *c); static void configure(Client *c); static void configurenotify(XEvent *e); @@ -480,22 +480,25 @@ cleanup(void) { XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurResize]); XFreeCursor(dpy, cursor[CurMove]); - cleanupmons(); + while(mons) + cleanupmon(mons); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); } void -cleanupmons(void) { +cleanupmon(Monitor *mon) { Monitor *m; - while(mons) { - m = mons->next; - XUnmapWindow(dpy, mons->barwin); - XDestroyWindow(dpy, mons->barwin); - free(mons); - mons = m; + if(mon == mons) + mons = mons->next; + else { + for(m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); } void @@ -1727,6 +1730,7 @@ updategeom(void) { #ifdef XINERAMA if(XineramaIsActive(dpy)) { int i, j, n, nn; + Client *c; Monitor *m; XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; @@ -1755,7 +1759,7 @@ updategeom(void) { || unique[i].width != m->mw || unique[i].height != m->mh)) { dirty = True; - m->num = unique[i].screen_number; + m->num = i; m->mx = m->wx = unique[i].x_org; m->my = m->wy = unique[i].y_org; m->mw = m->ww = unique[i].width; @@ -1763,10 +1767,22 @@ updategeom(void) { updatebarpos(m); } } - else { /* less monitors available */ - cleanup(); - setup(); - scan(); + 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; + cleanupmon(m); + } } free(unique); } -- 2.20.1 From 91e902f7fe0c88933b1f8b85f1b8748b832a4d3c Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Tue, 22 Sep 2009 20:34:03 +0100 Subject: [PATCH 14/16] switching to release flags --- config.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.mk b/config.mk index 2b93435..086424d 100644 --- a/config.mk +++ b/config.mk @@ -20,10 +20,10 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} # flags CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -LDFLAGS = -g ${LIBS} -#LDFLAGS = -s ${LIBS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +#LDFLAGS = -g ${LIBS} +LDFLAGS = -s ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -- 2.20.1 From 0b72be924d3f0daa63e45a09951d6cb6cc9b335e Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sat, 26 Sep 2009 19:52:04 +0100 Subject: [PATCH 15/16] Added tag 5.7 for changeset 257403d4cd96 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6ef9274..5b96aa2 100644 --- a/.hgtags +++ b/.hgtags @@ -63,3 +63,4 @@ e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2 deaa276abac17ca08fbeb936916e4c8292d293a4 5.5 5550702215773aad462f22a774dced9b87437c51 5.6 e47a47bd3ed42fd3cf023572147b75ebc2adef82 5.6.1 +257403d4cd962cac03344a871ea56cc742bae38e 5.7 -- 2.20.1 From 9e8dd3479da9f484c9aa37adcd327989149e89ef Mon Sep 17 00:00:00 2001 From: Anselm R Garbe Date: Sun, 27 Sep 2009 10:31:14 +0100 Subject: [PATCH 16/16] fixed the layout symbol bug reported by Nibble (but using a different approach as he suggested) - optimised drawbar() and arrange() handling for multiple monitors, arrange only arranges the relevant monitors when applicable, same with drawbar - need to release 5.7.1 --- config.mk | 2 +- dwm.c | 66 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/config.mk b/config.mk index 086424d..bb55cfa 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 5.7 +VERSION = 5.7.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 5199e71..b3a389d 100644 --- a/dwm.c +++ b/dwm.c @@ -152,7 +152,8 @@ typedef struct { /* 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(void); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); static void attach(Client *c); static void attachstack(Client *c); static void buttonpress(XEvent *e); @@ -379,18 +380,24 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) { } void -arrange(void) { - Monitor *m; - - for(m = mons; m; m = m->next) +arrange(Monitor *m) { + if(m) + showhide(m->stack); + else for(m = mons; m; m = m->next) showhide(m->stack); focus(NULL); - for(m = mons; m; m = m->next) { - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); - restack(m); - } + if(m) + arrangemon(m); + else for(m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) { + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if(m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); + restack(m); } void @@ -546,7 +553,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - arrange(); + arrange(NULL); } } } @@ -1139,7 +1146,7 @@ manage(Window w, XWindowAttributes *wa) { XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ XMapWindow(dpy, c->win); setclientstate(c, NormalState); - arrange(); + arrange(c->mon); } void @@ -1265,7 +1272,7 @@ propertynotify(XEvent *e) { case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL))) - arrange(); + arrange(c->mon); break; case XA_WM_NORMAL_HINTS: updatesizehints(c); @@ -1360,7 +1367,7 @@ restack(Monitor *m) { XEvent ev; XWindowChanges wc; - drawbars(); + drawbar(m); if(!m->sel) return; if(m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1427,7 +1434,7 @@ sendmon(Client *c, Monitor *m) { attach(c); attachstack(c); focus(NULL); - arrange(); + arrange(NULL); } void @@ -1442,12 +1449,14 @@ void setlayout(const Arg *arg) { if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) selmon->sellt ^= 1; - if(arg && arg->v) + if(arg && arg->v) { selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + } if(selmon->sel) - arrange(); + arrange(selmon); else - drawbars(); + drawbar(selmon); } /* arg > 1.0 will set mfact absolutly */ @@ -1461,7 +1470,7 @@ setmfact(const Arg *arg) { if(f < 0.1 || f > 0.9) return; selmon->mfact = f; - arrange(); + arrange(selmon); } void @@ -1558,7 +1567,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; - arrange(); + arrange(selmon); } } @@ -1615,7 +1624,7 @@ togglebar(const Arg *arg) { selmon->showbar = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(); + arrange(selmon); } void @@ -1626,7 +1635,7 @@ togglefloating(const Arg *arg) { if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, selmon->sel->w, selmon->sel->h, False); - arrange(); + arrange(selmon); } void @@ -1638,7 +1647,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; - arrange(); + arrange(selmon); } } @@ -1648,7 +1657,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; - arrange(); + arrange(selmon); } } @@ -1663,6 +1672,7 @@ unfocus(Client *c) { void unmanage(Client *c, Bool destroyed) { + Monitor *m = c->mon; XWindowChanges wc; /* The server grab construct avoids race conditions. */ @@ -1681,7 +1691,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); - arrange(); + arrange(m); } void @@ -1908,7 +1918,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - arrange(); + arrange(selmon); } Client * @@ -1986,7 +1996,7 @@ zoom(const Arg *arg) { detach(c); attach(c); focus(c); - arrange(); + arrange(c->mon); } int -- 2.20.1