1 use crate::config::Config;
2 use crate::{models::TagId, models::WindowHandle, Window, Workspace};
3 
4 use serde::{Deserialize, Serialize};
5 use std::collections::{HashMap, VecDeque};
6 
7 use super::MaybeWindowHandle;
8 
9 #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
10 pub enum FocusBehaviour {
11     Sloppy,
12     ClickTo,
13     Driven,
14 }
15 
16 impl Default for FocusBehaviour {
default() -> Self17     fn default() -> Self {
18         Self::Sloppy
19     }
20 }
21 
22 #[derive(Serialize, Deserialize, Debug, Clone)]
23 pub struct FocusManager {
24     pub behaviour: FocusBehaviour,
25     pub focus_new_windows: bool,
26     pub workspace_history: VecDeque<usize>,
27     pub window_history: VecDeque<MaybeWindowHandle>,
28     pub tag_history: VecDeque<TagId>,
29     pub tags_last_window: HashMap<TagId, WindowHandle>,
30 }
31 
32 impl FocusManager {
new(config: &impl Config) -> Self33     pub fn new(config: &impl Config) -> Self {
34         Self {
35             behaviour: config.focus_behaviour(),
36             focus_new_windows: config.focus_new_windows(),
37             workspace_history: Default::default(),
38             window_history: Default::default(),
39             tag_history: Default::default(),
40             tags_last_window: Default::default(),
41         }
42     }
43 
44     /// Return the currently focused workspace.
45     #[must_use]
workspace<'a, 'b>(&self, workspaces: &'a [Workspace]) -> Option<&'b Workspace> where 'a: 'b,46     pub fn workspace<'a, 'b>(&self, workspaces: &'a [Workspace]) -> Option<&'b Workspace>
47     where
48         'a: 'b,
49     {
50         let index = *self.workspace_history.get(0)?;
51         workspaces.get(index)
52     }
53 
54     /// Return the currently focused workspace.
workspace_mut<'a, 'b>( &self, workspaces: &'a mut Vec<Workspace>, ) -> Option<&'b mut Workspace> where 'a: 'b,55     pub fn workspace_mut<'a, 'b>(
56         &self,
57         workspaces: &'a mut Vec<Workspace>,
58     ) -> Option<&'b mut Workspace>
59     where
60         'a: 'b,
61     {
62         let index = *self.workspace_history.get(0)?;
63         workspaces.get_mut(index)
64     }
65 
66     /// Return the currently focused tag if the offset is 0.
67     /// Offset is used to reach further down the history.
tag(&self, offset: usize) -> Option<TagId>68     pub fn tag(&self, offset: usize) -> Option<TagId> {
69         self.tag_history.get(offset).copied()
70     }
71 
72     /// Return the currently focused window.
73     #[must_use]
window<'a, 'b>(&self, windows: &'a [Window]) -> Option<&'b Window> where 'a: 'b,74     pub fn window<'a, 'b>(&self, windows: &'a [Window]) -> Option<&'b Window>
75     where
76         'a: 'b,
77     {
78         let handle = *self.window_history.get(0)?;
79         if let Some(handle) = handle {
80             return windows.iter().find(|w| w.handle == handle);
81         }
82         None
83     }
84 
85     /// Return the currently focused window.
window_mut<'a, 'b>(&self, windows: &'a mut Vec<Window>) -> Option<&'b mut Window> where 'a: 'b,86     pub fn window_mut<'a, 'b>(&self, windows: &'a mut Vec<Window>) -> Option<&'b mut Window>
87     where
88         'a: 'b,
89     {
90         let handle = *self.window_history.get(0)?;
91         if let Some(handle) = handle {
92             return windows.iter_mut().find(|w| w.handle == handle);
93         }
94         None
95     }
96 }
97