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

commita4c1eb3b90d04c36b00cd429fed600b438dc1be7
parenta021638c27
authorMarten Ringwelski <[email protected]>
date2020-12-07 13:51
focus-follow-cursor: Change output focus when needed

 doc/riverctl.1.scd |  7 +++++--
 river/Cursor.zig   | 24 +++++++-----------------
 river/Seat.zig     |  2 ++
 3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd
index 0fc240b..b1188fb 100644
--- a/doc/riverctl.1.scd
+++ b/doc/riverctl.1.scd
@@ -136,10 +136,13 @@ that tag 1 through 9 are visible.
 *focus-follows-cursor* *disabled*|*normal*|*strict*
 	When _disabled_ moving the cursor will not influence the focus. This is the default setting.
 	If set to _normal_ moving the cursor over a window will focus that window.
-	The focus still can be changed and moving the cursor within the (now unfocused) window will not change the focus to that window
-	but let the currently focused window in focus.
+	The focus still can be changed and moving the cursor within the (now unfocused) window will
+	not change the focus to that window but let the currently focused window in focus.
 	When set to _strict_ this is not the case. The focus will be updated on every cursor movement.
 
+	When the to be focused view is on another output than the currently focused output the view's
+	output is focused.
+
 *map* [-release] _mode_ _modifiers_ _key_ _command_
 	_mode_ is either "normal" (the default mode), "locked" (the mode entered when
 	an input inhibitor such as a lock screen is active) or a mode created with *declare-mode*.
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 17ebc42..ae31e51 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -584,25 +584,15 @@ fn passthrough(self: *Self, time: u32) void {
 
             c.wlr_seat_pointer_notify_enter(self.seat.wlr_seat, wlr_surface, sx, sy);
             c.wlr_seat_pointer_notify_motion(self.seat.wlr_seat, time, sx, sy);
-            if (View.fromWlrSurface(wlr_surface)) |view| {
-                // Change focus according to config
-                switch (config.focus_follows_cursor) {
-                    .disabled => {},
-                    .normal => {
-                        // Only refocus when the cursor entered a new surface
-                        if (focus_change) {
-                            self.seat.focus(view);
-                            root.startTransaction();
-                        }
-                    },
-                    .strict => {
-                        self.seat.focus(view);
-                        root.startTransaction();
-                    },
+
+            const follow_mode = config.focus_follows_cursor;
+            if (follow_mode == .strict or (follow_mode == .normal and focus_change)) {
+                if (View.fromWlrSurface(wlr_surface)) |view| {
+                    self.seat.focus(view);
+                    self.seat.focusOutput(view.output);
+                    root.startTransaction();
                 }
             }
-
-            return;
         }
     } else {
         // There is either no surface under the cursor or input is disallowed
diff --git a/river/Seat.zig b/river/Seat.zig
index eaed5fc..d2184d9 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -242,6 +242,8 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
 
 /// Focus the given output, notifying any listening clients of the change.
 pub fn focusOutput(self: *Self, output: *Output) void {
+    if (self.focused_output == output) return;
+
     const root = &self.input_manager.server.root;
 
     var it = self.status_trackers.first;