implemented different version of updategeom
authorAnselm R Garbe <anselm@garbe.us>
Mon, 21 Sep 2009 18:51:17 +0000 (19:51 +0100)
committerAnselm R Garbe <anselm@garbe.us>
Mon, 21 Sep 2009 18:51:17 +0000 (19:51 +0100)
config.mk
dwm.c

index 086424d..2b93435 100644 (file)
--- 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 (file)
--- 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