diff --git a/river/Root.zig b/river/Root.zig index d0707c3..d6b86b9 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -286,6 +286,15 @@ pub fn deactivateOutput(root: *Self, output: *Output) void { if (view.inflight_transaction) { view.commitTransaction(); } + + // Store outputs connector name so that views can be moved back to + // reconnecting outputs. Skip if there is already a connector name + // stored to better handle the case of multiple outputs being + // removed sequentially. + if (view.output_before_evac == null) { + const name = mem.span(output.wlr_output.name); + view.output_before_evac = util.gpa.dupe(u8, name) catch null; + } } } // Use the first output in the list as fallback. If the last real output @@ -386,6 +395,20 @@ pub fn activateOutput(root: *Self, output: *Output) void { seat.focusOutput(output); } } + } else { + // Otherwise check if any views were previously evacuated from an output + // with the same (connector-)name and move them back. + var it = root.views.iterator(.forward); + while (it.next()) |view| { + const name = view.output_before_evac orelse continue; + if (mem.eql(u8, name, mem.span(output.wlr_output.name))) { + if (view.pending.output != output) { + view.setPendingOutput(output); + } + util.gpa.free(name); + view.output_before_evac = null; + } + } } assert(root.fallback_pending.focus_stack.empty()); assert(root.fallback_pending.wm_stack.empty()); diff --git a/river/View.zig b/river/View.zig index 311b960..9a8f5ce 100644 --- a/river/View.zig +++ b/river/View.zig @@ -174,6 +174,9 @@ post_fullscreen_box: wlr.Box = undefined, foreign_toplevel_handle: ForeignToplevelHandle = .{}, +/// Connector name of the output this view occupied before an evacuation. +output_before_evac: ?[]const u8 = null, + pub fn create(impl: Impl) error{OutOfMemory}!*Self { assert(impl != .none); @@ -243,6 +246,8 @@ pub fn destroy(view: *Self) void { view.inflight_focus_stack_link.remove(); view.inflight_wm_stack_link.remove(); + if (view.output_before_evac) |name| util.gpa.free(name); + util.gpa.destroy(view); } } diff --git a/river/command/output.zig b/river/command/output.zig index 088aee8..3e10635 100644 --- a/river/command/output.zig +++ b/river/command/output.zig @@ -22,6 +22,7 @@ const wlr = @import("wlroots"); const flags = @import("flags"); const server = &@import("../main.zig").server; +const util = @import("../util.zig"); const Direction = @import("../command.zig").Direction; const PhysicalDirectionDirection = @import("../command.zig").PhysicalDirection; @@ -79,6 +80,14 @@ pub fn sendToOutput( seat.focused.view.setPendingOutput(destination_output); + // When explicitly sending a view to an output, the user likely + // does not expect a previously evacuated view moved back to a + // re-connecting output. + if (seat.focused.view.output_before_evac) |name| { + util.gpa.free(name); + seat.focused.view.output_before_evac = null; + } + server.root.applyPending(); } }