From 59d6432332a8e021e56e69f0f8c1f1c184744c80 Mon Sep 17 00:00:00 2001 From: Leon Henrik Plickat Date: Mon, 17 Aug 2020 23:13:16 +0200 Subject: [PATCH] Implement "attach-mode" --- doc/riverctl.1.scd | 3 +++ river/Output.zig | 5 +++++ river/View.zig | 4 ++-- river/command.zig | 1 + river/command/attach_mode.zig | 41 +++++++++++++++++++++++++++++++++++ river/view_stack.zig | 32 +++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 river/command/attach_mode.zig diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index 3f32965..3b7da3c 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -95,6 +95,9 @@ that tag 1 through 9 are visible. ## CONFIGURATION COMMANDS +*attach-mode* *top*|*bottom* + Configure where new views should attach in the view stack for the currently focused output. + *background-color* _#RRGGBB_|_#RRGGBBAA_ Set the background color. diff --git a/river/Output.zig b/river/Output.zig index a62c724..777d831 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -30,6 +30,7 @@ const LayerSurface = @import("LayerSurface.zig"); const Root = @import("Root.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; +const AttachMode = @import("view_stack.zig").AttachMode; const OutputStatus = @import("OutputStatus.zig"); const State = struct { @@ -37,6 +38,8 @@ const State = struct { tags: u32, }; +attach_mode: AttachMode, + root: *Root, wlr_output: *c.wlr_output, @@ -107,6 +110,8 @@ pub fn init(self: *Self, root: *Root, wlr_output: *c.wlr_output) !void { self.layout = try std.mem.dupe(util.gpa, u8, "full"); + self.attach_mode = .top; + self.status_trackers = std.SinglyLinkedList(OutputStatus).init(); // Set up listeners diff --git a/river/View.zig b/river/View.zig index d745f6d..2686b2e 100644 --- a/river/View.zig +++ b/river/View.zig @@ -243,7 +243,7 @@ pub fn sendToOutput(self: *Self, destination_output: *Output) void { const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); self.output.views.remove(node); - destination_output.views.push(node); + destination_output.views.attach(node, destination_output.attach_mode); self.output.sendViewTags(); destination_output.sendViewTags(); @@ -340,7 +340,7 @@ pub fn map(self: *Self) void { // Add the view to the stack of its output const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); - self.output.views.push(node); + self.output.views.attach(node, self.output.attach_mode); // Focus the new view, assuming the seat is focusing the proper output // and there isn't something else like a fullscreen view grabbing focus. diff --git a/river/command.zig b/river/command.zig index dc6619d..7cb685e 100644 --- a/river/command.zig +++ b/river/command.zig @@ -30,6 +30,7 @@ const str_to_impl_fn = [_]struct { name: []const u8, impl: fn (*std.mem.Allocator, *Seat, []const []const u8, *?[]const u8) Error!void, }{ + .{ .name = "attach-mode", .impl = @import("command/attach_mode.zig").attach_mode }, .{ .name = "background-color", .impl = @import("command/config.zig").backgroundColor }, .{ .name = "border-color-focused", .impl = @import("command/config.zig").borderColorFocused }, .{ .name = "border-color-unfocused", .impl = @import("command/config.zig").borderColorUnfocused }, diff --git a/river/command/attach_mode.zig b/river/command/attach_mode.zig new file mode 100644 index 0000000..a689893 --- /dev/null +++ b/river/command/attach_mode.zig @@ -0,0 +1,41 @@ +// This file is part of river, a dynamic tiling wayland compositor. +// +// Copyright 2020 Leon Henrik Plickat +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +const std = @import("std"); + +const util = @import("../util.zig"); + +const Error = @import("../command.zig").Error; +const Seat = @import("../Seat.zig"); + +pub fn attach_mode( + allocator: *std.mem.Allocator, + seat: *Seat, + args: []const []const u8, + out: *?[]const u8, +) Error!void { + if (args.len < 2) return Error.NotEnoughArguments; + if (args.len > 2) return Error.TooManyArguments; + + if (std.mem.eql(u8, "top", args[1])) { + seat.focused_output.attach_mode = .top; + } else if (std.mem.eql(u8, "bottom", args[1])) { + seat.focused_output.attach_mode = .bottom; + } else { + return Error.UnknownOption; + } +} diff --git a/river/view_stack.zig b/river/view_stack.zig index ea344d1..eb69ebc 100644 --- a/river/view_stack.zig +++ b/river/view_stack.zig @@ -17,6 +17,11 @@ const View = @import("View.zig"); +pub const AttachMode = enum { + top, + bottom, +}; + /// A specialized doubly-linked stack that allows for filtered iteration /// over the nodes. T must be View or *View. pub fn ViewStack(comptime T: type) type { @@ -64,6 +69,33 @@ pub fn ViewStack(comptime T: type) type { self.first = new_node; } + /// Add a node to the bottom of the stack. + pub fn append(self: *Self, new_node: *Node) void { + // Set the prev/next pointers of the new node + new_node.prev = self.last; + new_node.next = null; + + if (self.last) |last| { + // If the list is not empty, set the next pointer of the current + // first node to the new node. + last.next = new_node; + } else { + // If the list is empty set the first pointer to the new node. + self.first = new_node; + } + + // Set the last pointer to the new node + self.last = new_node; + } + + /// Attach a node into the viewstack based on the attach mode + pub fn attach(self: *Self, new_node: *Node, mode: AttachMode) void { + switch (mode) { + .top => self.push(new_node), + .bottom => self.append(new_node), + } + } + /// Remove a node from the view stack. This removes it from the stack of /// all views as well as the stack of visible ones. pub fn remove(self: *Self, target_node: *Node) void {