aboutsummaryrefslogtreecommitdiff
path: root/river/Cursor.zig
diff options
context:
space:
mode:
Diffstat (limited to 'river/Cursor.zig')
-rw-r--r--river/Cursor.zig50
1 files changed, 50 insertions, 0 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 1d83444..3f15f3b 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -105,6 +105,7 @@ pressed_count: u32 = 0,
hide_cursor_timer: *wl.EventSource,
hidden: bool = false,
+may_need_warp: bool = false,
axis: wl.Listener(*wlr.Pointer.event.Axis) = wl.Listener(*wlr.Pointer.event.Axis).init(handleAxis),
frame: wl.Listener(*wlr.Cursor) = wl.Listener(*wlr.Cursor).init(handleFrame),
@@ -1050,6 +1051,9 @@ pub fn checkFocusFollowsCursor(self: *Self) void {
/// the target view of a cursor operation potentially being moved to a non-visible tag,
/// becoming fullscreen, etc.
pub fn updateState(self: *Self) void {
+ if (self.may_need_warp) {
+ self.warp();
+ }
if (self.shouldPassthrough()) {
self.mode = .passthrough;
var now: os.timespec = undefined;
@@ -1103,3 +1107,49 @@ fn passthrough(self: *Self, time: u32) void {
self.clearFocus();
}
}
+
+fn warp(self: *Self) void {
+ self.may_need_warp = false;
+ if (self.seat.focused_output == &server.root.noop_output) return;
+ // Warp pointer to center of the focused view/output (In layout coordinates) if enabled.
+ var output_layout_box: wlr.Box = undefined;
+ server.root.output_layout.getBox(self.seat.focused_output.wlr_output, &output_layout_box);
+ const target_box = switch (server.config.warp_cursor) {
+ .disabled => return,
+ .@"on-output-change" => output_layout_box,
+ .@"on-focus-change" => switch (self.seat.focused) {
+ .layer, .lock_surface, .none => output_layout_box,
+ .view => |view| wlr.Box{
+ .x = output_layout_box.x + view.current.box.x,
+ .y = output_layout_box.y + view.current.box.y,
+ .width = view.current.box.width,
+ .height = view.current.box.height,
+ },
+ .xwayland_override_redirect => |or_window| wlr.Box{
+ .x = or_window.xwayland_surface.x,
+ .y = or_window.xwayland_surface.y,
+ .width = or_window.xwayland_surface.width,
+ .height = or_window.xwayland_surface.height,
+ },
+ },
+ };
+ // Checking against the usable box here gives much better UX when, for example,
+ // a status bar allows using the pointer to change tag/view focus.
+ const usable_box = self.seat.focused_output.usable_box;
+ const usable_layout_box = wlr.Box{
+ .x = output_layout_box.x + usable_box.x,
+ .y = output_layout_box.y + usable_box.y,
+ .width = usable_box.width,
+ .height = usable_box.height,
+ };
+ if (!output_layout_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y) or
+ (usable_layout_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y) and
+ !target_box.containsPoint(self.wlr_cursor.x, self.wlr_cursor.y)))
+ {
+ const lx = @intToFloat(f64, target_box.x + @divTrunc(target_box.width, 2));
+ const ly = @intToFloat(f64, target_box.y + @divTrunc(target_box.height, 2));
+ if (!self.wlr_cursor.warp(null, lx, ly)) {
+ log.err("failed to warp cursor on focus change", .{});
+ }
+ }
+}