diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index ea910d4..6a0edd1 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -345,18 +345,20 @@ matches everything while _\*\*_ and the empty string are invalid. ## CONFIGURATION -*default-attach-mode* *top*|*bottom*|*after * +*default-attach-mode* *top*|*bottom*|*above*|*below*|*after * Set the attach mode to be used by all outputs by default. Possible values: - top: Prepends the newly spawned view at the top of the stack. - bottom: Appends the newly spawned view at the bottom of the stack. + - above: Inserts the newly spawned view above the currently focused view. + - below: Inserts the newly spawned view below the currently focused view. - after : Inserts the newly spawned view after N views in the stack. Note that the deprecated *attach-mode* command is aliased to *default-attach-mode* for backwards compatibility. -*output-attach-mode* *top*|*bottom*|*after * +*output-attach-mode* *top*|*bottom*|*above*|*below*|*after * Set the attach mode of the currently focused output, overriding the value of default-attach-mode if any. diff --git a/river/Config.zig b/river/Config.zig index 005cd48..539a02b 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -35,6 +35,8 @@ pub const AttachMode = union(enum) { top, bottom, after: u32, + above, + below, }; pub const FocusFollowsCursorMode = enum { diff --git a/river/Output.zig b/river/Output.zig index d208cb6..32f221a 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -60,6 +60,20 @@ pub const PendingState = struct { /// /// This includes both floating/fullscreen views and those arranged in the layout. wm_stack: wl.list.Head(View, .pending_wm_stack_link), + /// + /// Index of the first view in focus_stack in the wm_stack list. + pub fn focusedIndex(self: *PendingState) ?u32 { + var focus_stack_it = self.focus_stack.iterator(.forward); + const focused_view = focus_stack_it.next() orelse return null; + + var it = self.wm_stack.iterator(.forward); + var count: u32 = 0; + while (it.next()) |other| { + if (other == focused_view) break; + count += 1; + } + return count; + } }; wlr_output: *wlr.Output, diff --git a/river/View.zig b/river/View.zig index 5bd0084..592f2d9 100644 --- a/river/View.zig +++ b/river/View.zig @@ -479,6 +479,14 @@ pub fn setPendingOutput(view: *Self, output: *Output) void { .top => output.pending.wm_stack.prepend(view), .bottom => output.pending.wm_stack.append(view), .after => |n| view.attachAfter(&output.pending, n), + .above => view.attachAfter( + &output.pending, + output.pending.focusedIndex() orelse 0, + ), + .below => view.attachAfter( + &output.pending, + (output.pending.focusedIndex() orelse 0) + 1, + ), } output.pending.focus_stack.prepend(view); @@ -607,6 +615,14 @@ pub fn map(view: *Self) !void { .top => server.root.fallback_pending.wm_stack.prepend(view), .bottom => server.root.fallback_pending.wm_stack.append(view), .after => |n| view.attachAfter(&server.root.fallback_pending, n), + .above => view.attachAfter( + &server.root.fallback_pending, + server.root.fallback_pending.focusedIndex() orelse 0, + ), + .below => view.attachAfter( + &server.root.fallback_pending, + (server.root.fallback_pending.focusedIndex() orelse 0) + 1, + ), } server.root.fallback_pending.focus_stack.prepend(view); diff --git a/river/command/attach_mode.zig b/river/command/attach_mode.zig index ef74edd..6ffc615 100644 --- a/river/command/attach_mode.zig +++ b/river/command/attach_mode.zig @@ -29,7 +29,7 @@ fn parseAttachMode(args: []const [:0]const u8) Error!Config.AttachMode { const tag = meta.stringToEnum(meta.Tag(Config.AttachMode), args[1]) orelse return Error.UnknownOption; switch (tag) { - inline .top, .bottom => |mode| { + inline .top, .bottom, .above, .below => |mode| { if (args.len > 2) return Error.TooManyArguments; return mode;