Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix(restore): a floating window remembered off-view reopens centered in view
try_restore replayed a saved floating origin verbatim, so Inkscape's start
screen restored a full viewport above the desk every login — at the cell
its previous incarnation was saved in, with nothing on screen to say it
existed. After the mode latching and geometric promotion, a window that is
still Floating (and not minimized) now asks policy::camera::recalled_origin
whether its remembered position would show at least a quarter of it under
the camera as it stands at restore; if not, it takes the origin that
centers it in the current view. Tiled windows are untouched: they are the
grid's, and a saved Tiled window off the current view stays exactly where
the grid has it.
Verified in a scale-2 shadow with a session save and --restore: a floating
GTK3 window parked eight grid periods below the view came back centered
(pan + (viewport - size) / 2 on both axes, to the pixel), while a tiled
window parked eight periods to the right came back at its far cell. The
same scenario on the previous binary restored the floating window
off-view.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
CLAUDE.md | 6 ++++++
src/server/window.rs | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/CLAUDE.md b/CLAUDE.md
index a9e6ee6..4052cd7 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -468,6 +468,12 @@ the **bare name** whenever the name's first `PATH` hit is a different file
from the one running (`path_shadowed_name`), and the restore's `sh -c`
resolves it the way the launcher did. The absolute path is kept when PATH
agrees with it.
+A restored **floating** window is recalled into the current view
+(`policy::camera::recalled_origin`, applied at the end of `try_restore`)
+when its remembered position would show less than a quarter of it: the
+camera at restore is wherever the session left it, and a floating window a
+screen away from that is lost, not remembered. Tiled windows stay where the
+grid has them.
### IPC & status sockets
diff --git a/src/server/window.rs b/src/server/window.rs
index 24eb570..630dafc 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1179,6 +1179,40 @@ impl Window {
}
}
+ // A remembered FLOATING position is only worth keeping if it is
+ // where the user can see it. The camera at restore is wherever
+ // the session left it (or wherever the user has panned since a
+ // relaunch), and a floating window a screen away from that is
+ // lost, not remembered: Inkscape's start screen came back a full
+ // viewport above the desk every login, at the cell its previous
+ // incarnation had been saved in, with nothing on screen to say
+ // it existed. Tiled windows are the grid's and stay put.
+ if self.tiling_mode == crate::tiling::TilingMode::Floating && !self.minimized {
+ let (_, _, vp_w, vp_h) = self.first_enabled_output_box();
+ let wm = &(*self.server).wm;
+ let cam = crate::policy::camera::Camera {
+ pan_x: wm.desk_pan_x,
+ pan_y: wm.desk_pan_y,
+ zoom: wm.desk_zoom,
+ };
+ if let Some((nx, ny)) = crate::policy::camera::recalled_origin(
+ self.virtual_x,
+ self.virtual_y,
+ saved.width as f64,
+ saved.height as f64,
+ cam,
+ vp_w,
+ vp_h,
+ ) {
+ log::info!(
+ "Recalling off-view floating window into view: app_id={} remembered=({:.0},{:.0}) -> ({:.0},{:.0})",
+ app_id_str, self.virtual_x, self.virtual_y, nx, ny
+ );
+ self.virtual_x = nx;
+ self.virtual_y = ny;
+ }
+ }
+
self.restored = true;
self.session_restored = from_session;
// The saved `focused` flag only means something for the startup