X-Git-Url: https://git.xinqibao.xyz/dwm.git/blobdiff_plain/82ec7a7ed4f3ba376faadfc2aca783b24618575f..c45d46ad9a44b9897c8c12eacb60b5cbdd31be7c:/dwm.c?ds=sidebyside

diff --git a/dwm.c b/dwm.c
index 2b4d6b0..48f50da 100644
--- a/dwm.c
+++ b/dwm.c
@@ -121,7 +121,7 @@ typedef struct {
 } Layout;
 
 struct Monitor {
-	const char *ltsymbol;
+	char ltsymbol[16];
 	float mfact;
 	int num;
 	int by;               /* bar geometry */
@@ -163,6 +163,7 @@ static void clearurgent(Client *c);
 static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
+static Monitor *createmon(void);
 static void destroynotify(XEvent *e);
 static void detach(Client *c);
 static void detachstack(Client *c);
@@ -385,7 +386,7 @@ arrange(void) {
 		showhide(m->stack);
 	focus(NULL);
 	for(m = mons; m; m = m->next) {
-		m->ltsymbol = m->lt[m->sellt]->symbol;
+		strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
 		if(m->lt[m->sellt]->arrange)
 			m->lt[m->sellt]->arrange(m);
 		restack(m);
@@ -592,6 +593,22 @@ configurerequest(XEvent *e) {
 	XSync(dpy, False);
 }
 
+Monitor *
+createmon(void) {
+	Monitor *m;
+
+	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
+		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
+	m->tagset[0] = m->tagset[1] = 1;
+	m->mfact = mfact;
+	m->showbar = showbar;
+	m->topbar = topbar;
+	m->lt[0] = &layouts[0];
+	m->lt[1] = &layouts[1 % LENGTH(layouts)];
+	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+	return m;
+}
+
 void
 destroynotify(XEvent *e) {
 	Client *c;
@@ -1005,6 +1022,19 @@ isprotodel(Client *c) {
 	return ret;
 }
 
+#ifdef XINERAMA
+static Bool
+isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) {
+	unsigned int i;
+
+	for(i = 0; i < len; i++)
+		if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org
+		&& unique[i].width == info->width && unique[i].height == info->height)
+			return False;
+	return True;
+}
+#endif /* XINERAMA */
+
 void
 keypress(XEvent *e) {
 	unsigned int i;
@@ -1133,17 +1163,14 @@ maprequest(XEvent *e) {
 
 void
 monocle(Monitor *m) {
-	static char ntext[8];
 	unsigned int n = 0;
 	Client *c;
 
 	for(c = m->clients; c; c = c->next)
 		if(ISVISIBLE(c))
 			n++;
-	if(n > 0) { /* override layout symbol */
-		snprintf(ntext, sizeof ntext, "[%d]", n);
-		m->ltsymbol = ntext;
-	}
+	if(n > 0) /* override layout symbol */
+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
 	for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
 		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
 }
@@ -1695,131 +1722,72 @@ updatebarpos(Monitor *m) {
 
 Bool
 updategeom(void) {
-	int i, j, nn = 1, n = 1;
-	Client *c;
-	Monitor *newmons = NULL, *m = NULL, *tm;
+	Bool dirty = False;
 
-#ifdef XINERAMA
-	XineramaScreenInfo *info = NULL;
-	Bool *flags = NULL;
-
-	if(XineramaIsActive(dpy))
-		info = XineramaQueryScreens(dpy, &n);
-	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 < nn; i++) {
-		if(!(m = (Monitor *)malloc(sizeof(Monitor))))
-			die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
-		m->next = newmons;
-		newmons = m;
-	}
-	/* initialise monitor(s) */
 #ifdef XINERAMA
 	if(XineramaIsActive(dpy)) {
-		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;
+		int i, j, n, nn;
+		Monitor *m;
+		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
+		XineramaScreenInfo *unique = NULL;
+
+		info = XineramaQueryScreens(dpy, &nn);
+		for(n = 0, m = mons; m; m = m->next, n++);
+		/* only consider unique geometries as separate screens */
+		if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
+			die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
+		for(i = 0, j = 0; i < nn; i++)
+			if(isuniquegeom(unique, j, &info[i]))
+				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
+		XFree(info);
+		nn = j;
+		if(n <= nn) {
+			for(i = 0; i < (nn - n); i++) { /* new monitors available */
+				for(m = mons; m && m->next; m = m->next);
+				if(m)
+					m->next = createmon();
+				else
+					mons = createmon();
 			}
+			for(i = 0, m = mons; i < nn && m; m = m->next, i++)
+				if(i >= n
+				|| (unique[i].x_org != m->mx || unique[i].y_org != m->my
+				    || unique[i].width != m->mw || unique[i].height != m->mh))
+				{
+					dirty = True;
+					m->num = unique[i].screen_number;
+					m->mx = m->wx = unique[i].x_org;
+					m->my = m->wy = unique[i].y_org;
+					m->mw = m->ww = unique[i].width;
+					m->mh = m->wh = unique[i].height;
+					updatebarpos(m);
+				}
 		}
-		XFree(info);
-		free(flags);
+		else { /* less monitors available */
+			cleanup();
+			setup();
+			scan();
+		}
+		free(unique);
 	}
 	else
 #endif /* XINERAMA */
 	/* default monitor setup */
 	{
-		m->num = 0;
-		m->mx = m->wx = 0;
-		m->my = m->wy = 0;
-		m->mw = m->ww = sw;
-		m->mh = m->wh = sh;
-	}
-	/* bar geometry setup */
-	for(m = newmons; m; m = m->next) {
-		m->sel = m->stack = m->clients = NULL;
-		m->seltags = 0;
-		m->sellt = 0;
-		m->tagset[0] = m->tagset[1] = 1;
-		m->mfact = mfact;
-		m->showbar = showbar;
-		m->topbar = topbar;
-		m->lt[0] = &layouts[0];
-		m->lt[1] = &layouts[1 % LENGTH(layouts)];
-		m->ltsymbol = layouts[0].symbol;
-		updatebarpos(m);
-	}
-	/* reassign left over clients of disappeared monitors */
-	for(tm = mons; tm; tm = tm->next)
-		while(tm->clients) {
-			c = tm->clients;
-			tm->clients = c->next;
-			detachstack(c);
-			c->mon = newmons;
-			attach(c);
-			attachstack(c);
+		if(!mons)
+			mons = createmon();
+		if(mons->mw != sw || mons->mh != sh) {
+			dirty = True;
+			mons->mw = mons->ww = sw;
+			mons->mh = mons->wh = sh;
+			updatebarpos(mons);
 		}
-	/* select focused monitor */
-	cleanupmons();
-	selmon = mons = newmons;
-	selmon = wintomon(root);
-	return True;
+	}
+	if(dirty) {
+		selmon = mons;
+		selmon = wintomon(root);
+	}
+	return dirty;
 }
 
 void