aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshironeko <shironeko@tesaguri.club>2022-12-31 13:51:42 -0500
committerIsaac Freund <mail@isaacfreund.com>2023-01-01 18:05:41 +0100
commit931405abe46e12485f2439135bd0fa20ea7fc984 (patch)
treed2c2bb256bd2d230aa1a7ef5330518f86e9fde07
parent2c86c2b6e59c5a0de54b5734a83b0f80caf2df04 (diff)
downloadriver-931405abe46e12485f2439135bd0fa20ea7fc984.tar.gz
river-931405abe46e12485f2439135bd0fa20ea7fc984.tar.xz
Rework focus-follows-cursor to work with warp
When focus-follows-cursor is used with cursor-warp, some windows will get focus before the cursor properly "enters" the window since they have a larger input-region than their window geometry, this causes the cursor to be yanked to the middle unexpectedly. This fix makes it so the focus is only given when the cursor enters the window geometry.
-rw-r--r--river/Cursor.zig42
1 files changed, 28 insertions, 14 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index d73c376..24aa5a1 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -112,6 +112,8 @@ hide_cursor_timer: *wl.EventSource,
hidden: bool = false,
may_need_warp: bool = false,
+last_focus_follows_cursor_target: ?*View = null,
+
/// Keeps track of the last known location of all touch points in layout coordinates.
/// This information is necessary for proper touch dnd support if there are multiple touch points.
touch_points: std.AutoHashMapUnmanaged(i32, LayoutPoint) = .{},
@@ -1049,21 +1051,33 @@ pub fn checkFocusFollowsCursor(self: *Self) void {
if (self.seat.drag == .pointer) return;
if (server.config.focus_follows_cursor == .disabled) return;
if (self.surfaceAt()) |result| {
- if (server.config.focus_follows_cursor == .always or
- self.seat.wlr_seat.pointer_state.focused_surface != result.surface)
- {
- switch (result.parent) {
- .view => |view| {
- if (self.seat.focused != .view or self.seat.focused.view != view) {
- self.seat.focusOutput(view.output);
- self.seat.focus(view);
- server.root.startTransaction();
- }
- },
- .layer_surface, .lock_surface => {},
- .xwayland_override_redirect => assert(build_options.xwayland),
- }
+ switch (result.parent) {
+ .view => |view| {
+ // Don't re-focus the last focused view when the mode is .normal
+ if (server.config.focus_follows_cursor == .normal and
+ self.last_focus_follows_cursor_target == view) return;
+ // Some windows have a input region bigger than their window
+ // geometry, we only want to move focus when the cursor
+ // properly enters the window (the box that we draw borders around)
+ var output_layout_box: wlr.Box = undefined;
+ server.root.output_layout.getBox(view.output.wlr_output, &output_layout_box);
+ const cursor_ox = self.wlr_cursor.x - @intToFloat(f64, output_layout_box.x);
+ const cursor_oy = self.wlr_cursor.y - @intToFloat(f64, output_layout_box.y);
+ if ((self.seat.focused != .view or self.seat.focused.view != view) and
+ view.current.box.containsPoint(cursor_ox, cursor_oy))
+ {
+ self.seat.focusOutput(view.output);
+ self.seat.focus(view);
+ self.last_focus_follows_cursor_target = view;
+ server.root.startTransaction();
+ }
+ },
+ .layer_surface, .lock_surface => {},
+ .xwayland_override_redirect => assert(build_options.xwayland),
}
+ } else {
+ // The cursor is not above any view, so clear the last followed check
+ self.last_focus_follows_cursor_target = null;
}
}