drastically changed updategeom() handling, see comment in updategeom() for details 20f69179
anselm@garbe.us · 2012-06-23 10:12 2 file(s) · +54 −71
config.mk +1 −1
1 1
# dwm version
2 -
VERSION = 6.0-tip
2 +
VERSION = 6.1
3 3
4 4
# Customize below to fit your system
5 5
dwm.c +53 −70
235 235
static void unfocus(Client *c, Bool setfocus);
236 236
static void unmanage(Client *c, Bool destroyed);
237 237
static void unmapnotify(XEvent *e);
238 -
static Bool updategeom(void);
238 +
static void updategeom(void);
239 239
static void updatebarpos(Monitor *m);
240 240
static void updatebars(void);
241 241
static void updateclientlist(void);
573 573
configurenotify(XEvent *e) {
574 574
	Monitor *m;
575 575
	XConfigureEvent *ev = &e->xconfigure;
576 -
	Bool dirty;
577 576
578 -
	// TODO: updategeom handling sucks, needs to be simplified
579 577
	if(ev->window == root) {
580 -
		dirty = (sw != ev->width || sh != ev->height);
581 578
		sw = ev->width;
582 579
		sh = ev->height;
583 -
		if(updategeom() || dirty) {
584 -
			if(dc.drawable != 0)
585 -
				XFreePixmap(dpy, dc.drawable);
586 -
			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
587 -
			updatebars();
588 -
			for(m = mons; m; m = m->next)
589 -
				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
590 -
			focus(NULL);
591 -
			arrange(NULL);
592 -
		}
580 +
		if(dc.drawable != 0)
581 +
			XFreePixmap(dpy, dc.drawable);
582 +
		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
583 +
		updatebars();
584 +
		for(m = mons; m; m = m->next)
585 +
			XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
586 +
		focus(NULL);
587 +
		arrange(NULL);
593 588
	}
594 589
}
595 590
1076 1071
static Bool
1077 1072
isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) {
1078 1073
	while(n--)
1079 -
		if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
1080 -
		&& unique[n].width == info->width && unique[n].height == info->height)
1074 +
		/* treat origin (x, y) as fixpoint for uniqueness only, first screen wins */
1075 +
		if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org)
1081 1076
			return False;
1082 1077
	return True;
1083 1078
}
1887 1882
			                (unsigned char *) &(c->win), 1);
1888 1883
}
1889 1884
1890 -
Bool
1885 +
void
1891 1886
updategeom(void) {
1892 -
	Bool dirty = False;
1887 +
	/* Starting with dwm 6.1 this function uses a new (simpler) strategy:
1888 +
	 * whenever screen changes are reported, we destroy all monitors
1889 +
	 * and recreate all unique origin monitors and add all clients to
1890 +
	 * the first monitor, only. In several circumstances this may suck,
1891 +
	 * but dealing with all corner-cases sucks even more.*/
1893 1892
1894 1893
#ifdef XINERAMA
1895 1894
	if(XineramaIsActive(dpy)) {
1896 -
		int i, j, n, nn;
1895 +
		int i, j, n;
1897 1896
		Client *c;
1898 -
		Monitor *m;
1899 -
		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
1897 +
		Monitor *m, *oldmons = mons;
1898 +
		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n);
1900 1899
		XineramaScreenInfo *unique = NULL;
1901 1900
1902 -
		for(n = 0, m = mons; m; m = m->next, n++);
1903 1901
		/* only consider unique geometries as separate screens */
1904 -
		if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
1905 -
			die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
1906 -
		for(i = 0, j = 0; i < nn; i++)
1902 +
		if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * n)))
1903 +
			die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * n);
1904 +
		for(i = 0, j = 0; i < n; i++)
1907 1905
			if(isuniquegeom(unique, j, &info[i]))
1908 1906
				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
1909 1907
		XFree(info);
1910 -
		nn = j;
1911 -
		if(n <= nn) {
1912 -
			for(i = 0; i < (nn - n); i++) { /* new monitors available */
1913 -
				for(m = mons; m && m->next; m = m->next);
1914 -
				if(m)
1915 -
					m->next = createmon();
1916 -
				else
1917 -
					mons = createmon();
1918 -
			}
1919 -
			for(i = 0, m = mons; i < nn && m; m = m->next, i++)
1920 -
				if(i >= n
1921 -
				|| (unique[i].x_org != m->mx || unique[i].y_org != m->my
1922 -
				    || unique[i].width != m->mw || unique[i].height != m->mh))
1923 -
				{
1924 -
					dirty = True;
1925 -
					m->num = i;
1926 -
					m->mx = m->wx = unique[i].x_org;
1927 -
					m->my = m->wy = unique[i].y_org;
1928 -
					m->mw = m->ww = unique[i].width;
1929 -
					m->mh = m->wh = unique[i].height;
1930 -
					updatebarpos(m);
1931 -
				}
1908 +
		/* create new monitor structure */
1909 +
		n = j;
1910 +
		mons = m = createmon(); /* new first monitor */
1911 +
		for(i = 1; i < n; i++) {
1912 +
			m->next = createmon();
1913 +
			m = m->next;
1914 +
		}
1915 +
		for(i = 0, m = mons; i < n && m; m = m->next, i++) {
1916 +
			m->num = i;
1917 +
			m->mx = m->wx = unique[i].x_org;
1918 +
			m->my = m->wy = unique[i].y_org;
1919 +
			m->mw = m->ww = unique[i].width;
1920 +
			m->mh = m->wh = unique[i].height;
1921 +
			updatebarpos(m);
1932 1922
		}
1933 -
		else { /* less monitors available nn < n */
1934 -
			for(i = nn; i < n; i++) {
1935 -
				for(m = mons; m && m->next; m = m->next);
1936 -
				while(m->clients) {
1937 -
					dirty = True;
1938 -
					c = m->clients;
1939 -
					m->clients = c->next;
1940 -
					detachstack(c);
1941 -
					c->mon = mons;
1942 -
					attach(c);
1943 -
					attachstack(c);
1944 -
				}
1945 -
				if(m == selmon)
1946 -
					selmon = mons;
1947 -
				cleanupmon(m);
1923 +
		free(unique);
1924 +
		/* re-attach old clients and cleanup old monitor structure */
1925 +
		while(oldmons) {
1926 +
			m = oldmons;
1927 +
			while(m->clients) {
1928 +
				c = m->clients;
1929 +
				m->clients = c->next;
1930 +
				detachstack(c);
1931 +
				c->mon = mons;
1932 +
				attach(c);
1933 +
				attachstack(c);
1948 1934
			}
1935 +
			oldmons = m->next;
1936 +
			cleanupmon(m);
1949 1937
		}
1950 -
		free(unique);
1951 1938
	}
1952 1939
	else
1953 1940
#endif /* XINERAMA */
1954 1941
	/* default monitor setup */
1955 1942
	{
1956 -
		if(!mons)
1943 +
		if(!mons) /* only true if !XINERAMA compile flag */
1957 1944
			mons = createmon();
1958 1945
		if(mons->mw != sw || mons->mh != sh) {
1959 -
			dirty = True;
1960 1946
			mons->mw = mons->ww = sw;
1961 1947
			mons->mh = mons->wh = sh;
1962 1948
			updatebarpos(mons);
1963 1949
		}
1964 1950
	}
1965 -
	if(dirty) {
1966 -
		selmon = mons;
1967 -
		selmon = wintomon(root);
1968 -
	}
1969 -
	return dirty;
1951 +
	selmon = mons;
1952 +
	selmon = wintomon(root);
1970 1953
}
1971 1954
1972 1955
void