srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/udev
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-07-27 01:25:00 +0200
committersrdusr <[email protected]>2026-07-27 01:25:00 +0200
commite20d49b0ee3dbd83499445d61eb2d65904d74311 (patch)
treebec0d976da83c17fef7a68033e4d2b66394421c1 /crates/wayland/src/udev
parent48ccac7ecaeff0aaa503804bdf8e033e273b9862 (diff)
downloadsrdwm-e20d49b0ee3dbd83499445d61eb2d65904d74311.tar.gz
srdwm-e20d49b0ee3dbd83499445d61eb2d65904d74311.zip
Hide a window only when srdwm knows it has not drawn, not when a lookup says so
Regression I introduced two commits ago, reported live: "I can click close where the button would normally be and it does close, but it is still invisible." The gate that stops an empty frame being drawn before a client paints asked the renderer, from inside the render loop, whether a window's surface had a buffer attached right now - and treated "no" as "do not draw". That question is only meaningful for a native xdg-shell toplevel. An XWayland window's surface state does not describe it the same way, so the answer came back no on every frame and the window was never drawn again, while srdwm's own hit-testing carried on working perfectly: an invisible window that still takes clicks, which is a worse failure than the empty frame it was meant to prevent. Inverted to the fail-safe direction. `new_managed_window` - the one path that creates a native toplevel - puts the window into `awaiting_first_buffer`, and `commit` takes it out on the first commit that carries a buffer. The render and capture paths test that set and nothing else. A window is now hidden only when srdwm itself put it there, so no window whose plumbing works differently can be hidden by a lookup that did not apply to it: the XWayland map path never touches the set, and neither can anything else. The buffer question still gets asked, but only in `commit`, about a surface it was just handed, where it is the right question. Verified both halves: an ordinary spawn still shows no frame before content (26 captured frames with content, 0 without), and the only way into the set is one line in one function.
Diffstat (limited to 'crates/wayland/src/udev')
-rw-r--r--crates/wayland/src/udev/capture.rs2
-rw-r--r--crates/wayland/src/udev/platform.rs2
-rw-r--r--crates/wayland/src/udev/render.rs4
3 files changed, 4 insertions, 4 deletions
diff --git a/crates/wayland/src/udev/capture.rs b/crates/wayland/src/udev/capture.rs
index 287c003..310c9f7 100644
--- a/crates/wayland/src/udev/capture.rs
+++ b/crates/wayland/src/udev/capture.rs
@@ -71,7 +71,7 @@ impl CompState {
for id in ids {
// Matches the render loops: a capture must not show a frame the
// screen does not (see `window_has_content`).
- if !Self::has_content(&self.windows_shown_once, &self.id_to_window, id) {
+ if !Self::has_content(&self.awaiting_first_buffer, id) {
continue;
}
let Some(w) = self.id_to_window.get(&id) else { continue };
diff --git a/crates/wayland/src/udev/platform.rs b/crates/wayland/src/udev/platform.rs
index 86307dc..d3c091c 100644
--- a/crates/wayland/src/udev/platform.rs
+++ b/crates/wayland/src/udev/platform.rs
@@ -256,7 +256,7 @@ impl UdevPlatform {
dead_layer_surfaces: HashSet::new(),
hidden_layer_surfaces: HashMap::new(),
layer_surfaces_shown_once: HashSet::new(),
- windows_shown_once: HashSet::new(),
+ awaiting_first_buffer: HashSet::new(),
decorations: HashMap::new(),
border_top_decorations: HashMap::new(),
border_bottom_decorations: HashMap::new(),
diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs
index a2cf367..cefd759 100644
--- a/crates/wayland/src/udev/render.rs
+++ b/crates/wayland/src/udev/render.rs
@@ -308,7 +308,7 @@ impl CompState {
// stand around empty desktop until the client paints,
// then jump when the placeholder size is replaced. See
// `window_has_content`.
- if !Self::has_content(&self.windows_shown_once, &self.id_to_window, id) {
+ if !Self::has_content(&self.awaiting_first_buffer, id) {
continue;
}
let Some(w) = self.wm.borrow().window(id).cloned() else { continue };
@@ -558,7 +558,7 @@ impl CompState {
for &id in &ids {
// See the GPU loop above: a window with no buffer yet has
// nothing for a frame to go around.
- if !Self::has_content(&self.windows_shown_once, &self.id_to_window, id) {
+ if !Self::has_content(&self.awaiting_first_buffer, id) {
continue;
}
let Some(w) = self.wm.borrow().window(id).cloned() else { continue };