aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de>2021-05-07 03:46:26 +0200
committerIsaac Freund <ifreund@ifreund.xyz>2021-06-26 19:03:49 +0200
commit085cca0d5e72ef04874671c58676781c208d4c65 (patch)
tree1aa2fc7ad7de223401d72b2423fabcc07ff19187
parent505639432efc22ee8c85c4a9b34e111acbe896d4 (diff)
downloadriver-085cca0d5e72ef04874671c58676781c208d4c65.tar.gz
river-085cca0d5e72ef04874671c58676781c208d4c65.tar.xz
cursor: add option to warp on output change
On output change, if the cursor is not already on the newly focused output, it will now be warped to its center. The check is necessary, since focusing outputs with the pointer will be implemented in the future.
-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;