git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitd29381a19a3b226bf533d8029fa7f6fe2d89ae88
parentde66e48018
authorIsaac Freund <[email protected]>
date2026-04-17 09:48
Window: fix frame perfection edge case on map

If the river_window.dimensions event is not sent in the first render
sequence after the propose_dimensions request, river may render an
imperfect frame after the client commits initial dimensions and before
the following render sequence is completed.

This commit fixes the bug.

 river/Window.zig | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/river/Window.zig b/river/Window.zig
index 1dfab9f..45037b9 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -882,8 +882,8 @@ pub fn renderStart(window: *Window) void {
     const sent = &window.rendering_sent;
     const scheduled = &window.rendering_scheduled;
 
-    // The check for 0 width/height is necessary to handle timeout of the first configure sent.
-    if (scheduled.width != 0 and scheduled.height != 0 and
+    // Check if mapped to handle timeout of the first configure sent.
+    if (window.state == .mapped and
         (scheduled.resend_dimensions or
             scheduled.width != sent.width or scheduled.height != sent.height))
     {
@@ -917,8 +917,16 @@ fn presentationHint(window: *Window) river.OutputV1.PresentationMode {
 
 pub fn renderFinish(window: *Window) void {
     const requested = &window.rendering_requested;
-    window.tree.node.setEnabled(!requested.hidden);
-    window.popup_tree.node.setEnabled(!requested.hidden);
+
+    // Keep the scene nodes disabled until the render sequence in which the first
+    // dimensions event was sent is completed. If we enable the nodes before the
+    // window is mapped, there may be an imperfect frame rendered after the window
+    // commits its initial buffer and before the render sequence with the first
+    // dimensions event is completed.
+    // Keeping the nodes enabled while closing is necessary for frame perfection.
+    const enabled = !requested.hidden and (window.state == .mapped or window.state == .closing);
+    window.tree.node.setEnabled(enabled);
+    window.popup_tree.node.setEnabled(enabled);
 
     window.box.width = window.rendering_sent.width;
     window.box.height = window.rendering_sent.height;