diff --git a/src/sxwm.c b/src/sxwm.c
index 55fe97b..9c1b2ae 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -3077,6 +3151,48 @@ void update_mons(void)
}
free(old);
+
+ /*
+ client->mon is a plain index into mons[], but monitor count/order
+ can change across a hotplug (e.g. the internal panel toggled off
+ for a closed lid, then back on). A stale index gets silently
+ reinterpreted as whatever monitor now sits at that slot, dragging
+ windows onto the wrong screen -- or, once clamped, squeezing them
+ into bounds far smaller than they were tiled for. Re-derive mon
+ from each client's real last-known position instead of trusting
+ the old index, and pull floating windows back on-screen if the
+ monitor they end up on no longer covers where they were sitting.
+ */
+ for (int ws = 0; ws < NUM_WORKSPACES; ws++) {
+ for (Client *c = workspaces[ws]; c; c = c->next) {
+ c->mon = CLAMP(get_monitor_for(c), 0, n_mons - 1);
+
+ if (!c->floating)
+ continue;
+
+ int mx = mons[c->mon].x, my = mons[c->mon].y;
+ int mw = mons[c->mon].w, mh = mons[c->mon].h;
+ int x = c->x, y = c->y;
+
+ if (x < mx)
+ x = mx;
+ if (y < my)
+ y = my;
+ if (x + c->w > mx + mw)
+ x = mx + mw - c->w;
+ if (y + c->h > my + mh)
+ y = my + mh - c->h;
+
+ if (x != c->x || y != c->y) {
+ c->x = x;
+ c->y = y;
+ if (c->mapped)
+ XMoveWindow(dpy, c->win, x, y);
+ }
+ }
+ }
+
+ current_mon = CLAMP(current_mon, 0, n_mons - 1);
}
void update_net_client_list(void)