diff options
Diffstat (limited to 'crates/core/src')
| -rw-r--r-- | crates/core/src/manager/dragresize.rs | 8 | ||||
| -rw-r--r-- | crates/core/src/manager/tests.rs | 33 | ||||
| -rw-r--r-- | crates/core/src/manager/windows.rs | 19 |
3 files changed, 59 insertions, 1 deletions
diff --git a/crates/core/src/manager/dragresize.rs b/crates/core/src/manager/dragresize.rs index 906e5db..16aa539 100644 --- a/crates/core/src/manager/dragresize.rs +++ b/crates/core/src/manager/dragresize.rs @@ -387,6 +387,14 @@ impl WindowManager { /// Every remembered `app_id` and its geometry - what `window_memory.rs` /// iterates to persist the full table (e.g. on a clean shutdown), not /// just whatever changed most recently. + /// This app's remembered geometry, if any. `None` means nothing has + /// been recorded for it - which is what a window that closed while its + /// size was still a placeholder deliberately leaves behind, so its next + /// launch gets to pick its own size again. + pub fn remembered_geometry_for(&self, app_id: &str) -> Option<(i32, i32, u32, u32)> { + self.remembered_geometry.get(app_id).copied() + } + pub fn all_remembered_geometry(&self) -> impl Iterator<Item = (&str, (i32, i32, u32, u32))> { self.remembered_geometry.iter().map(|(k, &v)| (k.as_str(), v)) } diff --git a/crates/core/src/manager/tests.rs b/crates/core/src/manager/tests.rs index 152c71d..fdf0517 100644 --- a/crates/core/src/manager/tests.rs +++ b/crates/core/src/manager/tests.rs @@ -915,6 +915,39 @@ } #[test] + fn a_size_the_client_never_chose_is_not_remembered() { + // The poisoning loop: remember a placeholder once and every future + // launch is forced to it, which looks like "every window spawns the + // same shape". + let mut wm = wm_with_monitor(); + let id = wm.alloc_window_id(); + let mut w = Window::new(id, "w"); + w.app_id = "someapp".into(); + wm.add_window(w); + assert!(wm.window(id).unwrap().size_is_provisional, "no remembered size, so the guess is provisional"); + wm.remove_window(id); + assert!(wm.remembered_geometry_for("someapp").is_none(), "a guess must never be remembered"); + } + + #[test] + fn a_size_the_client_did_choose_is_remembered() { + let mut wm = wm_with_monitor(); + let id = wm.alloc_window_id(); + let mut w = Window::new(id, "w"); + w.app_id = "someapp".into(); + wm.add_window(w); + // What the backend does once the client commits a real buffer. + if let Some(w) = wm.window_mut(id) { + w.size_is_provisional = false; + w.geometry.width = 1389; + w.geometry.height = 933; + } + wm.remove_window(id); + let remembered = wm.remembered_geometry_for("someapp").expect("a real choice must be remembered"); + assert_eq!((remembered.2, remembered.3), (1389, 933)); + } + + #[test] fn a_dialog_opens_centered_not_cascaded_into_the_corner() { let mut wm = wm_with_monitor(); let a = wm.alloc_window_id(); diff --git a/crates/core/src/manager/windows.rs b/crates/core/src/manager/windows.rs index 0186679..1e8a6cb 100644 --- a/crates/core/src/manager/windows.rs +++ b/crates/core/src/manager/windows.rs @@ -369,8 +369,25 @@ impl WindowManager { // simply never consulted again on the read side once `layout_name // == "tiling"`, so remembering it anyway is harmless, not wasted // work worth a special case. + // + // `size_is_provisional` still set means the client never actually + // chose a size: the window closed while still carrying the + // backend's placeholder guess. Remembering that guess poisons this + // table permanently, and does so in a way that hides itself: + // + // 1. a window closes early, the placeholder is remembered + // 2. next launch finds a remembered size, so it is NOT provisional + // 3. the client is therefore forced to the placeholder instead of + // being asked to pick, and looks identical to every other + // poisoned app + // 4. on close the same placeholder is written back + // + // Reported as windows "spawning in squares" - every app coming out + // the same shape whatever it is. Five of eleven entries in the live + // store had been captured this way, including Firefox, whose real + // remembered size earlier the same day had been 1389x933. if let Some(w) = &window { - if !w.app_id.is_empty() { + if !w.app_id.is_empty() && !w.size_is_provisional { self.remembered_geometry.insert(w.app_id.clone(), (w.geometry.x, w.geometry.y, w.geometry.width, w.geometry.height)); } } |