From 55a798bd8b44465a354c1bd7723d4ece855c362c Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Thu, 12 Sep 2024 16:48:29 +0300 Subject: Prevent unintended focus-follows-mouse during workspace switch --- src/layout/mod.rs | 29 +++++++++++++++++++++++++++++ src/niri.rs | 4 ++++ 2 files changed, 33 insertions(+) (limited to 'src') diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 5ab81f03..9d69e0ff 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1031,6 +1031,35 @@ impl Layout { 0. } + pub fn should_trigger_focus_follows_mouse_on(&self, window: &W::Id) -> bool { + // During an animation, it's easy to trigger focus-follows-mouse on the previous workspace, + // especially when clicking to switch workspace on a bar of some kind. This cancels the + // workspace switch, which is annoying and not intended. + // + // This function allows focus-follows-mouse to trigger only on the animation target + // workspace. + let MonitorSet::Normal { monitors, .. } = &self.monitor_set else { + return true; + }; + + let (mon, ws_idx) = monitors + .iter() + .find_map(|mon| { + mon.workspaces + .iter() + .position(|ws| ws.has_window(window)) + .map(|ws_idx| (mon, ws_idx)) + }) + .unwrap(); + + // During a gesture, focus-follows-mouse does not cause any unintended workspace switches. + if let Some(WorkspaceSwitch::Gesture(_)) = mon.workspace_switch { + return true; + } + + ws_idx == mon.active_workspace_idx + } + pub fn activate_window(&mut self, window: &W::Id) { let MonitorSet::Normal { monitors, diff --git a/src/niri.rs b/src/niri.rs index 7c87ecc5..9e432319 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -4570,6 +4570,10 @@ impl Niri { if let Some(window) = &new_focus.window { if current_focus.window.as_ref() != Some(window) { + if !self.layout.should_trigger_focus_follows_mouse_on(window) { + return; + } + if let Some(threshold) = ffm.max_scroll_amount { if self.layout.scroll_amount_to_activate(window) > threshold.0 { return; -- cgit