fix(bar): pass reconnect event to bar

This commit changes the `rx_gui` from receiving just a notification from
komorebi to now receive a new type `KomorebiEvent` which can be either a
`KomorebiEvent::Notification(komorebi_client::Notification)` or a
`KomorebiEvent::Reconnect`.

The `Reconnect` is sent after losing connection with komorebi and then
reconnecting again.

Now on the bar `update` we check for this `rx_gui` if we get a
notification we pass that to the
`KomorebiNotificationState::handle_notification` function just like
before (except now it takes a notification directly instead of taking
the `rx_gui` and checking for some message on the channel).

If instead we get a `Reconnect` we send a `MonitorWorkAreaOffset` socket
message to komorebi to update the work area offset.
This commit is contained in:
alex-ds13
2025-01-22 22:51:14 +00:00
committed by LGUG2Z
parent 3e1fc6123a
commit d7fcbb7d00
3 changed files with 144 additions and 138 deletions

View File

@@ -13,6 +13,7 @@ use crate::render::RenderConfig;
use crate::render::RenderExt;
use crate::widget::BarWidget;
use crate::widget::WidgetConfig;
use crate::KomorebiEvent;
use crate::BAR_HEIGHT;
use crate::DEFAULT_PADDING;
use crate::MAX_LABEL_WIDTH;
@@ -20,6 +21,7 @@ use crate::MONITOR_LEFT;
use crate::MONITOR_RIGHT;
use crate::MONITOR_TOP;
use crossbeam_channel::Receiver;
use crossbeam_channel::TryRecvError;
use eframe::egui::Align;
use eframe::egui::Align2;
use eframe::egui::Area;
@@ -63,7 +65,7 @@ pub struct Komobar {
pub left_widgets: Vec<Box<dyn BarWidget>>,
pub center_widgets: Vec<Box<dyn BarWidget>>,
pub right_widgets: Vec<Box<dyn BarWidget>>,
pub rx_gui: Receiver<komorebi_client::Notification>,
pub rx_gui: Receiver<KomorebiEvent>,
pub rx_config: Receiver<KomobarConfig>,
pub bg_color: Rc<RefCell<Color32>>,
pub bg_color_with_alpha: Rc<RefCell<Color32>>,
@@ -504,7 +506,7 @@ impl Komobar {
pub fn new(
cc: &eframe::CreationContext<'_>,
rx_gui: Receiver<komorebi_client::Notification>,
rx_gui: Receiver<KomorebiEvent>,
rx_config: Receiver<KomobarConfig>,
config: Arc<KomobarConfig>,
) -> Self {
@@ -632,20 +634,51 @@ impl eframe::App for Komobar {
);
}
if let Some(komorebi_notification_state) = &self.komorebi_notification_state {
komorebi_notification_state
.borrow_mut()
.handle_notification(
ctx,
self.monitor_index,
self.rx_gui.clone(),
self.bg_color.clone(),
self.bg_color_with_alpha.clone(),
self.config.transparency_alpha,
self.config.grouping,
self.config.theme,
self.render_config.clone(),
);
match self.rx_gui.try_recv() {
Err(error) => match error {
TryRecvError::Empty => {}
TryRecvError::Disconnected => {
tracing::error!(
"failed to receive komorebi notification on gui thread: {error}"
);
}
},
Ok(KomorebiEvent::Notification(notification)) => {
if let Some(komorebi_notification_state) = &self.komorebi_notification_state {
komorebi_notification_state
.borrow_mut()
.handle_notification(
ctx,
self.monitor_index,
notification,
self.bg_color.clone(),
self.bg_color_with_alpha.clone(),
self.config.transparency_alpha,
self.config.grouping,
self.config.theme,
self.render_config.clone(),
);
}
}
Ok(KomorebiEvent::Reconnect) => {
if let Err(error) =
komorebi_client::send_message(&SocketMessage::MonitorWorkAreaOffset(
self.monitor_index,
self.work_area_offset,
))
{
tracing::error!(
"error applying work area offset to monitor '{}': {}",
self.monitor_index,
error,
);
} else {
tracing::info!(
"work area offset applied to monitor: {}",
self.monitor_index
);
}
}
}
if !self.applied_theme_on_first_frame {

View File

@@ -10,8 +10,6 @@ use crate::widget::BarWidget;
use crate::ICON_CACHE;
use crate::MAX_LABEL_WIDTH;
use crate::MONITOR_INDEX;
use crossbeam_channel::Receiver;
use crossbeam_channel::TryRecvError;
use eframe::egui::vec2;
use eframe::egui::Color32;
use eframe::egui::ColorImage;
@@ -496,7 +494,7 @@ impl KomorebiNotificationState {
&mut self,
ctx: &Context,
monitor_index: usize,
rx_gui: Receiver<komorebi_client::Notification>,
notification: komorebi_client::Notification,
bg_color: Rc<RefCell<Color32>>,
bg_color_with_alpha: Rc<RefCell<Color32>>,
transparency_alpha: Option<u8>,
@@ -504,119 +502,104 @@ impl KomorebiNotificationState {
default_theme: Option<KomobarTheme>,
render_config: Rc<RefCell<RenderConfig>>,
) {
match rx_gui.try_recv() {
Err(error) => match error {
TryRecvError::Empty => {}
TryRecvError::Disconnected => {
tracing::error!(
"failed to receive komorebi notification on gui thread: {error}"
);
}
},
Ok(notification) => {
match notification.event {
NotificationEvent::WindowManager(_) => {}
NotificationEvent::Socket(message) => match message {
SocketMessage::ReloadStaticConfiguration(path) => {
if let Ok(config) = komorebi_client::StaticConfig::read(&path) {
if let Some(theme) = config.theme {
apply_theme(
ctx,
KomobarTheme::from(theme),
bg_color.clone(),
bg_color_with_alpha.clone(),
transparency_alpha,
grouping,
render_config,
);
tracing::info!("applied theme from updated komorebi.json");
} else if let Some(default_theme) = default_theme {
apply_theme(
ctx,
default_theme,
bg_color.clone(),
bg_color_with_alpha.clone(),
transparency_alpha,
grouping,
render_config,
);
tracing::info!("removed theme from updated komorebi.json and applied default theme");
} else {
tracing::warn!("theme was removed from updated komorebi.json but there was no default theme to apply");
}
}
}
SocketMessage::Theme(theme) => {
match notification.event {
NotificationEvent::WindowManager(_) => {}
NotificationEvent::Socket(message) => match message {
SocketMessage::ReloadStaticConfiguration(path) => {
if let Ok(config) = komorebi_client::StaticConfig::read(&path) {
if let Some(theme) = config.theme {
apply_theme(
ctx,
KomobarTheme::from(theme),
bg_color,
bg_color.clone(),
bg_color_with_alpha.clone(),
transparency_alpha,
grouping,
render_config,
);
tracing::info!("applied theme from komorebi socket message");
tracing::info!("applied theme from updated komorebi.json");
} else if let Some(default_theme) = default_theme {
apply_theme(
ctx,
default_theme,
bg_color.clone(),
bg_color_with_alpha.clone(),
transparency_alpha,
grouping,
render_config,
);
tracing::info!("removed theme from updated komorebi.json and applied default theme");
} else {
tracing::warn!("theme was removed from updated komorebi.json but there was no default theme to apply");
}
_ => {}
},
}
self.monitor_index = monitor_index;
self.mouse_follows_focus = notification.state.mouse_follows_focus;
let monitor = &notification.state.monitors.elements()[monitor_index];
self.work_area_offset =
notification.state.monitors.elements()[monitor_index].work_area_offset();
let focused_workspace_idx = monitor.focused_workspace_idx();
let mut workspaces = vec![];
self.selected_workspace = monitor.workspaces()[focused_workspace_idx]
.name()
.to_owned()
.unwrap_or_else(|| format!("{}", focused_workspace_idx + 1));
for (i, ws) in monitor.workspaces().iter().enumerate() {
let should_show = if self.hide_empty_workspaces {
focused_workspace_idx == i || !ws.containers().is_empty()
} else {
true
};
if should_show {
workspaces.push((
ws.name().to_owned().unwrap_or_else(|| format!("{}", i + 1)),
ws.into(),
));
}
}
self.workspaces = workspaces;
if monitor.workspaces()[focused_workspace_idx]
.monocle_container()
.is_some()
{
self.layout = KomorebiLayout::Monocle;
} else if !*monitor.workspaces()[focused_workspace_idx].tile() {
self.layout = KomorebiLayout::Floating;
} else if notification.state.is_paused {
self.layout = KomorebiLayout::Paused;
} else {
self.layout = match monitor.workspaces()[focused_workspace_idx].layout() {
komorebi_client::Layout::Default(layout) => {
KomorebiLayout::Default(*layout)
}
komorebi_client::Layout::Custom(_) => KomorebiLayout::Custom,
};
SocketMessage::Theme(theme) => {
apply_theme(
ctx,
KomobarTheme::from(theme),
bg_color,
bg_color_with_alpha.clone(),
transparency_alpha,
grouping,
render_config,
);
tracing::info!("applied theme from komorebi socket message");
}
_ => {}
},
}
self.focused_container_information =
(&monitor.workspaces()[focused_workspace_idx]).into();
self.monitor_index = monitor_index;
self.mouse_follows_focus = notification.state.mouse_follows_focus;
let monitor = &notification.state.monitors.elements()[monitor_index];
self.work_area_offset =
notification.state.monitors.elements()[monitor_index].work_area_offset();
let focused_workspace_idx = monitor.focused_workspace_idx();
let mut workspaces = vec![];
self.selected_workspace = monitor.workspaces()[focused_workspace_idx]
.name()
.to_owned()
.unwrap_or_else(|| format!("{}", focused_workspace_idx + 1));
for (i, ws) in monitor.workspaces().iter().enumerate() {
let should_show = if self.hide_empty_workspaces {
focused_workspace_idx == i || !ws.containers().is_empty()
} else {
true
};
if should_show {
workspaces.push((
ws.name().to_owned().unwrap_or_else(|| format!("{}", i + 1)),
ws.into(),
));
}
}
self.workspaces = workspaces;
if monitor.workspaces()[focused_workspace_idx]
.monocle_container()
.is_some()
{
self.layout = KomorebiLayout::Monocle;
} else if !*monitor.workspaces()[focused_workspace_idx].tile() {
self.layout = KomorebiLayout::Floating;
} else if notification.state.is_paused {
self.layout = KomorebiLayout::Paused;
} else {
self.layout = match monitor.workspaces()[focused_workspace_idx].layout() {
komorebi_client::Layout::Default(layout) => KomorebiLayout::Default(*layout),
komorebi_client::Layout::Custom(_) => KomorebiLayout::Custom,
};
}
self.focused_container_information = (&monitor.workspaces()[focused_workspace_idx]).into();
}
}

View File

@@ -115,6 +115,11 @@ fn process_hwnd() -> Option<isize> {
}
}
pub enum KomorebiEvent {
Notification(komorebi_client::Notification),
Reconnect,
}
fn main() -> color_eyre::Result<()> {
unsafe { SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) }?;
@@ -333,8 +338,6 @@ fn main() -> color_eyre::Result<()> {
"komorebi-bar",
native_options,
Box::new(|cc| {
let config_cl = config_arc.clone();
let ctx_repainter = cc.egui_ctx.clone();
std::thread::spawn(move || loop {
std::thread::sleep(Duration::from_secs(1));
@@ -377,25 +380,12 @@ fn main() -> color_eyre::Result<()> {
tracing::info!("reconnected to komorebi");
let (monitor_index, work_area_offset) = match &config_cl.monitor {
MonitorConfigOrIndex::MonitorConfig(monitor_config) => {
(monitor_config.index, monitor_config.work_area_offset)
}
MonitorConfigOrIndex::Index(idx) => (*idx, None),
};
if let Some(rect) = &work_area_offset {
while komorebi_client::send_message(
&SocketMessage::MonitorWorkAreaOffset(
monitor_index,
*rect,
),
)
.is_err()
{
std::thread::sleep(Duration::from_secs(1));
}
if let Err(error) = tx_gui.send(KomorebiEvent::Reconnect) {
tracing::error!("could not send komorebi reconnect event to gui thread: {error}")
}
ctx_komorebi.request_repaint();
continue;
}
match String::from_utf8(buffer) {
@@ -406,7 +396,7 @@ fn main() -> color_eyre::Result<()> {
Ok(notification) => {
tracing::debug!("received notification from komorebi");
if let Err(error) = tx_gui.send(notification) {
if let Err(error) = tx_gui.send(KomorebiEvent::Notification(notification)) {
tracing::error!("could not send komorebi notification update to gui thread: {error}")
}