Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
command/attach-modes: above and below options
doc/riverctl.1.scd | 6 ++++--
river/Config.zig | 2 ++
river/Output.zig | 14 ++++++++++++++
river/View.zig | 16 ++++++++++++++++
river/command/attach_mode.zig | 2 +-
5 files changed, 37 insertions(+), 3 deletions(-)
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 <N>*
+*default-attach-mode* *top*|*bottom*|*above*|*below*|*after <N>*
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 <N>: 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 <N>*
+*output-attach-mode* *top*|*bottom*|*above*|*below*|*after <N>*
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;