From 3ad0ae6aca5d9bbf223c8d73b7f2996a6937658b Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Thu, 27 Oct 2022 09:08:36 -0700 Subject: [PATCH] feat(wm): introduce lazy monitor cache This commit introduces a lazy monitor cache that only gets populated with a monitor has been disconnected, before the monitor is removed from the state. If and when the same monitor is reconnected and identified by its size on the virtual screen, the cached monitor state will be used to repopulate layout options, avoiding a potentially expensive full configuration reload. re #275 --- komorebi/src/window_manager.rs | 48 ++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 56e8cdb5..d5c81a18 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::collections::VecDeque; use std::io::ErrorKind; use std::num::NonZeroUsize; @@ -54,6 +55,7 @@ use crate::WORKSPACE_RULES; #[derive(Debug)] pub struct WindowManager { pub monitors: Ring, + pub monitor_cache: HashMap, pub incoming_events: Arc>>, pub command_listener: UnixListener, pub is_paused: bool, @@ -166,6 +168,7 @@ impl WindowManager { Ok(Self { monitors: Ring::default(), + monitor_cache: HashMap::new(), incoming_events: incoming, command_listener: listener, is_paused: false, @@ -341,12 +344,15 @@ impl WindowManager { } let mut orphaned_containers = vec![]; + let mut invalid_indices = vec![]; - for invalid in self + for (i, invalid) in self .monitors() .iter() - .filter(|m| !valid_names.contains(m.name())) + .enumerate() + .filter(|(_, m)| !valid_names.contains(m.name())) { + invalid_indices.push(i); for workspace in invalid.workspaces() { for container in workspace.containers() { // Save the orphaned containers from an invalid monitor @@ -356,6 +362,12 @@ impl WindowManager { } } + for i in invalid_indices { + if let Some(monitor) = self.monitors().get(i) { + self.monitor_cache.insert(i, monitor.clone()); + } + } + // Remove any invalid monitors from our state self.monitors_mut() .retain(|m| valid_names.contains(m.name())); @@ -411,9 +423,41 @@ impl WindowManager { } } + #[allow(clippy::needless_collect)] + let old_sizes = self + .monitors() + .iter() + .map(Monitor::size) + .copied() + .collect::>(); + // Check for and add any new monitors that may have been plugged in WindowsApi::load_monitor_information(&mut self.monitors)?; + let mut check_cache = vec![]; + + for (i, m) in self.monitors().iter().enumerate() { + if !old_sizes.contains(m.size()) { + check_cache.push(i); + } + } + + for i in check_cache { + if let Some(cached) = self.monitor_cache.get(&i).cloned() { + if let Some(monitor) = self.monitors_mut().get_mut(i) { + for (w_idx, workspace) in monitor.workspaces_mut().iter_mut().enumerate() { + if let Some(cached_workspace) = cached.workspaces().get(w_idx) { + workspace.set_layout(cached_workspace.layout().clone()); + workspace.set_layout_rules(cached_workspace.layout_rules().clone()); + workspace.set_layout_flip(cached_workspace.layout_flip()); + workspace.set_workspace_padding(cached_workspace.workspace_padding()); + workspace.set_container_padding(cached_workspace.container_padding()); + } + } + } + } + } + let final_count = self.monitors().len(); if after_count != final_count { self.retile_all(true)?;