git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit1c546be63499cc98106b45f95c6906b01f78c4d6
parent69c063b985
authorMarten Ringwelski <[email protected]>
date2021-01-02 09:43
command: Implement spawn-tagmask

 doc/riverctl.1.scd     | 10 ++++++++++
 river/Output.zig       |  3 +++
 river/Server.zig       |  9 +++++++--
 river/command.zig      |  1 +
 river/command/tags.zig | 11 +++++++++++
 5 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index ef51ee1..9caa4ac 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -104,6 +104,8 @@ take a normal base 10 number as their argument but the semantics are best
 understood in binary. The binary number 000000001 represents a set containing
 only tag 1 while 100001101 represents a set containing tags 1, 3, 4, and 9.
 
+When a view spawns it is assigned the currently focused tags of the output.
+
 At least one tag must always be focused and each view must be assigned at
 least one tag. Operations that would violate either of these requirements
 are ignored by river.
@@ -124,6 +126,14 @@ are ignored by river.
 	Toggle the tags of the currently focused view corresponding to the
 	set bits of _tags_.
 
+*spawn-tagmask* _tagmask_
+	Set a _tagmask_ to filter the tags assigned to newly spawned views
+	on the focused output. This mask will be applied to the tags of
+	new views with a bitwise and. If, for example, the tags 000011111
+	are focused on an output with a _tagmask_ of 111110001, a new view
+	will be assigned the tags 000010001. If no tags would remain after
+	filtering, the _tagmask_ is ignored.
+
 ## MAPPINGS
 
 Mappings are modal in river. Each mapping is associated with a mode and is
diff --git a/river/Output.zig b/river/Output.zig
index 2a70c25..c8cd6c3 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -73,6 +73,9 @@ layout: []const u8,
 /// Determines where new views will be attached to the view stack.
 attach_mode: AttachMode = .top,
 
+/// Bitmask that whitelists tags for newly spawned views
+spawn_tagmask: u32 = std.math.maxInt(u32),
+
 /// List of status tracking objects relaying changes to this output to clients.
 status_trackers: std.SinglyLinkedList(OutputStatus) = .{},
 
diff --git a/river/Server.zig b/river/Server.zig
index bcebe01..a5f7ca0 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -177,7 +177,7 @@ fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wl
         xdg_surface.resource.postNoMemory();
         return;
     };
-    node.view.init(output, output.current.tags, xdg_surface);
+    node.view.init(output, getNewViewTags(output), xdg_surface);
 }
 
 /// This event is raised when the layer_shell recieves a new surface from a client.
@@ -247,5 +247,10 @@ fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), wlr_xw
     // The View will add itself to the output's view stack on map
     const output = self.input_manager.defaultSeat().focused_output;
     const node = util.gpa.create(ViewStack(View).Node) catch return;
-    node.view.init(output, output.current.tags, wlr_xwayland_surface);
+    node.view.init(output, getNewViewTags(output), wlr_xwayland_surface);
+}
+
+fn getNewViewTags(output: *Output) u32 {
+    const tags = output.current.tags & output.spawn_tagmask;
+    return if (tags != 0) tags else output.current.tags;
 }
diff --git a/river/command.zig b/river/command.zig
index 90dd793..88acdbc 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -71,6 +71,7 @@ const str_to_impl_fn = [_]struct {
     .{ .name = "set-view-tags",          .impl = @import("command/tags.zig").setViewTags },
     .{ .name = "snap",                   .impl = @import("command/move.zig").snap },
     .{ .name = "spawn",                  .impl = @import("command/spawn.zig").spawn },
+    .{ .name = "spawn-tagmask",          .impl = @import("command/tags.zig").spawnTagmask },
     .{ .name = "swap",                   .impl = @import("command/swap.zig").swap},
     .{ .name = "toggle-float",           .impl = @import("command/toggle_float.zig").toggleFloat },
     .{ .name = "toggle-focused-tags",    .impl = @import("command/tags.zig").toggleFocusedTags },
diff --git a/river/command/tags.zig b/river/command/tags.zig
index fa89626..9fd28d3 100644
--- a/river/command/tags.zig
+++ b/river/command/tags.zig
@@ -36,6 +36,17 @@ pub fn setFocusedTags(
     }
 }
 
+/// Set the spawn tagmask
+pub fn spawnTagmask(
+    allocator: *std.mem.Allocator,
+    seat: *Seat,
+    args: []const []const u8,
+    out: *?[]const u8,
+) Error!void {
+    const tags = try parseTags(allocator, args, out);
+    seat.focused_output.spawn_tagmask = tags;
+}
+
 /// Set the tags of the focused view.
 pub fn setViewTags(
     allocator: *std.mem.Allocator,