From 6915958dd4a29c60c6e501eb606aa3d43f33f1f3 Mon Sep 17 00:00:00 2001 From: Steve Midgley Date: Mon, 13 Jul 2026 17:49:37 -0700 Subject: [PATCH] x11: Seed client_rect with frame-relative coords for framed windows meta_window_x11_manage seeds priv->client_rect with window->rect (root coordinates) after meta_window_ensure_frame has already reparented the client to (0, 0) inside its frame. meta_window_x11_move_resize_internal compares that cache against frame-relative coordinates (borders.total.left, borders.total.top), so when a window's pre-manage root position happens to equal exactly that offset, need_move_client stays FALSE and the client is left at (0, 0) inside its frame - the titlebar is drawn behind the client, and the unused right/bottom of the frame shows through as black strips. The state never self-heals: the cache claims the client is already at the correct offset, so no later move or resize ever sends CWX|CWY for it. This happens in practice after every WM restart (cinnamon --replace or crash recovery) to windows parked in the top-left corner of the screen: when the old WM's connection closes its frames are destroyed, and the save-set returns clients to the root window preserving absolute coordinates - for a frame that sat at the screen origin, the client lands at exactly (borders.total.left, borders.total.top). Seed client_rect.x/y with frame->child_x/child_y - where XReparentWindow actually placed the client - instead. Co-Authored-By: Claude Code --- src/x11/window-x11.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 993c8d494..63929f265 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -561,6 +561,23 @@ meta_window_x11_manage (MetaWindow *window) priv->client_rect = window->rect; window->buffer_rect = window->rect; + /* If the window was reparented into a frame above, the client now sits + * at (child_x, child_y) == (0, 0) inside the frame — not at its + * pre-manage root coordinates. client_rect.x/y are compared against + * frame-relative coordinates in meta_window_x11_move_resize_internal, + * so seed them with the real frame-relative position. Seeding root + * coordinates instead skips the initial client move whenever they + * happen to equal (borders.total.left, borders.total.top) — e.g. a + * window returned to the root by the save-set during a WM restart, + * whose frame sat at the screen origin — leaving the client stuck at + * (0, 0) covering its own titlebar. + */ + if (window->frame) + { + priv->client_rect.x = window->frame->child_x; + priv->client_rect.y = window->frame->child_y; + } + if (!window->override_redirect) { MetaRectangle rect;