+ if((c = wintoclient(ev->window)))
+ unmanage(c, False);
+}
+
+void
+updatebars(void) {
+ Monitor *m;
+ XSetWindowAttributes wa;
+
+ wa.override_redirect = True;
+ wa.background_pixmap = ParentRelative;
+ wa.event_mask = ButtonPressMask|ExposureMask;
+ for(m = mons; m; m = m->next) {
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+ XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
+ XMapRaised(dpy, m->barwin);
+ }
+}
+
+void
+updatebarpos(Monitor *m) {
+ m->wy = m->my;
+ m->wh = m->mh;
+ if(m->showbar) {
+ m->wh -= bh;
+ m->by = m->topbar ? m->wy : m->wy + m->wh;
+ m->wy = m->topbar ? m->wy + bh : m->wy;
+ }
+ else
+ m->by = -bh;
+}
+
+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) */
+#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;
+ }
+ }
+ XFree(info);
+ free(flags);
+ }
+ 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);
+ }
+ /* select focused monitor */
+ cleanupmons();
+ selmon = mons = newmons;
+ selmon = wintomon(root);
+ return True;