From 20f6917910306bcb5275d726b01b42a3b5e868b4 Mon Sep 17 00:00:00 2001 From: "anselm@garbe.us" Date: Sat, 23 Jun 2012 10:12:46 +0200 Subject: [PATCH] drastically changed updategeom() handling, see comment in updategeom() for details --- config.mk | 2 +- dwm.c | 123 +++++++++++++++++++++++------------------------------- 2 files changed, 54 insertions(+), 71 deletions(-) diff --git a/config.mk b/config.mk index 7bb1c7c..35fd1e3 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.0-tip +VERSION = 6.1 # Customize below to fit your system diff --git a/dwm.c b/dwm.c index 685eb4a..1d79af6 100644 --- a/dwm.c +++ b/dwm.c @@ -235,7 +235,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c, Bool setfocus); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); -static Bool updategeom(void); +static void updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -573,23 +573,18 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - Bool dirty; - // TODO: updategeom handling sucks, needs to be simplified if(ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; - if(updategeom() || dirty) { - 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); - focus(NULL); - arrange(NULL); - } + 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); + focus(NULL); + arrange(NULL); } } @@ -1076,8 +1071,8 @@ initfont(const char *fontstr) { static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) - if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) + /* treat origin (x, y) as fixpoint for uniqueness only, first screen wins */ + if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org) return False; return True; } @@ -1887,86 +1882,74 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -Bool +void updategeom(void) { - Bool dirty = False; + /* Starting with dwm 6.1 this function uses a new (simpler) strategy: + * whenever screen changes are reported, we destroy all monitors + * and recreate all unique origin monitors and add all clients to + * the first monitor, only. In several circumstances this may suck, + * but dealing with all corner-cases sucks even more.*/ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - int i, j, n, nn; + int i, j, n; Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + Monitor *m, *oldmons = mons; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n); XineramaScreenInfo *unique = NULL; - 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(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * n))) + die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * n); + for(i = 0, j = 0; i < n; 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 = i; - 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); - } + /* create new monitor structure */ + n = j; + mons = m = createmon(); /* new first monitor */ + for(i = 1; i < n; i++) { + m->next = createmon(); + m = m->next; } - 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); - } + for(i = 0, m = mons; i < n && m; m = m->next, i++) { + 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; + m->mh = m->wh = unique[i].height; + updatebarpos(m); } free(unique); + /* re-attach old clients and cleanup old monitor structure */ + while(oldmons) { + m = oldmons; + while(m->clients) { + c = m->clients; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + oldmons = m->next; + cleanupmon(m); + } } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) + if(!mons) /* only true if !XINERAMA compile flag */ mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = True; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - if(dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; + selmon = mons; + selmon = wintomon(root); } void