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

commit5644d872699443f120333895fbf602eea77f6139
parent3e355376ce
authorpmkap <[email protected]>
date2022-02-06 14:41
command: allow targeting outputs by name

This extends focus-output and send-to-output to allow targeting
outputs by name instead of relative position.

 doc/riverctl.1.scd       | 11 ++++++-----
 river/command.zig        |  2 ++
 river/command/output.zig | 11 ++++++++++-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index 32be2a1..d4ba768 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -50,8 +50,9 @@ over the Wayland protocol.
 	Remove an app-id or title from the float filter list. Note that this
 	affects only new views, not already existing ones.
 
-*focus-output* *next*|*previous*|*up*|*right*|*down*|*left*
-	Focus the next or previous output or the closest output in any direction.
+*focus-output* *next*|*previous*|*up*|*right*|*down*|*left*|_name_
+	Focus the next or previous output, the closest output in any direction
+	or an output by name.
 
 *focus-view* *next*|*previous*
 	Focus the next or previous view in the stack.
@@ -68,9 +69,9 @@ over the Wayland protocol.
 	Snap the focused view to the specified screen edge. The view will
 	be set to floating.
 
-*send-to-output* *next*|*previous*|*up*|*right*|*down*|*left*
-	Send the focused view to the next or previous output or the closest
-	output in any direction.
+*send-to-output* *next*|*previous*|*up*|*right*|*down*|*left*|_name_
+	Send the focused view to the next or previous output, the closest
+	output in any direction or to an output by name.
 
 *spawn* _shell_command_
 	Run _shell_command_ using `/bin/sh -c _shell_command_`. Note that
diff --git a/river/command.zig b/river/command.zig
index fc52eea..22ba014 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -99,6 +99,7 @@ pub const Error = error{
     InvalidCharacter,
     InvalidDirection,
     InvalidPhysicalDirection,
+    InvalidOutputIndicator,
     InvalidOrientation,
     InvalidRgba,
     InvalidValue,
@@ -141,6 +142,7 @@ pub fn errToMsg(err: Error) [:0]const u8 {
         Error.InvalidCharacter => "invalid character in argument",
         Error.InvalidDirection => "invalid direction. Must be 'next' or 'previous'",
         Error.InvalidPhysicalDirection => "invalid direction. Must be 'up', 'down', 'left' or 'right'",
+        Error.InvalidOutputIndicator => "invalid indicator for an output. Must be 'next', 'previous', 'up', 'down', 'left', 'right' or a valid output name",
         Error.InvalidOrientation => "invalid orientation. Must be 'horizontal', or 'vertical'",
         Error.InvalidRgba => "invalid color format, must be hexadecimal 0xRRGGBB or 0xRRGGBBAA",
         Error.InvalidValue => "invalid value",
diff --git a/river/command/output.zig b/river/command/output.zig
index 22cc837..4bbd717 100644
--- a/river/command/output.zig
+++ b/river/command/output.zig
@@ -63,6 +63,8 @@ pub fn sendToOutput(
 
     if (seat.focused == .view) {
         const destination_output = (try getOutput(seat, args[1])) orelse return;
+        // If the view is already on destination_output, do nothing
+        if (seat.focused.view.output == destination_output) return;
         seat.focused.view.sendToOutput(destination_output);
 
         // Handle the change and focus whatever's next in the focus stack
@@ -93,6 +95,13 @@ fn getOutput(seat: *Seat, str: []const u8) !?*Output {
         ) orelse return null;
         return @intToPtr(*Output, wlr_output.data);
     } else {
-        return Error.InvalidDirection;
+        // Check if an output matches by name
+        var it = server.root.outputs.first;
+        while (it) |node| : (it = node.next) {
+            if (std.mem.eql(u8, std.mem.span(node.data.wlr_output.name), str)) {
+                return &node.data;
+            }
+        }
+        return Error.InvalidOutputIndicator;
     }
 }