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 82ec7a7e
Anselm R Garbe · 2009-09-18 21:18 1 file(s) · +77 −24
dwm.c +77 −24
221 221
static void unfocus(Client *c);
222 222
static void unmanage(Client *c, Bool destroyed);
223 223
static void unmapnotify(XEvent *e);
224 -
static void updategeom(void);
224 +
static Bool updategeom(void);
225 225
static void updatebarpos(Monitor *m);
226 226
static void updatebars(void);
227 227
static void updatenumlockmask(void);
535 535
	if(ev->window == root) {
536 536
		sw = ev->width;
537 537
		sh = ev->height;
538 -
		updategeom();
539 -
		if(dc.drawable != 0)
540 -
			XFreePixmap(dpy, dc.drawable);
541 -
		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
542 -
		updatebars();
543 -
		for(m = mons; m; m = m->next)
544 -
			XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
545 -
		arrange();
538 +
		if(updategeom()) {
539 +
			if(dc.drawable != 0)
540 +
				XFreePixmap(dpy, dc.drawable);
541 +
			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
542 +
			updatebars();
543 +
			for(m = mons; m; m = m->next)
544 +
				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
545 +
			arrange();
546 +
		}
546 547
	}
547 548
}
548 549
1692 1693
		m->by = -bh;
1693 1694
}
1694 1695
1695 -
void
1696 +
Bool
1696 1697
updategeom(void) {
1697 -
	int i, n = 1;
1698 +
	int i, j, nn = 1, n = 1;
1698 1699
	Client *c;
1699 1700
	Monitor *newmons = NULL, *m = NULL, *tm;
1700 1701
1701 1702
#ifdef XINERAMA
1702 -
	int nn;
1703 1703
	XineramaScreenInfo *info = NULL;
1704 +
	Bool *flags = NULL;
1704 1705
1705 1706
	if(XineramaIsActive(dpy))
1706 1707
		info = XineramaQueryScreens(dpy, &n);
1707 -
	for(i = 1, nn = n; i < n; i++)
1708 -
		if(info[i - 1].x_org == info[i].x_org && info[i - 1].y_org == info[i].y_org
1709 -
		&& info[i - 1].width == info[i].width && info[i - 1].height == info[i].height)
1710 -
			--nn;
1711 -
	n = nn; /* we only consider unique geometries as separate screens */
1708 +
	flags = (Bool *)malloc(sizeof(Bool) * n);
1709 +
	for(i = 0; i < n; i++)
1710 +
		flags[i] = False;
1711 +
	/* next double-loop seeks any combination of retrieved Xinerama info
1712 +
	 * with existing monitors, this is used to avoid unnecessary
1713 +
	 * re-allocations of monitor structs */
1714 +
	for(i = 0, nn = n; i < n; i++)
1715 +
		for(j = 0, m = mons; m; m = m->next, j++)
1716 +
			if(!flags[j]) {
1717 +
				if((flags[j] = (
1718 +
					info[i].x_org == m->mx
1719 +
					&& info[i].y_org == m->my
1720 +
					&& info[i].width == m->mw
1721 +
					&& info[i].height == m->mh)
1722 +
				))
1723 +
					--nn;
1724 +
			}
1725 +
	if(nn == 0) { /* no need to re-allocate monitors */
1726 +
		j = 0;
1727 +
		for(i = 0, m = mons; m; m = m->next, i++) {
1728 +
			m->num = info[i].screen_number;
1729 +
			if(info[i].x_org != m->mx
1730 +
			|| info[i].y_org != m->my
1731 +
			|| info[i].width != m->mw
1732 +
			|| info[i].height != m->mh)
1733 +
			{
1734 +
				m->mx = m->wx = info[i].x_org;
1735 +
				m->my = m->wy = info[i].y_org;
1736 +
				m->mw = m->ww = info[i].width;
1737 +
				m->mh = m->wh = info[i].height;
1738 +
				updatebarpos(m);
1739 +
				j++;
1740 +
			}
1741 +
		}
1742 +
		XFree(info);
1743 +
		free(flags);
1744 +
		return j > 0;
1745 +
	}
1746 +
	/* next algorithm only considers unique geometries as separate screens */
1747 +
	for(i = 0; i < n; i++)
1748 +
		flags[i] = False; /* used for ignoring certain monitors */
1749 +
	for(i = 0, nn = n; i < n; i++)
1750 +
		for(j = 0; j < n; j++)
1751 +
			if(i != j && !flags[i]) {
1752 +
				if((flags[i] = (
1753 +
					info[i].x_org == info[j].x_org
1754 +
					&& info[i].y_org == info[j].y_org
1755 +
					&& info[i].width == info[j].width
1756 +
					&& info[i].height == info[j].height)
1757 +
				))
1758 +
					--nn;
1759 +
			}
1712 1760
#endif /* XINERAMA */
1713 1761
	/* allocate monitor(s) for the new geometry setup */
1714 -
	for(i = 0; i < n; i++) {
1762 +
	for(i = 0; i < nn; i++) {
1715 1763
		if(!(m = (Monitor *)malloc(sizeof(Monitor))))
1716 1764
			die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
1717 1765
		m->next = newmons;
1720 1768
	/* initialise monitor(s) */
1721 1769
#ifdef XINERAMA
1722 1770
	if(XineramaIsActive(dpy)) {
1723 -
		for(i = 0, m = newmons; m; m = m->next, i++) {
1724 -
			m->num = info[i].screen_number;
1725 -
			m->mx = m->wx = info[i].x_org;
1726 -
			m->my = m->wy = info[i].y_org;
1727 -
			m->mw = m->ww = info[i].width;
1728 -
			m->mh = m->wh = info[i].height;
1771 +
		for(i = 0, m = newmons; m && i < n; i++) {
1772 +
			if(!flags[i]) { /* only use screens that aren't dublettes */
1773 +
				m->num = info[i].screen_number;
1774 +
				m->mx = m->wx = info[i].x_org;
1775 +
				m->my = m->wy = info[i].y_org;
1776 +
				m->mw = m->ww = info[i].width;
1777 +
				m->mh = m->wh = info[i].height;
1778 +
				m = m->next;
1779 +
			}
1729 1780
		}
1730 1781
		XFree(info);
1782 +
		free(flags);
1731 1783
	}
1732 1784
	else
1733 1785
#endif /* XINERAMA */
1767 1819
	cleanupmons();
1768 1820
	selmon = mons = newmons;
1769 1821
	selmon = wintomon(root);
1822 +
	return True;
1770 1823
}
1771 1824
1772 1825
void