diff --git a/komorebi-bar/src/bar.rs b/komorebi-bar/src/bar.rs index 1fcb56bb..f07db84a 100644 --- a/komorebi-bar/src/bar.rs +++ b/komorebi-bar/src/bar.rs @@ -61,6 +61,7 @@ use std::sync::Arc; pub struct Komobar { pub hwnd: Option, pub monitor_index: usize, + pub disabled: bool, pub config: Arc, pub render_config: Rc>, pub komorebi_notification_state: Option>>, @@ -305,12 +306,22 @@ impl Komobar { self.center_widgets = center_widgets; self.right_widgets = right_widgets; - let (monitor_index, config_work_area_offset) = match &config.monitor { + let (usr_monitor_index, config_work_area_offset) = match &config.monitor { MonitorConfigOrIndex::MonitorConfig(monitor_config) => { (monitor_config.index, monitor_config.work_area_offset) } MonitorConfigOrIndex::Index(idx) => (*idx, None), }; + let monitor_index = if let Some(state) = &self.komorebi_notification_state { + state + .borrow() + .monitor_usr_idx_map + .get(&usr_monitor_index) + .map_or(usr_monitor_index, |i| *i) + } else { + usr_monitor_index + }; + self.monitor_index = monitor_index; if let (prev_rect, Some(new_rect)) = (&self.work_area_offset, &config_work_area_offset) { @@ -515,6 +526,7 @@ impl Komobar { let mut komobar = Self { hwnd: process_hwnd(), monitor_index: 0, + disabled: false, config: config.clone(), render_config: Rc::new(RefCell::new(RenderConfig::new())), komorebi_notification_state: None, @@ -652,6 +664,32 @@ impl eframe::App for Komobar { NotificationEvent::Monitor(MonitorNotification::DisplayConnectionChange) ) { let state = ¬ification.state; + let usr_monitor_index = match &self.config.monitor { + MonitorConfigOrIndex::MonitorConfig(monitor_config) => monitor_config.index, + MonitorConfigOrIndex::Index(idx) => *idx, + }; + let monitor_index = state + .monitor_usr_idx_map + .get(&usr_monitor_index) + .map_or(usr_monitor_index, |i| *i); + self.monitor_index = monitor_index; + + if self.monitor_index >= state.monitors.elements().len() { + // Monitor for this bar got disconnected lets disable the bar until it + // reconnects + self.disabled = true; + tracing::warn!( + "This bar's monitor got disconnected. The bar will be disabled until it reconnects..." + ); + return; + } else { + if self.disabled { + tracing::info!( + "This bar's monitor reconnected. The bar will be enabled again!" + ); + } + self.disabled = false; + } // Store the monitor coordinates in case they've changed MONITOR_RIGHT.store( @@ -674,6 +712,10 @@ impl eframe::App for Komobar { false }; + if self.disabled { + return; + } + if let Some(komorebi_notification_state) = &self.komorebi_notification_state { komorebi_notification_state .borrow_mut() @@ -719,6 +761,12 @@ impl eframe::App for Komobar { } } + if self.disabled { + // The check for disabled is performed above, if we get here and the bar is still + // disabled then we should return without drawing anything. + return; + } + if !self.applied_theme_on_first_frame { self.try_apply_theme(&self.config.clone(), ctx); self.applied_theme_on_first_frame = true; diff --git a/komorebi-bar/src/komorebi.rs b/komorebi-bar/src/komorebi.rs index 61878fef..34c3bbe8 100644 --- a/komorebi-bar/src/komorebi.rs +++ b/komorebi-bar/src/komorebi.rs @@ -38,6 +38,7 @@ use serde::Deserialize; use serde::Serialize; use std::cell::RefCell; use std::collections::BTreeMap; +use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; use std::sync::atomic::Ordering; @@ -121,6 +122,7 @@ impl From<&KomorebiConfig> for Komorebi { focused_container_information: KomorebiNotificationStateContainerInformation::EMPTY, stack_accent: None, monitor_index: MONITOR_INDEX.load(Ordering::SeqCst), + monitor_usr_idx_map: HashMap::new(), })), workspaces: value.workspaces, layout: value.layout.clone(), @@ -483,6 +485,7 @@ pub struct KomorebiNotificationState { pub work_area_offset: Option, pub stack_accent: Option, pub monitor_index: usize, + pub monitor_usr_idx_map: HashMap, } impl KomorebiNotificationState { @@ -553,6 +556,13 @@ impl KomorebiNotificationState { } self.monitor_index = monitor_index; + self.monitor_usr_idx_map = notification.state.monitor_usr_idx_map.clone(); + + if monitor_index >= notification.state.monitors.elements().len() { + // The bar's monitor is diconnected, so the bar is disabled no need to check anything + // any further otherwise we'll get `OutOfBounds` panics. + return; + } self.mouse_follows_focus = notification.state.mouse_follows_focus; diff --git a/komorebi-bar/src/main.rs b/komorebi-bar/src/main.rs index b60bf449..d12d00d9 100644 --- a/komorebi-bar/src/main.rs +++ b/komorebi-bar/src/main.rs @@ -238,12 +238,16 @@ fn main() -> color_eyre::Result<()> { &SocketMessage::State, )?)?; - let (monitor_index, work_area_offset) = match &config.monitor { + let (usr_monitor_index, work_area_offset) = match &config.monitor { MonitorConfigOrIndex::MonitorConfig(monitor_config) => { (monitor_config.index, monitor_config.work_area_offset) } MonitorConfigOrIndex::Index(idx) => (*idx, None), }; + let monitor_index = state + .monitor_usr_idx_map + .get(&usr_monitor_index) + .map_or(usr_monitor_index, |i| *i); MONITOR_RIGHT.store( state.monitors.elements()[monitor_index].size().right,