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

commitaf1cb615078336a2020296ee3e591a30db4dc07d
parent4cd4c4bad0
authorIsaac Freund <[email protected]>
date2023-03-01 23:04
View: fix frame perfection on unmap

 river/XdgToplevel.zig  | 10 ++++++++++
 river/XwaylandView.zig |  8 +++++---
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index cb5a20c..cade2eb 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -220,7 +220,17 @@ fn handleUnmap(listener: *wl.Listener(void)) void {
     self.set_title.link.remove();
     self.set_app_id.link.remove();
 
+    // TODO(wlroots): This enable/disable dance is a workaround for an signal
+    // ordering issue with the scene xdg surface helper's unmap handler that
+    // disables the node. We however need the node enabled for View.unmap()
+    // so that we can save buffers for frame perfection.
+    var it = self.view.surface_tree.children.iterator(.forward);
+    const xdg_surface_tree_node = it.next().?;
+    xdg_surface_tree_node.setEnabled(true);
+
     self.view.unmap();
+
+    xdg_surface_tree_node.setEnabled(false);
 }
 
 fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
index 10373d5..d94393b 100644
--- a/river/XwaylandView.zig
+++ b/river/XwaylandView.zig
@@ -222,9 +222,6 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface:
 fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
     const self = @fieldParentPtr(Self, "unmap", listener);
 
-    self.surface_tree.?.node.destroy();
-    self.surface_tree = null;
-
     // Remove listeners that are only active while mapped
     self.set_title.link.remove();
     self.set_class.link.remove();
@@ -232,6 +229,11 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSur
     self.request_minimize.link.remove();
 
     self.view.unmap();
+
+    // Don't destroy the surface tree until after View.unmap() has a chance
+    // to save buffers for frame perfection.
+    self.surface_tree.?.node.destroy();
+    self.surface_tree = null;
 }
 
 fn handleRequestConfigure(