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