Commit Diff


commit - df2d0a797fced7aff2cc197688824ba0c66abaa7
commit + 703f0cd0ff2254a2ef0cce93f5e372eb21f40870
blob - 50e3cc2e48a97e63627838ed69f516e9fdf8a630
blob + 1fbd873a34c66f9c28d9a695aae64ad534c98f48
--- CHANGES
+++ CHANGES
@@ -1,3 +1,8 @@
+0.2.1
+
+Minor update: xitems now correctly redraws in the unlikely event of
+xexepose (other than the first).
+
 0.2
 
 - Added support for UTF-8.
blob - a1272ea4d49976174e4aec7a3072f6a526c1772f
blob + 0d2c695cfe1fa32a51362bcef8b9c99d059a74c5
--- version.mk
+++ version.mk
@@ -1 +1 @@
-V = 0.2
+V = 0.2.1
blob - 33b16b1945b952ad25cb36cc06c30569812e74f7
blob + f67a5b0a6cc854b0d52a66c6a1fcef8c199648d4
--- xitems.c
+++ xitems.c
@@ -99,6 +99,22 @@ static XftFont *font;
 static XftColor c_fg, c_sfg, c_sbg;
 static unsigned long pixels[PIXEL_N];
 
+/*
+ * freeitems -- recursively free the list of items. First call should be
+ * freeitems(NULL).
+ */
+static void
+freeitems(struct item *it)
+{
+	if (!it)
+		it = first;
+	else if (it == first)
+		return;
+
+	freeitems(it->next);
+	free(it);
+}
+
 /* selpos -- mark the item at position y (from top) as selected. */
 static void
 selpos(int y)
@@ -121,6 +137,37 @@ selpos(int y)
 end:
 	if (unselected != selected)
 		unselected->dirty = selected->dirty = true;
+}
+
+/* inbounds -- check if point y is within the bounds of line going from top. */
+static bool
+inbounds(int y, int top, int height)
+{
+	return y >= top && y <= top+height;
+}
+
+/* expose -- mark exposed items as dirty. */
+static void
+expose(XExposeEvent e)
+{
+	struct item *it = first;
+	int y = 0;
+
+	do {
+		/*
+		 * If either end of e's vertical part is within the bounds
+		 * of the item, there is at least some collision. Conversely,
+		 * if either of the item's vertical ends is within e's bounds,
+		 * they must collide.
+		 */
+		int bot = y+height, e_bot = e.y+e.height;
+		if (inbounds(e.y, y, bot) || inbounds(e_bot, y, bot) ||
+		    inbounds(y, e.y, e_bot) || inbounds(bot, e.y, e_bot))
+			it->dirty = true;
+
+		y += height;
+		it = it->next;
+	} while (it != first);
 }
 
 /* redraw -- redraw the entire window. */
@@ -160,22 +207,6 @@ redraw(void)
 	} while (it != first);
 }
 
-/*
- * freeitems -- recursively free the list of items. First call should be
- * freeitems(NULL).
- */
-static void
-freeitems(struct item *it)
-{
-	if (!it)
-		it = first;
-	else if (it == first)
-		return;
-
-	freeitems(it->next);
-	free(it);
-}
-
 /* cleanup -- free allocated resources. */
 static void
 cleanup(void)
@@ -268,6 +299,9 @@ proc(void)
 		selpos(ev.xbutton.y);
 		/* FALLTHRU */
 	case Expose:
+		expose(ev.xexpose);
+		if (ev.xexpose.count)
+			break;
 		redraw();
 		break;
 	case LeaveNotify:
@@ -396,7 +430,7 @@ alloccol_xft(char *s, XftColor *c)
 {
 	if (!(XftColorAllocName(dpy, DefaultVisual(dpy, screen),
 	    DefaultColormap(dpy, screen), s, c)))
-		die(1, "couldn't allocate Xft colour %s\n", s);
+		die(1, "couldn't allocate Xft colour %s", s);
 }
 
 /* alloccol -- safely allocate new colour c from string s. */
@@ -405,7 +439,7 @@ alloccol(char *s, XColor *c)
 {
 	XColor dummy;
 	if (!(XAllocNamedColor(dpy, DefaultColormap(dpy, screen), s, c, &dummy)))
-		die(1, "couldn't allocate colour %s\n", s);
+		die(1, "couldn't allocate colour %s", s);
 }
 
 /*
@@ -506,9 +540,9 @@ insitem(struct item *it, char *s) {
 		*end = '\0';
 
 		if ((ks = XStringToKeysym(p)) == NoSymbol)
-			warn("no such keysym: %s\n", p);
+			warn("no such keysym: %s", p);
 		else if (new->nks >= MAXKS)
-			warn("too many keysyms (%s)\n", p);
+			warn("too many keysyms (%s)", p);
 		else {
 			KeySym k, dummy;
 			XConvertCase(ks, &k, &dummy);