diff --git a/src/sxwm.c b/src/sxwm.c
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -3235,8 +3235,17 @@
if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &n_children))
return;
- int screen_w = scr_width;
- int screen_h = scr_height;
+ /* scr_width/scr_height are only refreshed by update_mons(), on
+ * startup and root ConfigureNotify -- unlike reserve_top/reserve_left
+ * (measured from a monitor's own x/y, independent of total screen
+ * size), reserve_bottom/reserve_right are measured as a distance from
+ * the *opposite* edge of the whole screen, so a stale cached
+ * scr_width/scr_height silently corrupts only those two, never
+ * left/top. Query the server directly here instead of trusting the
+ * cache, since this runs cheaply and infrequently (on retile, not
+ * per-frame). */
+ int screen_w = XDisplayWidth(dpy, DefaultScreen(dpy));
+ int screen_h = XDisplayHeight(dpy, DefaultScreen(dpy));
for (unsigned int i = 0; i < n_children; i++) {
Window w = children[i];