[hackers] [dwm] 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 || Anselm R Garbe

From: <hg_AT_suckless.org>
Date: Fri, 18 Sep 2009 19:18:09 +0000 (UTC)

changeset: 1492:62a601261c8b
tag: tip
user: Anselm R Garbe <anselm_AT_garbe.us>
date: Fri Sep 18 21:18:00 2009 +0100
files: dwm.c
description:
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

diff -r 4754e7889841 -r 62a601261c8b dwm.c
--- a/dwm.c Wed Sep 16 15:59:54 2009 +0100
+++ b/dwm.c Fri Sep 18 21:18:00 2009 +0100
@@ -221,7 +221,7 @@
 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 @@
         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 @@
                 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 @@
         /* 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 @@
         cleanupmons();
         selmon = mons = newmons;
         selmon = wintomon(root);
+ return True;
 }
 
 void
Received on Fri Sep 18 2009 - 19:18:09 UTC

This archive was generated by hypermail 2.2.0 : Fri Sep 18 2009 - 19:24:05 UTC