From ae056d17d137463b70f34862b9e33a9813c4b381 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Fri, 31 May 2024 01:15:00 +0200 Subject: layer-shell: recompute the exclusive-zone reservation on unmap, not just on commit ensure_layer_initial_configure (state.rs) already recomputes the usable monitor rect when a layer surface's exclusive zone changes, but only from the commit pre-hook - a surface that goes away without a final commit (zwlr_layer_surface_v1's destroy path, layer_destroyed here) never ran that check. unmap_layer's own zone change went unnoticed. Found live by the AGS peer session: unmapping the bar for fullscreen logged visible=false immediately, but `srd monitors` kept reporting the bar's old reserved_top for as long as fullscreen lasted. Harmless there only because toggle_fullscreen targets full_geometry, which ignores the reservation outright - but wrong for anything that reads the reserved/usable rect while a bar is unmapped without a clean exit (a crash, not just AGS's cooperative fullscreen hide). Same zone_before/zone_after diff ensure_layer_initial_ configure already uses, run around unmap_layer instead of arrange(). Verified: cargo build --workspace, cargo clippy -p srdwm-wayland (0 new warnings), cargo test -p srdwm-core (111/111). --- crates/wayland/src/protocols.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/wayland/src/protocols.rs b/crates/wayland/src/protocols.rs index a0aed3f..9f23c69 100644 --- a/crates/wayland/src/protocols.rs +++ b/crates/wayland/src/protocols.rs @@ -636,7 +636,25 @@ impl WlrLayerShellHandler for CompState { let mut map = layer_map_for_output(&output); let found = map.layers().find(|l| l.layer_surface() == &surface).cloned(); if let Some(layer) = found { + // Same zone-change recompute `ensure_layer_initial_configure` + // already does on every commit that changes a layer's + // exclusive zone (state.rs) - but this is the *only* place + // that ever runs for a surface that goes away without one + // last commit. `unmap_layer` alone doesn't trigger it: + // reported live (by the AGS peer session) as a bar unmapping + // for fullscreen yet `srd monitors` still reporting the + // bar's old reserved_top for as long as fullscreen lasted -- + // harmless there only because fullscreen targets + // `full_geometry`, which ignores the reservation anyway, but + // wrong for anything that reads `usable`/`geometry` while a + // bar is unmapped without exiting cleanly (a crash, not just + // AGS's cooperative fullscreen hide). + let zone_before = map.non_exclusive_zone(); map.unmap_layer(&layer); + let zone_after = map.non_exclusive_zone(); + if zone_after != zone_before { + self.pending.borrow_mut().push(srdwm_core::Event::MonitorAdded(srdwm_core::Monitor::new(0, "", srdwm_core::Rect::new(0, 0, 0, 0)))); + } break; } } -- cgit v1.2.3