aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/riverctl.1.scd9
-rw-r--r--river/Config.zig8
-rw-r--r--river/Seat.zig17
-rw-r--r--river/command.zig3
-rw-r--r--river/command/config.zig13
5 files changed, 48 insertions, 2 deletions
diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index 3dc8330..cebac70 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -228,7 +228,7 @@ A complete list may be found in _/usr/include/linux/input-event-codes.h_
There are three available modes:
- _disabled_: Moving the cursor does not affect focus. This is
- the default
+ the default.
- _normal_: Moving the cursor over a view will focus that view.
Moving the cursor within a view will not re-focus that view if
focus has moved elsewhere.
@@ -238,6 +238,13 @@ A complete list may be found in _/usr/include/linux/input-event-codes.h_
If the view to be focused is on an output that does not have focus,
focus is switched to that output.
+*set-cursor-warp* *disabled*|*on-output-change*
+ Set the cursor warp mode. There are two available modes:
+
+ - _disabled_: Cursor will not be warped. This is the default.
+ - _on-output-change_: When a different output is focused, the cursor will be
+ warped to its center.
+
*opacity* _focused_ _unfocused_ _initial_ _step-size_ _delta-t_
Configure server-side opacity of views, including transition
animations. A value of 0.0 is fully transparent while 1.0 is fully
diff --git a/river/Config.zig b/river/Config.zig
index 91e62e5..606dc6b 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -33,6 +33,11 @@ pub const FocusFollowsCursorMode = enum {
strict,
};
+pub const WarpCursorMode = enum {
+ disabled,
+ @"on-output-change",
+};
+
/// Color of background in RGBA (alpha should only affect nested sessions)
background_color: [4]f32 = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }, // Solarized base03
@@ -60,6 +65,9 @@ csd_filter: std.ArrayList([]const u8),
/// The selected focus_follows_cursor mode
focus_follows_cursor: FocusFollowsCursorMode = .disabled,
+/// If true, the cursor warps to the center of the focused output
+warp_cursor: WarpCursorMode = .disabled,
+
/// The default layout namespace for outputs which have never had a per-output
/// value set. Call Output.handleLayoutNamespaceChange() on setting this if
/// Output.layout_namespace is null.
diff --git a/river/Seat.zig b/river/Seat.zig
index b91a309..e741617 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -266,6 +266,23 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
pub fn focusOutput(self: *Self, output: *Output) void {
if (self.focused_output == output) return;
+ // Warp pointer to center of newly focused output (In layout coordinates),
+ // but only if cursor is not already on the output and this feature is enabled.
+ switch (server.config.warp_cursor) {
+ .disabled => {},
+ .@"on-output-change" => {
+ const layout_box = server.root.output_layout.getBox(output.wlr_output).?;
+ if (!layout_box.containsPoint(self.cursor.wlr_cursor.x, self.cursor.wlr_cursor.y)) {
+ const eff_res = output.getEffectiveResolution();
+ const lx = @intToFloat(f32, layout_box.x + @intCast(i32, eff_res.width / 2));
+ const ly = @intToFloat(f32, layout_box.y + @intCast(i32, eff_res.height / 2));
+ if (!self.cursor.wlr_cursor.warp(null, lx, ly)) {
+ log.err("failed to warp cursor on output change", .{});
+ }
+ }
+ },
+ }
+
var it = self.status_trackers.first;
while (it) |node| : (it = node.next) node.data.sendOutput(.unfocused);
diff --git a/river/command.zig b/river/command.zig
index 313e11b..eb55343 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -58,8 +58,8 @@ const str_to_impl_fn = [_]struct {
.{ .name = "focus-output", .impl = @import("command/output.zig").focusOutput },
.{ .name = "focus-view", .impl = @import("command/focus_view.zig").focusView },
.{ .name = "input", .impl = @import("command/input.zig").input },
- .{ .name = "list-inputs", .impl = @import("command/input.zig").listInputs },
.{ .name = "list-input-configs", .impl = @import("command/input.zig").listInputConfigs},
+ .{ .name = "list-inputs", .impl = @import("command/input.zig").listInputs },
.{ .name = "map", .impl = @import("command/map.zig").map },
.{ .name = "map-pointer", .impl = @import("command/map.zig").mapPointer },
.{ .name = "mod-layout-value", .impl = @import("command/layout.zig").modLayoutValue },
@@ -68,6 +68,7 @@ const str_to_impl_fn = [_]struct {
.{ .name = "output-layout", .impl = @import("command/layout.zig").outputLayout },
.{ .name = "resize", .impl = @import("command/move.zig").resize },
.{ .name = "send-to-output", .impl = @import("command/output.zig").sendToOutput },
+ .{ .name = "set-cursor-warp", .impl = @import("command/config.zig").setCursorWarp },
.{ .name = "set-focused-tags", .impl = @import("command/tags.zig").setFocusedTags },
.{ .name = "set-layout-value", .impl = @import("command/layout.zig").setLayoutValue },
.{ .name = "set-repeat", .impl = @import("command/set_repeat.zig").setRepeat },
diff --git a/river/command/config.zig b/river/command/config.zig
index 1ae0c5c..80539d4 100644
--- a/river/command/config.zig
+++ b/river/command/config.zig
@@ -21,6 +21,7 @@ const server = &@import("../main.zig").server;
const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig");
+const Config = @import("../Config.zig");
pub fn borderWidth(
allocator: *std.mem.Allocator,
@@ -81,6 +82,18 @@ pub fn borderColorUnfocused(
while (it) |node| : (it = node.next) node.data.damage.addWhole();
}
+pub fn setCursorWarp(
+ 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;
+ server.config.warp_cursor = std.meta.stringToEnum(Config.WarpCursorMode, args[1]) orelse
+ return Error.UnknownOption;
+}
+
/// Parse a color in the format #RRGGBB or #RRGGBBAA
fn parseRgba(string: []const u8) ![4]f32 {
if (string[0] != '#' or (string.len != 7 and string.len != 9)) return error.InvalidRgba;