I (Luke Shumaker) wrote this patch to fix a bug where if Xinerama is (mis)configured such that there are two screens with the same size and position, then wmii removes both of them from the list, resulting in nscreens=0, which causes a segfault when it tries to dereference screen[0]. This is the case by default with a recent version of the drivers for my Nvidia 9400GT (where the DVI and VGA ports mirror eachother). Plus, the code's more efficient now, because it does everything in place, instead of needing to malloc another list. diff -ru wmii-hg-2823.orig/cmd/wmii/main.c wmii-hg-2823/cmd/wmii/main.c --- wmii-hg-2823.orig/cmd/wmii/main.c 1989-12-31 19:00:00.000000000 -0500 +++ wmii-hg-2823/cmd/wmii/main.c 2015-01-15 23:51:34.325953828 -0500 @@ -163,7 +163,7 @@ void init_screens(void) { static int old_n, old_nscreens; - Rectangle *rects, *r; + Rectangle *rects; View *v; int i, j, n, m; @@ -178,23 +178,27 @@ /* Reallocate screens, zero any new ones. */ rects = xinerama_screens(&n); - r = malloc(n * sizeof *r); /* Weed out subsumed/cloned screens */ - for(m=-1; m < n; n=m) { - for(i=n-1, m=0; i >= 0; i--) { - for(j=0; j < n; j++) - if (i != j && - eqrect(rects[i], - rect_intersection(rects[i], rects[j]))) - break; - if (j == n) - r[m++] = rects[i]; + for(m=0, i=0; i < n; i++) { + for(j=0; j < n; j++) { + if (i != j && + /* rects[i] is entirely contained in rects[j] */ + eqrect(rects[i], rect_intersection(rects[i], rects[j])) && + /* but if they are the same, accept the first */ + (i > j || ! eqrect(rects[i], rects[j]))) { + /* remove rects[i] from rects[] */ + break; + } + } + if (j < n) { /* hit "break" */ + /* remove rects[i] from rects[] */ + n--; + for(j=i; j < n; j++) + rects[j] = rects[j+1]; + i--; } - for(i=m-1, j=0; i >= 0; i--) - rects[j++] = r[i]; } - free(r); m = nscreens; nscreens_new = keep_screens ? max(n, nscreens) : n;