Skip to content

Commit

Permalink
feat(wm): introduce lazy monitor cache
Browse files Browse the repository at this point in the history
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
  • Loading branch information
LGUG2Z committed Oct 31, 2022
1 parent 2575ca2 commit 3ad0ae6
Showing 1 changed file with 46 additions and 2 deletions.
48 changes: 46 additions & 2 deletions 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;
Expand Down Expand Up @@ -54,6 +55,7 @@ use crate::WORKSPACE_RULES;
#[derive(Debug)]
pub struct WindowManager {
pub monitors: Ring<Monitor>,
pub monitor_cache: HashMap<usize, Monitor>,
pub incoming_events: Arc<Mutex<Receiver<WindowManagerEvent>>>,
pub command_listener: UnixListener,
pub is_paused: bool,
Expand Down Expand Up @@ -166,6 +168,7 @@ impl WindowManager {

Ok(Self {
monitors: Ring::default(),
monitor_cache: HashMap::new(),
incoming_events: incoming,
command_listener: listener,
is_paused: false,
Expand Down Expand Up @@ -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
Expand All @@ -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()));
Expand Down Expand Up @@ -411,9 +423,41 @@ impl WindowManager {
}
}

#[allow(clippy::needless_collect)]
let old_sizes = self
.monitors()
.iter()
.map(Monitor::size)
.copied()
.collect::<Vec<_>>();

// 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)?;
Expand Down

0 comments on commit 3ad0ae6

Please sign in to comment.