1use std::collections::hash_map::Entry;
10use std::collections::HashMap;
11
12use crate::{Event, KeyboardLayouts, Window, Workspace};
13
14pub trait EventStreamStatePart {
16 fn replicate(&self) -> Vec<Event>;
18
19 fn apply(&mut self, event: Event) -> Option<Event>;
24}
25
26#[derive(Debug, Default)]
34pub struct EventStreamState {
35 pub workspaces: WorkspacesState,
37
38 pub windows: WindowsState,
40
41 pub keyboard_layouts: KeyboardLayoutsState,
43
44 pub overview: OverviewState,
46
47 pub config: ConfigState,
49}
50
51#[derive(Debug, Default)]
53pub struct WorkspacesState {
54 pub workspaces: HashMap<u64, Workspace>,
56}
57
58#[derive(Debug, Default)]
60pub struct WindowsState {
61 pub windows: HashMap<u64, Window>,
63}
64
65#[derive(Debug, Default)]
67pub struct KeyboardLayoutsState {
68 pub keyboard_layouts: Option<KeyboardLayouts>,
70}
71
72#[derive(Debug, Default)]
74pub struct OverviewState {
75 pub is_open: bool,
77}
78
79#[derive(Debug, Default)]
81pub struct ConfigState {
82 pub failed: bool,
84}
85
86impl EventStreamStatePart for EventStreamState {
87 fn replicate(&self) -> Vec<Event> {
88 let mut events = Vec::new();
89 events.extend(self.workspaces.replicate());
90 events.extend(self.windows.replicate());
91 events.extend(self.keyboard_layouts.replicate());
92 events.extend(self.overview.replicate());
93 events.extend(self.config.replicate());
94 events
95 }
96
97 fn apply(&mut self, event: Event) -> Option<Event> {
98 let event = self.workspaces.apply(event)?;
99 let event = self.windows.apply(event)?;
100 let event = self.keyboard_layouts.apply(event)?;
101 let event = self.overview.apply(event)?;
102 let event = self.config.apply(event)?;
103 Some(event)
104 }
105}
106
107impl EventStreamStatePart for WorkspacesState {
108 fn replicate(&self) -> Vec<Event> {
109 let workspaces = self.workspaces.values().cloned().collect();
110 vec![Event::WorkspacesChanged { workspaces }]
111 }
112
113 fn apply(&mut self, event: Event) -> Option<Event> {
114 match event {
115 Event::WorkspacesChanged { workspaces } => {
116 self.workspaces = workspaces.into_iter().map(|ws| (ws.id, ws)).collect();
117 }
118 Event::WorkspaceUrgencyChanged { id, urgent } => {
119 for ws in self.workspaces.values_mut() {
120 if ws.id == id {
121 ws.is_urgent = urgent;
122 }
123 }
124 }
125 Event::WorkspaceActivated { id, focused } => {
126 let ws = self.workspaces.get(&id);
127 let ws = ws.expect("activated workspace was missing from the map");
128 let output = ws.output.clone();
129
130 for ws in self.workspaces.values_mut() {
131 let got_activated = ws.id == id;
132 if ws.output == output {
133 ws.is_active = got_activated;
134 }
135
136 if focused {
137 ws.is_focused = got_activated;
138 }
139 }
140 }
141 Event::WorkspaceActiveWindowChanged {
142 workspace_id,
143 active_window_id,
144 } => {
145 let ws = self.workspaces.get_mut(&workspace_id);
146 let ws = ws.expect("changed workspace was missing from the map");
147 ws.active_window_id = active_window_id;
148 }
149 event => return Some(event),
150 }
151 None
152 }
153}
154
155impl EventStreamStatePart for WindowsState {
156 fn replicate(&self) -> Vec<Event> {
157 let windows = self.windows.values().cloned().collect();
158 vec![Event::WindowsChanged { windows }]
159 }
160
161 fn apply(&mut self, event: Event) -> Option<Event> {
162 match event {
163 Event::WindowsChanged { windows } => {
164 self.windows = windows.into_iter().map(|win| (win.id, win)).collect();
165 }
166 Event::WindowOpenedOrChanged { window } => {
167 let (id, is_focused) = match self.windows.entry(window.id) {
168 Entry::Occupied(mut entry) => {
169 let entry = entry.get_mut();
170 *entry = window;
171 (entry.id, entry.is_focused)
172 }
173 Entry::Vacant(entry) => {
174 let entry = entry.insert(window);
175 (entry.id, entry.is_focused)
176 }
177 };
178
179 if is_focused {
180 for win in self.windows.values_mut() {
181 if win.id != id {
182 win.is_focused = false;
183 }
184 }
185 }
186 }
187 Event::WindowClosed { id } => {
188 let win = self.windows.remove(&id);
189 win.expect("closed window was missing from the map");
190 }
191 Event::WindowFocusChanged { id } => {
192 for win in self.windows.values_mut() {
193 win.is_focused = Some(win.id) == id;
194 }
195 }
196 Event::WindowFocusTimestampChanged {
197 id,
198 focus_timestamp,
199 } => {
200 for win in self.windows.values_mut() {
201 if win.id == id {
202 win.focus_timestamp = focus_timestamp;
203 break;
204 }
205 }
206 }
207 Event::WindowUrgencyChanged { id, urgent } => {
208 for win in self.windows.values_mut() {
209 if win.id == id {
210 win.is_urgent = urgent;
211 break;
212 }
213 }
214 }
215 Event::WindowLayoutsChanged { changes } => {
216 for (id, update) in changes {
217 let win = self.windows.get_mut(&id);
218 let win = win.expect("changed window was missing from the map");
219 win.layout = update;
220 }
221 }
222 event => return Some(event),
223 }
224 None
225 }
226}
227
228impl EventStreamStatePart for KeyboardLayoutsState {
229 fn replicate(&self) -> Vec<Event> {
230 if let Some(keyboard_layouts) = self.keyboard_layouts.clone() {
231 vec![Event::KeyboardLayoutsChanged { keyboard_layouts }]
232 } else {
233 vec![]
234 }
235 }
236
237 fn apply(&mut self, event: Event) -> Option<Event> {
238 match event {
239 Event::KeyboardLayoutsChanged { keyboard_layouts } => {
240 self.keyboard_layouts = Some(keyboard_layouts);
241 }
242 Event::KeyboardLayoutSwitched { idx } => {
243 let kb = self.keyboard_layouts.as_mut();
244 let kb = kb.expect("keyboard layouts must be set before a layout can be switched");
245 kb.current_idx = idx;
246 }
247 event => return Some(event),
248 }
249 None
250 }
251}
252
253impl EventStreamStatePart for OverviewState {
254 fn replicate(&self) -> Vec<Event> {
255 vec![Event::OverviewOpenedOrClosed {
256 is_open: self.is_open,
257 }]
258 }
259
260 fn apply(&mut self, event: Event) -> Option<Event> {
261 match event {
262 Event::OverviewOpenedOrClosed { is_open } => {
263 self.is_open = is_open;
264 }
265 event => return Some(event),
266 }
267 None
268 }
269}
270
271impl EventStreamStatePart for ConfigState {
272 fn replicate(&self) -> Vec<Event> {
273 vec![Event::ConfigLoaded {
274 failed: self.failed,
275 }]
276 }
277
278 fn apply(&mut self, event: Event) -> Option<Event> {
279 match event {
280 Event::ConfigLoaded { failed } => {
281 self.failed = failed;
282 }
283 event => return Some(event),
284 }
285 None
286 }
287}