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

This commit is contained in:
Anselm R Garbe 2009-09-18 21:18:00 +01:00
parent e7300e0f6f
commit 82ec7a7ed4
1 changed files with 77 additions and 24 deletions

101
dwm.c
View File

@ -221,7 +221,7 @@ static void toggleview(const Arg *arg);
static void unfocus(Client *c); static void unfocus(Client *c);
static void unmanage(Client *c, Bool destroyed); static void unmanage(Client *c, Bool destroyed);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
static void updategeom(void); static Bool updategeom(void);
static void updatebarpos(Monitor *m); static void updatebarpos(Monitor *m);
static void updatebars(void); static void updatebars(void);
static void updatenumlockmask(void); static void updatenumlockmask(void);
@ -535,14 +535,15 @@ configurenotify(XEvent *e) {
if(ev->window == root) { if(ev->window == root) {
sw = ev->width; sw = ev->width;
sh = ev->height; sh = ev->height;
updategeom(); if(updategeom()) {
if(dc.drawable != 0) if(dc.drawable != 0)
XFreePixmap(dpy, dc.drawable); XFreePixmap(dpy, dc.drawable);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
updatebars(); updatebars();
for(m = mons; m; m = m->next) for(m = mons; m; m = m->next)
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
arrange(); arrange();
}
} }
} }
@ -1692,26 +1693,73 @@ updatebarpos(Monitor *m) {
m->by = -bh; m->by = -bh;
} }
void Bool
updategeom(void) { updategeom(void) {
int i, n = 1; int i, j, nn = 1, n = 1;
Client *c; Client *c;
Monitor *newmons = NULL, *m = NULL, *tm; Monitor *newmons = NULL, *m = NULL, *tm;
#ifdef XINERAMA #ifdef XINERAMA
int nn;
XineramaScreenInfo *info = NULL; XineramaScreenInfo *info = NULL;
Bool *flags = NULL;
if(XineramaIsActive(dpy)) if(XineramaIsActive(dpy))
info = XineramaQueryScreens(dpy, &n); info = XineramaQueryScreens(dpy, &n);
for(i = 1, nn = n; i < n; i++) flags = (Bool *)malloc(sizeof(Bool) * n);
if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org for(i = 0; i < n; i++)
&& info[i - 1].width == info[i].width && info[i - 1].height == info[i].height) flags[i] = False;
--nn; /* next double-loop seeks any combination of retrieved Xinerama info
n = nn; /* we only consider unique geometries as separate screens */ * 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 */ #endif /* XINERAMA */
/* allocate monitor(s) for the new geometry setup */ /* 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)))) if(!(m = (Monitor *)malloc(sizeof(Monitor))))
die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
m->next = newmons; m->next = newmons;
@ -1720,14 +1768,18 @@ updategeom(void) {
/* initialise monitor(s) */ /* initialise monitor(s) */
#ifdef XINERAMA #ifdef XINERAMA
if(XineramaIsActive(dpy)) { if(XineramaIsActive(dpy)) {
for(i = 0, m = newmons; m; m = m->next, i++) { for(i = 0, m = newmons; m && i < n; i++) {
m->num = info[i].screen_number; if(!flags[i]) { /* only use screens that aren't dublettes */
m->mx = m->wx = info[i].x_org; m->num = info[i].screen_number;
m->my = m->wy = info[i].y_org; m->mx = m->wx = info[i].x_org;
m->mw = m->ww = info[i].width; m->my = m->wy = info[i].y_org;
m->mh = m->wh = info[i].height; m->mw = m->ww = info[i].width;
m->mh = m->wh = info[i].height;
m = m->next;
}
} }
XFree(info); XFree(info);
free(flags);
} }
else else
#endif /* XINERAMA */ #endif /* XINERAMA */
@ -1767,6 +1819,7 @@ updategeom(void) {
cleanupmons(); cleanupmons();
selmon = mons = newmons; selmon = mons = newmons;
selmon = wintomon(root); selmon = wintomon(root);
return True;
} }
void void