[hackers] [dwm][PATCH 2/2] updategeom: make only one pass over mons

From: Devin J. Pohly <djpohly_AT_gmail.com>
Date: Mon, 27 Jan 2020 07:55:58 -0600

There is no need to iterate repeatedly over mons when adding/removing
monitors, or to figure out ahead of time how many entries there are in
the list. Instead, we can do this with a single iteration:

1. If we have reached neither the new monitor count nor the end of the
   old list, resize the existing monitor.

2. If we reach the end of the old list before the new monitor count,
   create a new monitor first, then resize it as above.

3. After we reach the new monitor count, destroy any remaining monitors.
---
 dwm.c | 66 +++++++++++++++++++++++++----------------------------------
 1 file changed, 28 insertions(+), 38 deletions(-)
diff --git a/dwm.c b/dwm.c
index 958a0e4..1eb49f9 100644
--- a/dwm.c
+++ b/dwm.c
_AT_@ -1847,13 +1847,12 @@ updategeom(void)
 
 #ifdef XINERAMA
 	if (XineramaIsActive(dpy)) {
-		int i, j, n, nn;
+		int i, j, nn;
 		Client *c;
 		Monitor *m, **pm;
 		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
 		XineramaScreenInfo *unique = NULL;
 
-		for (n = 0, m = mons; m; m = m->next, n++);
 		/* only consider unique geometries as separate screens */
 		unique = ecalloc(nn, sizeof(XineramaScreenInfo));
 		for (i = 0, j = 0; i < nn; i++)
_AT_@ -1861,44 +1860,35 @@ updategeom(void)
 				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
 		XFree(info);
 		nn = j;
-		if (n <= nn) { /* new monitors available */
-			for (i = 0; i < (nn - n); i++) {
-				for (m = mons; m && m->next; m = m->next);
-				if (m)
-					m->next = createmon();
-				else
-					mons = createmon();
+		for (i = 0, pm = &mons; i < nn; i++, pm = &(*pm)->next) {
+			if (!*pm) /* reached end of mons before nn */
+				*pm = createmon();
+			m = *pm;
+			m->num = i;
+			if (unique[i].x_org != m->mx || unique[i].y_org != m->my
+					|| unique[i].width != m->mw || unique[i].height != m->mh)
+			{
+				dirty = 1;
+				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);
 			}
-			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 = 1;
-					m->num = i;
-					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);
-				}
-		} else { /* less monitors available nn < n */
-			for (i = 0, pm = &mons; i < nn; i++, pm = &(*pm)->next);
-			for (/* i */; i < n; i++) {
-				m = *pm;
-				while ((c = m->clients)) {
-					dirty = 1;
-					m->clients = c->next;
-					detachstack(c);
-					c->mon = mons;
-					attach(c);
-					attachstack(c);
-				}
-				if (m == selmon)
-					selmon = mons;
-				*pm = (*pm)->next;
-				cleanupmon(m);
+		}
+		while ((m = *pm)) { /* extra monitors remain beyond nn */
+			while ((c = m->clients)) {
+				dirty = 1;
+				m->clients = c->next;
+				detachstack(c);
+				c->mon = mons;
+				attach(c);
+				attachstack(c);
 			}
+			if (m == selmon)
+				selmon = mons;
+			*pm = (*pm)->next;
+			cleanupmon(m);
 		}
 		free(unique);
 	} else
-- 
2.25.0
Received on Mon Jan 27 2020 - 14:55:58 CET

This archive was generated by hypermail 2.3.0 : Mon Jan 27 2020 - 15:00:30 CET