diff --git a/river/Root.zig b/river/Root.zig index 5743d30..7399408 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -280,6 +280,10 @@ pub fn deactivateOutput(root: *Self, output: *Output) void { view.inflight_wm_stack_link.remove(); view.inflight_wm_stack_link.init(); + + if (view.inflight_transaction) { + view.commitTransaction(); + } } } // Use the first output in the list as fallback. If the last real output @@ -552,11 +556,16 @@ fn sendConfigures(root: *Self) void { while (output_it.next()) |output| { var focus_stack_it = output.inflight.focus_stack.iterator(.forward); while (focus_stack_it.next()) |view| { + assert(!view.inflight_transaction); + view.inflight_transaction = true; + // This can happen if a view is unmapped while a layout demand including it is inflight + // If a view has been unmapped, don't send it a configure. if (!view.mapped) continue; if (view.configure()) { root.inflight_configures += 1; + view.saveSurfaceTree(); view.sendFrameDone(); } @@ -617,8 +626,6 @@ fn commitTransaction(root: *Self) void { view.tree.node.reparent(root.hidden.tree); view.popup_tree.node.reparent(root.hidden.tree); - - view.commitTransaction(); } } diff --git a/river/View.zig b/river/View.zig index 4de5fc1..b5b418e 100644 --- a/river/View.zig +++ b/river/View.zig @@ -131,6 +131,8 @@ popup_tree: *wlr.SceneTree, constraints: Constraints = .{}, mapped: bool = false, +/// This is true if the View is involved in the currently inflight transaction. +inflight_transaction: bool = false, /// This indicates that the view should be destroyed when the current /// transaction completes. See View.destroy() destroying: bool = false, @@ -273,6 +275,9 @@ pub fn resizeUpdatePosition(view: *Self, width: i32, height: i32) void { } pub fn commitTransaction(view: *Self) void { + assert(view.inflight_transaction); + view.inflight_transaction = false; + view.foreign_toplevel_handle.update(); // Tag and output changes must be applied immediately even if the configure sequence times out.