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

commitbb0101cd8b51b7a299c3f279cf0814be1b297b4f
parent6a4f37f03c
authorpolykernel <[email protected]>
date2023-11-06 10:53
river: add fullscreen rule

This commit adds a fullscreen rule for configuring
whether the view should be drawn fullscreen on start up.

The actions "fullscreen" and "no-fullscreen" map to the two
possible state of a view and semantically operate on the same
rule list. The behavior of adding, deleting and listing rules
follows that of float and ssd.

 completions/bash/riverctl      |  4 ++--
 completions/fish/riverctl.fish |  4 ++--
 completions/zsh/_riverctl      |  4 ++--
 doc/riverctl.1.scd             |  4 ++--
 river/View.zig                 |  3 +++
 river/command/rule.zig         | 24 +++++++++++++++++++++++-
 6 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/completions/bash/riverctl b/completions/bash/riverctl
index c92e001..c756321 100644
--- a/completions/bash/riverctl
+++ b/completions/bash/riverctl
@@ -1,6 +1,6 @@
 function __riverctl_completion ()
 {
-	local rule_actions="float no-float ssd csd tag output position dimensions"
+	local rule_actions="float no-float ssd csd tag output position dimensions fullscreen no-fullscreen"
 	if [ "${COMP_CWORD}" -eq 1 ]
 	then
 		OPTS=" \
@@ -66,7 +66,7 @@ function __riverctl_completion ()
 			"move"|"snap") OPTS="up down left right" ;;
 			"resize") OPTS="horizontal vertical" ;;
 			"rule-add"|"rule-del") OPTS="-app-id -title $rule_actions" ;;
-			"list-rules") OPTS="float ssd tag output position dimensions" ;;
+			"list-rules") OPTS="float ssd tag output position dimensions fullscreen" ;;
 			"map") OPTS="-release -repeat -layout" ;;
 			"unmap") OPTS="-release" ;;
 			"attach-mode") OPTS="top bottom" ;;
diff --git a/completions/fish/riverctl.fish b/completions/fish/riverctl.fish
index 5f596b9..9b321f3 100644
--- a/completions/fish/riverctl.fish
+++ b/completions/fish/riverctl.fish
@@ -88,10 +88,10 @@ complete -c riverctl -n '__fish_seen_subcommand_from unmap'
 complete -c riverctl -n '__fish_seen_subcommand_from attach-mode'                 -n '__fish_riverctl_complete_arg 2' -a 'top bottom'
 complete -c riverctl -n '__fish_seen_subcommand_from focus-follows-cursor'        -n '__fish_riverctl_complete_arg 2' -a 'disabled normal always'
 complete -c riverctl -n '__fish_seen_subcommand_from set-cursor-warp'             -n '__fish_riverctl_complete_arg 2' -a 'disabled on-output-change on-focus-change'
-complete -c riverctl -n '__fish_seen_subcommand_from list-rules'                  -n '__fish_riverctl_complete_arg 2' -a 'float ssd tag output position dimensions'
+complete -c riverctl -n '__fish_seen_subcommand_from list-rules'                  -n '__fish_riverctl_complete_arg 2' -a 'float ssd tag output position dimensions fullscreen'
 
 # Options and subcommands for 'rule-add' and 'rule-del'
-set -l rule_actions float no-float ssd csd tag output position dimensions
+set -l rule_actions float no-float ssd csd tag output position dimensions fullscreen no-fullscreen
 complete -c riverctl -n '__fish_seen_subcommand_from rule-add rule-del' -n "not __fish_seen_subcommand_from $rule_actions" -n 'not __fish_seen_argument -o app-id' -o 'app-id' -r
 complete -c riverctl -n '__fish_seen_subcommand_from rule-add rule-del' -n "not __fish_seen_subcommand_from $rule_actions" -n 'not __fish_seen_argument -o title'  -o 'title' -r
 complete -c riverctl -n '__fish_seen_subcommand_from rule-add rule-del' -n "not __fish_seen_subcommand_from $rule_actions" -n 'test (math (count (commandline -opc)) % 2) -eq 0' -a "$rule_actions"
diff --git a/completions/zsh/_riverctl b/completions/zsh/_riverctl
index 2a50abd..6467fbc 100644
--- a/completions/zsh/_riverctl
+++ b/completions/zsh/_riverctl
@@ -183,9 +183,9 @@ _riverctl()
                     # In case of a new rule added in river, we just need
                     # to add it to the third option between '()',
                     # i.e (float no-float <new-option>)
-                    _arguments '1: :(-app-id -title)' '2: : ' ':: :(float no-float ssd csd tag output position dimensions)'
+                    _arguments '1: :(-app-id -title)' '2: : ' ':: :(float no-float ssd csd tag output position dimensions fullscreen no-fullscreen)'
                 ;;
-                list-rules) _alternative 'arguments:args:(float ssd tag output position dimensions)' ;;
+                list-rules) _alternative 'arguments:args:(float ssd tag output position dimensions fullscreen)' ;;
                 *) return 0 ;;
             esac
         ;;
diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index 803f56c..f3704fe 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -311,7 +311,7 @@ matches everything while _\*\*_ and the empty string are invalid.
 	Both *float* and *no-float* rules are added to the same list,
 	which means that adding a *no-float* rule with the same arguments
 	as a *float* rule will overwrite it. The same holds for *ssd* and
-	*csd* rules.
+	*csd*, *fullscreen* and *no-fullscreen* rules.
 
 	If multiple rules in a list match a given view the most specific
 	rule will be applied. For example with the following rules
@@ -339,7 +339,7 @@ matches everything while _\*\*_ and the empty string are invalid.
 *rule-del* [*-app-id* _glob_|*-title* _glob_] _action_
 	Delete a rule created using *rule-add* with the given arguments.
 
-*list-rules* *float*|*ssd*|*tag*|*position*|*dimensions*
+*list-rules* *float*|*ssd*|*tag*|*position*|*dimensions*|*fullscreen*
 	Print the specified rule list. The output is ordered from most specific
 	to least specific, the same order in which views are checked against
 	when searching for a match. Only the first matching rule in the list
diff --git a/river/View.zig b/river/View.zig
index 36d1e12..bd4935d 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -488,6 +488,9 @@ pub fn map(view: *Self) !void {
     if (server.config.float_rules.match(view)) |float| {
         view.pending.float = float;
     }
+    if (server.config.fullscreen_rules.match(view)) |fullscreen| {
+        view.pending.fullscreen = fullscreen;
+    }
     if (server.config.ssd_rules.match(view)) |ssd| {
         view.pending.ssd = ssd;
     }
diff --git a/river/command/rule.zig b/river/command/rule.zig
index 1ccc1ce..0104fad 100644
--- a/river/command/rule.zig
+++ b/river/command/rule.zig
@@ -36,6 +36,8 @@ const Action = enum {
     output,
     position,
     dimensions,
+    fullscreen,
+    @"no-fullscreen",
 };
 
 pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void {
@@ -51,7 +53,7 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
     const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
 
     const positional_arguments_count: u8 = switch (action) {
-        .float, .@"no-float", .ssd, .csd => 1,
+        .float, .@"no-float", .ssd, .csd, .fullscreen, .@"no-fullscreen" => 1,
         .tag, .output => 2,
         .position, .dimensions => 3,
     };
@@ -122,6 +124,13 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
                 },
             });
         },
+        .fullscreen, .@"no-fullscreen" => {
+            try server.config.fullscreen_rules.add(.{
+                .app_id_glob = app_id_glob,
+                .title_glob = title_glob,
+                .value = (action == .fullscreen),
+            });
+        },
     }
 }
 
@@ -165,6 +174,9 @@ pub fn ruleDel(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
         .dimensions => {
             _ = server.config.dimensions_rules.del(rule);
         },
+        .fullscreen, .@"no-fullscreen" => {
+            _ = server.config.fullscreen_rules.del(rule);
+        },
     }
 }
 
@@ -188,6 +200,7 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
         output,
         position,
         dimensions,
+        fullscreen,
     }, args[1]) orelse return Error.UnknownOption;
     const max_glob_len = switch (list) {
         .float => server.config.float_rules.getMaxGlobLen(),
@@ -196,6 +209,7 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
         .output => server.config.output_rules.getMaxGlobLen(),
         .position => server.config.position_rules.getMaxGlobLen(),
         .dimensions => server.config.dimensions_rules.getMaxGlobLen(),
+        .fullscreen => server.config.fullscreen_rules.getMaxGlobLen(),
     };
     const app_id_column_max = 2 + @max("app-id".len, max_glob_len.app_id);
     const title_column_max = 2 + @max("title".len, max_glob_len.title);
@@ -256,6 +270,14 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
                 try writer.print("{d}x{d}\n", .{ rule.value.width, rule.value.height });
             }
         },
+        .fullscreen => {
+            const rules = server.config.fullscreen_rules.rules.items;
+            for (rules) |rule| {
+                try fmt.formatBuf(rule.title_glob, .{ .width = title_column_max, .alignment = .left }, writer);
+                try fmt.formatBuf(rule.app_id_glob, .{ .width = app_id_column_max, .alignment = .left }, writer);
+                try writer.print("{s}\n", .{if (rule.value) "fullscreen" else "no-fullscreen"});
+            }
+        },
     }
 
     out.* = try buffer.toOwnedSlice();