From 9e88d3e3f86a1248b72fdb9bab59d9936a3323a6 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:28:00 +0200 Subject: Let a new window pick its own size instead of forcing a guessed placeholder Root-caused "windows spawn small and square, not remembering placement or size": new_managed_window hardcoded a fresh toplevel's geometry to 800x632 before the client had said anything about its own preferred size, and sync_geometry forced that guess onto the client's very first xdg_toplevel::configure unconditionally. Per xdg-shell, size: None on that first configure is how every mainstream compositor lets a client pick its own natural size instead; this one never did, so every app converged on the same placeholder rectangle regardless of what it would have chosen. Window::size_is_provisional marks a size that really was just the guess (not a remembered geometry, a rule's explicit geometry action, or a maximize/phone-mode fill, none of which are guesses). sync_geometry sends size: None for such a window's first configure; a new adopt_provisional_size, called from the commit handler, adopts the client's own real first size into Window::geometry the moment it commits one, clamping only position so a bigger-than-guessed window can't hang off its monitor's edge. Live-verified in a nested compositor: a zenity dialog now renders at its own compact natural size instead of being stretched to the old guess. --- crates/wayland/src/state/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crates/wayland/src/state/mod.rs') diff --git a/crates/wayland/src/state/mod.rs b/crates/wayland/src/state/mod.rs index 629b58c..f39edcc 100644 --- a/crates/wayland/src/state/mod.rs +++ b/crates/wayland/src/state/mod.rs @@ -586,6 +586,14 @@ pub(crate) struct CompState { /// motion event of every drag, which is what made moving a window /// stutter. Only a real size change now does either. pub(crate) last_synced_size: HashMap, + /// Windows whose `Window::size_is_provisional` was `true` at creation + /// and whose client hasn't sent a real, non-empty content commit yet -- + /// see that field's own doc comment. `sync_geometry` sends `size: None` + /// (let the client pick) instead of forcing this guessed size for the + /// one configure sent while a window is in this set; `commit()` removes + /// it and adopts the client's own real first size into `Window:: + /// geometry` the moment one arrives. + pub(crate) provisional_size: HashSet, /// A size-changing `xdg_toplevel.configure` that's been sent but not /// yet reflected in the client's own real committed content size -- /// `(size requested, when it was sent)`. `sync_geometry` won't send -- cgit v1.2.3