From 69c54fb44784b58cc66000b85a4736c6c7233ca2 Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:39:20 +0000 Subject: [PATCH] fix(bar): simplify config for bar # This is a combination of 8 commits. # This is the 1st commit message: fix(bar): add simplified config for bar This commit creates a few new config options for the bar that should make it a lot simpler for new users to configure the bar. - Remove the need for `position`: if a position is given the bar will still use it with priority over the new config. Instead of position you can now use the following: - `height`: defines the height of the bar (50 by default) - `horizontal_margin`: defines the left and right offset of the bar, it is the same as setting a `position.start.x` and then remove the same amount on `position.end.x`. - `vertical_margin`: defines the top and bottom offset of the bar, it is the same as setting a `position.start.y` and then add a correct amount on the `work_area_offset`. - Remove the need for `frame`: some new configs were added that take priority over the old `frame`. These are: - `horizontal_padding`: defines the left and right padding of the bar. Similar to `frame.inner_margin.x`. - `vertical_padding`: defines the top and bottom padding of the bar. Similar to `frame.inner_margin.y`. - Remove the need for `work_area_offset`: if a `work_area_offset` is given then it will take priority, if not, then it will calculate the necessary `work_area_offset` using the bar height, position and horizontal and vertical margins. # This is the commit message n.2: feat(bar): set margin/padding as one or two values This commit changes the `horizontal_margin`, `vertical_margin`, `horizontal_padding` and `vertical_padding` to now take a `SpacingAxisConfig` which can take a single value or two values. For example, you can set the vertical margin of the bar to add some spacing above and below like this: ```json "vertical_margin": 10 ``` Which will add a spacing of 10 above and below the bar. Or you can set it like this: ```json "vertical_margin": [10, 0] ``` Which will add a spacing of 10 above the bar but no spacing below. You can even set something like this: ```json "vertical_margin": [0, -10] ``` To make no spacing above and a negative spacing below to make it so the tiled windows show right next to the bar. This will basically be removing the workspace and container padding between the tiled windows and the bar. # This is the commit message n.3: fix(bar): use a right_to_left layout on right side This commit changes the right area with the right widgets to have a different layout that is still right_to_left as previously but behaves much better in regards to its height. # This is the commit message n.4: fix(bar): use default bar height When there is no `work_area_offset` and no `height` on the config it was using the `BAR_HEIGHT` as default, however the automatica work_area_offset calculation wasn't being done properly. Now it is! # This is the commit message n.5: feat(bar): monitor can be `MonitorConfig` or index This commit allows the `"monitor":` config to take a `MonitorConfig` object like it used to or simply a number (index). # This is the commit message n.6: docs(schema): update all json schemas # This is the commit message n.7: fix(bar): update example bar config # This is the commit message n.8: fix(bar): correct work_area_offset on secondary monitors --- docs/komorebi.bar.example.json | 10 +- komorebi-bar/src/bar.rs | 275 ++++++++++++++++++++++++++++----- komorebi-bar/src/config.rs | 37 ++++- komorebi-bar/src/main.rs | 53 ++++--- komorebi-bar/src/render.rs | 8 +- schema.bar.json | 184 ++++++++++++++++++---- 6 files changed, 462 insertions(+), 105 deletions(-) diff --git a/docs/komorebi.bar.example.json b/docs/komorebi.bar.example.json index 292f7df4a..9ea414796 100644 --- a/docs/komorebi.bar.example.json +++ b/docs/komorebi.bar.example.json @@ -1,14 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.33/schema.bar.json", - "monitor": { - "index": 0, - "work_area_offset": { - "left": 0, - "top": 40, - "right": 0, - "bottom": 40 - } - }, + "monitor": 0, "font_family": "JetBrains Mono", "theme": { "palette": "Base16", diff --git a/komorebi-bar/src/bar.rs b/komorebi-bar/src/bar.rs index 08b9fc214..62241f1a6 100644 --- a/komorebi-bar/src/bar.rs +++ b/komorebi-bar/src/bar.rs @@ -1,7 +1,9 @@ use crate::config::KomobarConfig; use crate::config::KomobarTheme; +use crate::config::MonitorConfigOrIndex; use crate::config::Position; use crate::config::PositionConfig; +use crate::config::SpacingAxisConfig; use crate::komorebi::Komorebi; use crate::komorebi::KomorebiNotificationState; use crate::process_hwnd; @@ -34,6 +36,7 @@ use eframe::egui::Margin; use eframe::egui::Rgba; use eframe::egui::Style; use eframe::egui::TextStyle; +use eframe::egui::Vec2; use eframe::egui::Visuals; use font_loader::system_fonts; use font_loader::system_fonts::FontPropertyBuilder; @@ -52,6 +55,7 @@ use std::sync::Arc; pub struct Komobar { pub hwnd: Option, + pub monitor_index: usize, pub config: Arc, pub render_config: Rc>, pub komorebi_notification_state: Option>>, @@ -64,6 +68,7 @@ pub struct Komobar { pub bg_color_with_alpha: Rc>, pub scale_factor: f32, pub size_rect: komorebi_client::Rect, + pub work_area_offset: komorebi_client::Rect, applied_theme_on_first_frame: bool, } @@ -199,7 +204,7 @@ impl Komobar { // Update the `size_rect` so that the bar position can be changed on the EGUI update // function - self.update_size_rect(config.position.clone()); + self.update_size_rect(config); self.try_apply_theme(config, ctx); @@ -295,23 +300,65 @@ impl Komobar { self.center_widgets = center_widgets; self.right_widgets = right_widgets; - if let (Some(prev_rect), Some(new_rect)) = ( - &self.config.monitor.work_area_offset, - &config.monitor.work_area_offset, - ) { + let (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), + }; + self.monitor_index = monitor_index; + + if let (prev_rect, Some(new_rect)) = (&self.work_area_offset, &config_work_area_offset) { if new_rect != prev_rect { + self.work_area_offset = *new_rect; + if let Err(error) = komorebi_client::send_message( + &SocketMessage::MonitorWorkAreaOffset(self.monitor_index, *new_rect), + ) { + 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 + ); + } + } + } else if let Some(height) = config.height.or(Some(BAR_HEIGHT)) { + // We only add the `bottom_margin` to the work_area_offset since the top margin is + // already considered on the `size_rect.top` + let new_rect = komorebi_client::Rect { + left: 0, + top: (height as i32) + + (self.size_rect.top - MONITOR_TOP.load(Ordering::SeqCst)) + + config.vertical_margin.as_ref().map_or(0, |v| match v { + SpacingAxisConfig::Symmetric(m) => *m as i32, + SpacingAxisConfig::Detailed((_, bottom)) => *bottom as i32, + }), + right: 0, + bottom: (height as i32) + + (self.size_rect.top - MONITOR_TOP.load(Ordering::SeqCst)) + + config.vertical_margin.as_ref().map_or(0, |v| match v { + SpacingAxisConfig::Symmetric(m) => *m as i32, + SpacingAxisConfig::Detailed((_, bottom)) => *bottom as i32, + }), + }; + if new_rect != self.work_area_offset { + self.work_area_offset = new_rect; if let Err(error) = komorebi_client::send_message( - &SocketMessage::MonitorWorkAreaOffset(config.monitor.index, *new_rect), + &SocketMessage::MonitorWorkAreaOffset(self.monitor_index, new_rect), ) { tracing::error!( "error applying work area offset to monitor '{}': {}", - config.monitor.index, + self.monitor_index, error, ); } else { tracing::info!( "work area offset applied to monitor: {}", - config.monitor.index + self.monitor_index ); } } @@ -325,8 +372,8 @@ impl Komobar { } /// Updates the `size_rect` field. Returns a bool indicating if the field was changed or not - fn update_size_rect(&mut self, position: Option) { - let position = position.unwrap_or(PositionConfig { + fn update_size_rect(&mut self, config: &KomobarConfig) { + let position = config.position.clone().unwrap_or(PositionConfig { start: Some(Position { x: MONITOR_LEFT.load(Ordering::SeqCst) as f32, y: MONITOR_TOP.load(Ordering::SeqCst) as f32, @@ -337,16 +384,40 @@ impl Komobar { }), }); - let start = position.start.unwrap_or(Position { + let mut start = position.start.unwrap_or(Position { x: MONITOR_LEFT.load(Ordering::SeqCst) as f32, y: MONITOR_TOP.load(Ordering::SeqCst) as f32, }); - let end = position.end.unwrap_or(Position { + let mut end = position.end.unwrap_or(Position { x: MONITOR_RIGHT.load(Ordering::SeqCst) as f32, y: BAR_HEIGHT, }); + if let Some(height) = config.height { + end.y = height; + } + + if let Some(vertical_margin) = &config.vertical_margin { + match vertical_margin { + SpacingAxisConfig::Symmetric(m) => start.y += m, + SpacingAxisConfig::Detailed((top, _)) => start.y += top, + } + } + + if let Some(horizontal_margin) = &config.horizontal_margin { + match horizontal_margin { + SpacingAxisConfig::Symmetric(m) => { + start.x += m; + end.x -= m * 2.0; + } + SpacingAxisConfig::Detailed((left, right)) => { + start.x += left; + end.x -= left + right; + } + } + } + if end.y == 0.0 { tracing::warn!("position.end.y is set to 0.0 which will make your bar invisible on a config reload - this is usually set to 50.0 by default") } @@ -453,6 +524,7 @@ impl Komobar { ) -> Self { let mut komobar = Self { hwnd: process_hwnd(), + monitor_index: 0, config: config.clone(), render_config: Rc::new(RefCell::new(RenderConfig::new())), komorebi_notification_state: None, @@ -465,6 +537,7 @@ impl Komobar { bg_color_with_alpha: Rc::new(RefCell::new(Style::default().visuals.panel_fill)), scale_factor: cc.egui_ctx.native_pixels_per_point().unwrap_or(1.0), size_rect: komorebi_client::Rect::default(), + work_area_offset: komorebi_client::Rect::default(), applied_theme_on_first_frame: false, }; @@ -578,7 +651,7 @@ impl eframe::App for Komobar { .borrow_mut() .handle_notification( ctx, - self.config.monitor.index, + self.monitor_index, self.rx_gui.clone(), self.bg_color.clone(), self.bg_color_with_alpha.clone(), @@ -619,40 +692,120 @@ impl eframe::App for Komobar { } } - let frame = if let Some(frame) = &self.config.frame { - Frame::none() - .inner_margin(Margin::symmetric( - frame.inner_margin.x, - frame.inner_margin.y, - )) - .fill(*self.bg_color_with_alpha.borrow()) - } else { - Frame::none().fill(*self.bg_color_with_alpha.borrow()) + let frame = match ( + &self.config.horizontal_padding, + &self.config.vertical_padding, + ) { + (None, None) => { + if let Some(frame) = &self.config.frame { + Frame::none() + .inner_margin(Margin::symmetric( + frame.inner_margin.x, + frame.inner_margin.y, + )) + .fill(*self.bg_color_with_alpha.borrow()) + } else { + Frame::none() + .inner_margin(Margin::same(0.0)) + .fill(*self.bg_color_with_alpha.borrow()) + } + } + (None, Some(SpacingAxisConfig::Symmetric(vertical_padding))) => Frame::none() + .inner_margin(Margin::symmetric(0.0, *vertical_padding)) + .fill(*self.bg_color_with_alpha.borrow()), + (None, Some(SpacingAxisConfig::Detailed((top, bottom)))) => Frame::none() + .inner_margin(Margin { + left: 0.0, + right: 0.0, + top: *top, + bottom: *bottom, + }) + .fill(*self.bg_color_with_alpha.borrow()), + (Some(SpacingAxisConfig::Symmetric(horizontal_padding)), None) => Frame::none() + .inner_margin(Margin::symmetric(*horizontal_padding, 0.0)) + .fill(*self.bg_color_with_alpha.borrow()), + (Some(SpacingAxisConfig::Detailed((left, right))), None) => Frame::none() + .inner_margin(Margin { + left: *left, + right: *right, + top: 0.0, + bottom: 0.0, + }) + .fill(*self.bg_color_with_alpha.borrow()), + (Some(horizontal_padding), Some(vertical_padding)) => { + let (left, right) = match horizontal_padding { + SpacingAxisConfig::Symmetric(m) => (*m, *m), + SpacingAxisConfig::Detailed((l, r)) => (*l, *r), + }; + let (top, bottom) = match vertical_padding { + SpacingAxisConfig::Symmetric(m) => (*m, *m), + SpacingAxisConfig::Detailed((t, b)) => (*t, *b), + }; + Frame::none() + .inner_margin(Margin { + left, + right, + top, + bottom, + }) + .fill(*self.bg_color_with_alpha.borrow()) + } }; let mut render_config = self.render_config.borrow_mut(); let frame = render_config.change_frame_on_bar(frame, &ctx.style()); - CentralPanel::default().frame(frame).show(ctx, |_| { + CentralPanel::default().frame(frame).show(ctx, |ui| { // Apply grouping logic for the bar as a whole let area_frame = if let Some(frame) = &self.config.frame { - Frame::none().inner_margin(Margin::symmetric(0.0, frame.inner_margin.y)) + Frame::none() + .inner_margin(Margin::symmetric(0.0, frame.inner_margin.y)) + .outer_margin(Margin::same(0.0)) } else { Frame::none() + .inner_margin(Margin::same(0.0)) + .outer_margin(Margin::same(0.0)) }; + let available_height = ui.max_rect().max.y; + ctx.style_mut(|style| { + style.spacing.interact_size.y = available_height; + }); + if !self.left_widgets.is_empty() { // Left-aligned widgets layout Area::new(Id::new("left_panel")) .anchor(Align2::LEFT_CENTER, [0.0, 0.0]) // Align in the left center of the window .show(ctx, |ui| { let mut left_area_frame = area_frame; - if let Some(frame) = &self.config.frame { + if let Some(SpacingAxisConfig::Symmetric(h_padding)) = + self.config.horizontal_padding + { + left_area_frame.inner_margin.left = h_padding; + } else if let Some(SpacingAxisConfig::Detailed((left, _))) = + self.config.horizontal_padding + { + left_area_frame.inner_margin.left = left; + } else if let Some(frame) = &self.config.frame { left_area_frame.inner_margin.left = frame.inner_margin.x; } + if let Some(SpacingAxisConfig::Symmetric(y_padding)) = + self.config.vertical_padding + { + left_area_frame.inner_margin.top = y_padding; + left_area_frame.inner_margin.bottom = y_padding; + } else if let Some(SpacingAxisConfig::Detailed((t, b))) = + self.config.vertical_padding + { + left_area_frame.inner_margin.top = t; + left_area_frame.inner_margin.bottom = b; + } else if let Some(frame) = &self.config.frame { + left_area_frame.inner_margin.top = frame.inner_margin.y; + left_area_frame.inner_margin.bottom = frame.inner_margin.y; + } left_area_frame.show(ui, |ui| { - ui.with_layout(Layout::left_to_right(Align::Center), |ui| { + ui.horizontal(|ui| { let mut render_conf = render_config.clone(); render_conf.alignment = Some(Alignment::Left); @@ -672,20 +825,50 @@ impl eframe::App for Komobar { .anchor(Align2::RIGHT_CENTER, [0.0, 0.0]) // Align in the right center of the window .show(ctx, |ui| { let mut right_area_frame = area_frame; - if let Some(frame) = &self.config.frame { + if let Some(SpacingAxisConfig::Symmetric(h_padding)) = + self.config.horizontal_padding + { + right_area_frame.inner_margin.right = h_padding; + } else if let Some(SpacingAxisConfig::Detailed((_, right))) = + self.config.horizontal_padding + { + right_area_frame.inner_margin.right = right; + } else if let Some(frame) = &self.config.frame { right_area_frame.inner_margin.right = frame.inner_margin.x; } + if let Some(SpacingAxisConfig::Symmetric(y_padding)) = + self.config.vertical_padding + { + right_area_frame.inner_margin.top = y_padding; + right_area_frame.inner_margin.bottom = y_padding; + } else if let Some(SpacingAxisConfig::Detailed((t, b))) = + self.config.vertical_padding + { + right_area_frame.inner_margin.top = t; + right_area_frame.inner_margin.bottom = b; + } else if let Some(frame) = &self.config.frame { + right_area_frame.inner_margin.top = frame.inner_margin.y; + right_area_frame.inner_margin.bottom = frame.inner_margin.y; + } right_area_frame.show(ui, |ui| { - ui.with_layout(Layout::right_to_left(Align::Center), |ui| { - let mut render_conf = render_config.clone(); - render_conf.alignment = Some(Alignment::Right); - - render_config.apply_on_alignment(ui, |ui| { - for w in &mut self.right_widgets { - w.render(ctx, ui, &mut render_conf); - } - }); - }); + let initial_size = Vec2 { + x: ui.available_size_before_wrap().x, + y: ui.spacing().interact_size.y, + }; + ui.allocate_ui_with_layout( + initial_size, + Layout::right_to_left(Align::Center), + |ui| { + let mut render_conf = render_config.clone(); + render_conf.alignment = Some(Alignment::Right); + + render_config.apply_on_alignment(ui, |ui| { + for w in &mut self.right_widgets { + w.render(ctx, ui, &mut render_conf); + } + }); + }, + ); }); }); } @@ -695,9 +878,23 @@ impl eframe::App for Komobar { Area::new(Id::new("center_panel")) .anchor(Align2::CENTER_CENTER, [0.0, 0.0]) // Align in the center of the window .show(ctx, |ui| { - let center_area_frame = area_frame; + let mut center_area_frame = area_frame; + if let Some(SpacingAxisConfig::Symmetric(y_padding)) = + self.config.vertical_padding + { + center_area_frame.inner_margin.top = y_padding; + center_area_frame.inner_margin.bottom = y_padding; + } else if let Some(SpacingAxisConfig::Detailed((t, b))) = + self.config.vertical_padding + { + center_area_frame.inner_margin.top = t; + center_area_frame.inner_margin.bottom = b; + } else if let Some(frame) = &self.config.frame { + center_area_frame.inner_margin.top = frame.inner_margin.y; + center_area_frame.inner_margin.bottom = frame.inner_margin.y; + } center_area_frame.show(ui, |ui| { - ui.with_layout(Layout::left_to_right(Align::Center), |ui| { + ui.horizontal(|ui| { let mut render_conf = render_config.clone(); render_conf.alignment = Some(Alignment::Center); diff --git a/komorebi-bar/src/config.rs b/komorebi-bar/src/config.rs index 1f3ee36a9..071bad73a 100644 --- a/komorebi-bar/src/config.rs +++ b/komorebi-bar/src/config.rs @@ -14,13 +14,27 @@ use std::path::PathBuf; #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] /// The `komorebi.bar.json` configuration file reference for `v0.1.34` pub struct KomobarConfig { + /// Bar height (default: 50) + pub height: Option, + /// Bar horizontal padding. Use one value for symmetric padding or use `[left, right]` to + /// specify a different padding on each side (default: 10) + pub horizontal_padding: Option, + /// Bar vertical padding. Use one value for symmetric padding or use `[top, bottom]` to + /// specify a different padding on each side (default: 10) + pub vertical_padding: Option, + /// Bar horizontal margin. Use one value for symmetric margin or use `[left, right]` to + /// specify a different margin on each side (default: 0) + pub horizontal_margin: Option, + /// Bar vertical margin. Use one value for symmetric margin or use `[top, bottom]` to + /// specify a different margin on each side (default: 0) + pub vertical_margin: Option, /// Bar positioning options #[serde(alias = "viewport")] pub position: Option, /// Frame options (see: https://docs.rs/egui/latest/egui/containers/frame/struct.Frame.html) pub frame: Option, - /// Monitor options - pub monitor: MonitorConfig, + /// The monitor index or the full monitor options + pub monitor: MonitorConfigOrIndex, /// Font family pub font_family: Option, /// Font size (default: 12.5) @@ -90,6 +104,15 @@ pub struct FrameConfig { pub inner_margin: Position, } +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[serde(untagged)] +pub enum MonitorConfigOrIndex { + /// The monitor index where you want the bar to show + Index(usize), + /// The full monitor options with the index and an optional work_area_offset + MonitorConfig(MonitorConfig), +} + #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct MonitorConfig { /// Komorebi monitor index of the monitor on which to render the bar @@ -98,6 +121,16 @@ pub struct MonitorConfig { pub work_area_offset: Option, } +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[serde(untagged)] +pub enum SpacingAxisConfig { + /// A symmetric spacing on some axis (horizontal or vertical), with the same size on both sides + Symmetric(f32), + /// A detailed spacing on some axis (horizontal or vertical), with a size for each side. If an + /// horizontal spacing, then it will be (left, right), if vertical it will be (top, bottom) + Detailed((f32, f32)), +} + impl KomobarConfig { pub fn read(path: &PathBuf) -> color_eyre::Result { let content = std::fs::read_to_string(path)?; diff --git a/komorebi-bar/src/main.rs b/komorebi-bar/src/main.rs index f47018620..cc0590b31 100644 --- a/komorebi-bar/src/main.rs +++ b/komorebi-bar/src/main.rs @@ -21,6 +21,7 @@ use crate::config::KomobarConfig; use crate::config::Position; use crate::config::PositionConfig; use clap::Parser; +use config::MonitorConfigOrIndex; use eframe::egui::ViewportBuilder; use font_loader::system_fonts; use hotwatch::EventKind; @@ -230,32 +231,39 @@ fn main() -> color_eyre::Result<()> { &SocketMessage::State, )?)?; + let (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), + }; + MONITOR_RIGHT.store( - state.monitors.elements()[config.monitor.index].size().right, + state.monitors.elements()[monitor_index].size().right, Ordering::SeqCst, ); MONITOR_TOP.store( - state.monitors.elements()[config.monitor.index].size().top, + state.monitors.elements()[monitor_index].size().top, Ordering::SeqCst, ); - MONITOR_TOP.store( - state.monitors.elements()[config.monitor.index].size().left, + MONITOR_LEFT.store( + state.monitors.elements()[monitor_index].size().left, Ordering::SeqCst, ); - MONITOR_INDEX.store(config.monitor.index, Ordering::SeqCst); + MONITOR_INDEX.store(monitor_index, Ordering::SeqCst); match config.position { None => { config.position = Some(PositionConfig { start: Some(Position { - x: state.monitors.elements()[config.monitor.index].size().left as f32, - y: state.monitors.elements()[config.monitor.index].size().top as f32, + x: state.monitors.elements()[monitor_index].size().left as f32, + y: state.monitors.elements()[monitor_index].size().top as f32, }), end: Some(Position { - x: state.monitors.elements()[config.monitor.index].size().right as f32, + x: state.monitors.elements()[monitor_index].size().right as f32, y: 50.0, }), }) @@ -263,14 +271,14 @@ fn main() -> color_eyre::Result<()> { Some(ref mut position) => { if position.start.is_none() { position.start = Some(Position { - x: state.monitors.elements()[config.monitor.index].size().left as f32, - y: state.monitors.elements()[config.monitor.index].size().top as f32, + x: state.monitors.elements()[monitor_index].size().left as f32, + y: state.monitors.elements()[monitor_index].size().top as f32, }); } if position.end.is_none() { position.end = Some(Position { - x: state.monitors.elements()[config.monitor.index].size().right as f32, + x: state.monitors.elements()[monitor_index].size().right as f32, y: 50.0, }) } @@ -287,15 +295,9 @@ fn main() -> color_eyre::Result<()> { ..Default::default() }; - if let Some(rect) = &config.monitor.work_area_offset { - komorebi_client::send_message(&SocketMessage::MonitorWorkAreaOffset( - config.monitor.index, - *rect, - ))?; - tracing::info!( - "work area offset applied to monitor: {}", - config.monitor.index - ); + if let Some(rect) = &work_area_offset { + komorebi_client::send_message(&SocketMessage::MonitorWorkAreaOffset(monitor_index, *rect))?; + tracing::info!("work area offset applied to monitor: {}", monitor_index); } let (tx_gui, rx_gui) = crossbeam_channel::unbounded(); @@ -374,10 +376,17 @@ fn main() -> color_eyre::Result<()> { tracing::info!("reconnected to komorebi"); - if let Some(rect) = &config_cl.monitor.work_area_offset { + 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( - config_cl.monitor.index, + monitor_index, *rect, ), ) diff --git a/komorebi-bar/src/render.rs b/komorebi-bar/src/render.rs index d6edc81c5..87e447ed5 100644 --- a/komorebi-bar/src/render.rs +++ b/komorebi-bar/src/render.rs @@ -1,5 +1,6 @@ use crate::bar::Alignment; use crate::config::KomobarConfig; +use crate::config::MonitorConfigOrIndex; use eframe::egui::Color32; use eframe::egui::Context; use eframe::egui::FontId; @@ -81,8 +82,13 @@ impl RenderExt for &KomobarConfig { let mut icon_font_id = text_font_id.clone(); icon_font_id.size *= icon_scale.unwrap_or(1.4).clamp(1.0, 2.0); + let monitor_idx = match &self.monitor { + MonitorConfigOrIndex::MonitorConfig(monitor_config) => monitor_config.index, + MonitorConfigOrIndex::Index(idx) => *idx, + }; + RenderConfig { - monitor_idx: self.monitor.index, + monitor_idx, spacing: self.widget_spacing.unwrap_or(10.0), grouping: self.grouping.unwrap_or(Grouping::None), background_color, diff --git a/schema.bar.json b/schema.bar.json index 903ec2214..718029a9a 100644 --- a/schema.bar.json +++ b/schema.bar.json @@ -1214,6 +1214,63 @@ } ] }, + "height": { + "description": "Bar height (default: 50)", + "type": "number", + "format": "float" + }, + "horizontal_margin": { + "description": "Bar horizontal margin. Use one value for symmetric margin or use `[left, right]` to specify a different margin on each side (default: 0)", + "anyOf": [ + { + "description": "A symmetric spacing on some axis (horizontal or vertical), with the same size on both sides", + "type": "number", + "format": "float" + }, + { + "description": "A detailed spacing on some axis (horizontal or vertical), with a size for each side. If an horizontal spacing, then it will be (left, right), if vertical it will be (top, bottom)", + "type": "array", + "items": [ + { + "type": "number", + "format": "float" + }, + { + "type": "number", + "format": "float" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + }, + "horizontal_padding": { + "description": "Bar horizontal padding. Use one value for symmetric padding or use `[left, right]` to specify a different padding on each side (default: 10)", + "anyOf": [ + { + "description": "A symmetric spacing on some axis (horizontal or vertical), with the same size on both sides", + "type": "number", + "format": "float" + }, + { + "description": "A detailed spacing on some axis (horizontal or vertical), with a size for each side. If an horizontal spacing, then it will be (left, right), if vertical it will be (top, bottom)", + "type": "array", + "items": [ + { + "type": "number", + "format": "float" + }, + { + "type": "number", + "format": "float" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + }, "icon_scale": { "description": "Scale of the icons relative to the font_size [[1.0-2.0]]. (default: 1.4)", "type": "number", @@ -2090,51 +2147,62 @@ "format": "float" }, "monitor": { - "description": "Monitor options", - "type": "object", - "required": [ - "index" - ], - "properties": { - "index": { - "description": "Komorebi monitor index of the monitor on which to render the bar", + "description": "The monitor index or the full monitor options", + "anyOf": [ + { + "description": "The monitor index where you want the bar to show", "type": "integer", "format": "uint", "minimum": 0.0 }, - "work_area_offset": { - "description": "Automatically apply a work area offset for this monitor to accommodate the bar", + { + "description": "The full monitor options with the index and an optional work_area_offset", "type": "object", "required": [ - "bottom", - "left", - "right", - "top" + "index" ], "properties": { - "bottom": { - "description": "The bottom point in a Win32 Rect", - "type": "integer", - "format": "int32" - }, - "left": { - "description": "The left point in a Win32 Rect", + "index": { + "description": "Komorebi monitor index of the monitor on which to render the bar", "type": "integer", - "format": "int32" - }, - "right": { - "description": "The right point in a Win32 Rect", - "type": "integer", - "format": "int32" + "format": "uint", + "minimum": 0.0 }, - "top": { - "description": "The top point in a Win32 Rect", - "type": "integer", - "format": "int32" + "work_area_offset": { + "description": "Automatically apply a work area offset for this monitor to accommodate the bar", + "type": "object", + "required": [ + "bottom", + "left", + "right", + "top" + ], + "properties": { + "bottom": { + "description": "The bottom point in a Win32 Rect", + "type": "integer", + "format": "int32" + }, + "left": { + "description": "The left point in a Win32 Rect", + "type": "integer", + "format": "int32" + }, + "right": { + "description": "The right point in a Win32 Rect", + "type": "integer", + "format": "int32" + }, + "top": { + "description": "The top point in a Win32 Rect", + "type": "integer", + "format": "int32" + } + } } } } - } + ] }, "position": { "description": "Bar positioning options", @@ -3427,6 +3495,58 @@ "format": "uint8", "minimum": 0.0 }, + "vertical_margin": { + "description": "Bar vertical margin. Use one value for symmetric margin or use `[top, bottom]` to specify a different margin on each side (default: 0)", + "anyOf": [ + { + "description": "A symmetric spacing on some axis (horizontal or vertical), with the same size on both sides", + "type": "number", + "format": "float" + }, + { + "description": "A detailed spacing on some axis (horizontal or vertical), with a size for each side. If an horizontal spacing, then it will be (left, right), if vertical it will be (top, bottom)", + "type": "array", + "items": [ + { + "type": "number", + "format": "float" + }, + { + "type": "number", + "format": "float" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + }, + "vertical_padding": { + "description": "Bar vertical padding. Use one value for symmetric padding or use `[top, bottom]` to specify a different padding on each side (default: 10)", + "anyOf": [ + { + "description": "A symmetric spacing on some axis (horizontal or vertical), with the same size on both sides", + "type": "number", + "format": "float" + }, + { + "description": "A detailed spacing on some axis (horizontal or vertical), with a size for each side. If an horizontal spacing, then it will be (left, right), if vertical it will be (top, bottom)", + "type": "array", + "items": [ + { + "type": "number", + "format": "float" + }, + { + "type": "number", + "format": "float" + } + ], + "maxItems": 2, + "minItems": 2 + } + ] + }, "widget_spacing": { "description": "Spacing between widgets (default: 10.0)", "type": "number",