gardesk/tarmac / 92d950c

Browse files

Stabilize mouse follow after external stack focus

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
92d950c7b5008fac53e3b0bb40b5bdb9470d21bb
Parents
540929d
Tree
b6d7007

1 changed file

StatusFile+-
M tarmac/src/core/state.rs 60 1
tarmac/src/core/state.rsmodified
@@ -871,6 +871,25 @@ impl WmState {
871871
         }
872872
     }
873873
 
874
+    fn sync_mouse_after_focus(&mut self, ws_idx: usize, id: WindowId) {
875
+        self.ffm_last_window = Some(id);
876
+        if !self.mouse_follows_focus {
877
+            return;
878
+        }
879
+
880
+        let rect = self
881
+            .monitor_showing_workspace(ws_idx)
882
+            .map_or_else(|| self.focused_rect(), |mi| self.monitor_rect(mi));
883
+        let geoms = self.workspace_focus_geometries(ws_idx, rect);
884
+        if let Some((_, target_rect)) = geoms.iter().find(|(wid, _)| *wid == id) {
885
+            warp_mouse_to_center(target_rect);
886
+        } else {
887
+            warp_mouse_to_center(&rect);
888
+        }
889
+        self.ffm_cooldown_until =
890
+            Some(std::time::Instant::now() + std::time::Duration::from_millis(200));
891
+    }
892
+
874893
     fn is_external_focus_candidate(&self, id: WindowId) -> bool {
875894
         self.registry
876895
             .get(id)
@@ -930,7 +949,7 @@ impl WmState {
930949
                 self.dismiss_special_on_monitor(mi);
931950
             }
932951
             self.focused_monitor = mi;
933
-            self.ffm_last_window = None;
952
+            self.sync_mouse_after_focus(ws_idx, id);
934953
             return;
935954
         }
936955
 
@@ -956,6 +975,7 @@ impl WmState {
956975
                         self.dismiss_special_on_monitor(self.focused_monitor);
957976
                     }
958977
                     self.switch_workspace(&target);
978
+                    self.sync_mouse_after_focus(ws_idx, id);
959979
                 }
960980
             }
961981
         }
@@ -3433,6 +3453,45 @@ mod tests {
34333453
         );
34343454
     }
34353455
 
3456
+    #[test]
3457
+    fn external_focus_arms_mouse_follow_for_promoted_stack_window() {
3458
+        let mut state = WmState::new();
3459
+        state.monitors = vec![Monitor {
3460
+            id: 42,
3461
+            frame: Rect::new(0.0, 0.0, 1920.0, 1080.0),
3462
+            usable_frame: Rect::new(0.0, 33.0, 1920.0, 1047.0),
3463
+            is_primary: true,
3464
+            active_workspace: 0,
3465
+        }];
3466
+        state.sync_workspace_visibility();
3467
+        let screen = state.monitors[0].usable_frame;
3468
+
3469
+        state.registry.add(tracked_window(50, 11, "Firefox"));
3470
+        state.registry.add(tracked_window(51, 11, "Messages"));
3471
+        state
3472
+            .workspaces
3473
+            .get_or_create_target(&WorkspaceTarget::Numbered(2));
3474
+
3475
+        {
3476
+            let ws = state.workspaces.get_mut(1);
3477
+            ws.tree.insert_with_rect(50, None, screen);
3478
+            ws.tree.insert_with_rect(51, Some(50), screen);
3479
+            assert!(ws.tree.make_stack_for_window(51));
3480
+            ws.tree.set_stack_active(50);
3481
+            ws.record_focus(50);
3482
+        }
3483
+
3484
+        state.adopt_external_app_focus(11, Some(51));
3485
+
3486
+        assert_eq!(state.active_workspace().focused, Some(51));
3487
+        assert_eq!(state.ffm_last_window, Some(51));
3488
+        assert!(state.ffm_cooldown_until.is_some());
3489
+        assert_eq!(
3490
+            state.active_workspace().tree.stack_info(51),
3491
+            Some((vec![50, 51], 1))
3492
+        );
3493
+    }
3494
+
34363495
     #[test]
34373496
     fn external_app_focus_dismisses_overlay_before_switching() {
34383497
         let mut state = WmState::new();