From 4d803360ddcf08c5bd17082a70b9d3a54c4b1ee6 Mon Sep 17 00:00:00 2001 From: atagen Date: Tue, 7 Apr 2026 09:35:31 +1000 Subject: [PATCH] wl_surface: skip damage on null surfaces --- src/ifs/wl_surface.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 3025eaf2..0f399afb 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1443,12 +1443,21 @@ impl WlSurface { self.commit_timeline.set_fifo_barrier(); } if damage_full && (self.visible.get() || was_visible) { - let mut damage = - buffer_abs_pos.with_size_saturating(max_surface_size.0, max_surface_size.1); - if let Some(tl) = self.toplevel.get() { - damage = damage.intersect(tl.node_absolute_position()); + // When a toplevel unmaps (null buffer commit), it transitions from visible to + // invisible here. Skip the immediate damage: the parent container or float node + // already called damage() when removing the child, and for tiled windows the + // deferred layout damage system handles repainting once siblings have resized. + // Emitting damage here creates an intermediate frame showing an empty gap. + let becoming_invisible = + was_visible && !self.visible.get() && self.buffer.is_none(); + if !becoming_invisible || self.toplevel.is_none() { + let mut damage = + buffer_abs_pos.with_size_saturating(max_surface_size.0, max_surface_size.1); + if let Some(tl) = self.toplevel.get() { + damage = damage.intersect(tl.node_absolute_position()); + } + self.client.state.damage(damage); } - self.client.state.damage(damage); } if self.visible.get() { let output = self.output.get();