Skip to content

Commit

Permalink
fix(bar): handle monitor disconnect/reconnect
Browse files Browse the repository at this point in the history
This commit makes so a bar can be disabled when it's monitor is
disconnected and re-enabled when said monitor reconnects.
This commit also uses the new `monitor_usr_idx_map` to properly map the
monitor index given by the users on config to the actual monitor index
on the `WindowManager`, since in case some middle monitor gets
disconnected the index of the monitors to the "right" of that one will
be lowered by 1.
This should allow for cases with monitor A, B and C, if monitor B
disconnects, its bar will be disabled and monitor C will properly change
its monitor index internally to 1 so it still gets the infos from
monitor C (which now will have index 1 on the `WindowManager`).
  • Loading branch information
alex-ds13 committed Jan 29, 2025
1 parent 941f3db commit 82a4590
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 2 deletions.
50 changes: 49 additions & 1 deletion komorebi-bar/src/bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use std::sync::Arc;
pub struct Komobar {
pub hwnd: Option<isize>,
pub monitor_index: usize,
pub disabled: bool,
pub config: Arc<KomobarConfig>,
pub render_config: Rc<RefCell<RenderConfig>>,
pub komorebi_notification_state: Option<Rc<RefCell<KomorebiNotificationState>>>,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -651,6 +663,32 @@ impl eframe::App for Komobar {
NotificationEvent::Monitor(MonitorNotification::DisplayConnectionChange)
) {
let state = &notification.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(
Expand All @@ -673,6 +711,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()
Expand Down Expand Up @@ -718,6 +760,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;
Expand Down
10 changes: 10 additions & 0 deletions komorebi-bar/src/komorebi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -483,6 +485,7 @@ pub struct KomorebiNotificationState {
pub work_area_offset: Option<Rect>,
pub stack_accent: Option<Color32>,
pub monitor_index: usize,
pub monitor_usr_idx_map: HashMap<usize, usize>,
}

impl KomorebiNotificationState {
Expand Down Expand Up @@ -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;

Expand Down
6 changes: 5 additions & 1 deletion komorebi-bar/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,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,
Expand Down

0 comments on commit 82a4590

Please sign in to comment.