diff --git a/docs/Configuration guide.md b/docs/Configuration guide.md index 25e1b22..50682cf 100644 --- a/docs/Configuration guide.md +++ b/docs/Configuration guide.md @@ -280,10 +280,11 @@ Check [here](config) for an example config file for a fully configured bar in ea The following table lists each of the top-level bar config options: -| Name | Type | Default | Description | -|--------------------|-----------------------------------------|---------|---------------------------------------------------------------| -| `ironvar_defaults` | `Map` | `{}` | Map of [ironvar](ironvars) keys against their default values. | -| `monitors` | `Map` | `null` | Map of monitor names against bar configs. | +| Name | Type | Default | Description | +|--------------------|-----------------------------------------|---------|-------------------------------------------------------------------------------| +| `ironvar_defaults` | `Map` | `{}` | Map of [ironvar](ironvars) keys against their default values. | +| `monitors` | `Map` | `null` | Map of monitor names against bar configs. | +| `icon_overrides` | `Map` | `{}` | Map of app IDs (or classes) to icon names, overriding the app's default icon. | > [!TIP] > `monitors` is only required if you are following **2b** or **2c** (ie not the same bar across all monitors). @@ -353,4 +354,4 @@ For information on the `Script` type, and embedding scripts in strings, see [her | `name` | `string` | `null` | Sets the unique widget name, allowing you to style it using `#name`. | | `class` | `string` | `null` | Sets one or more CSS classes, allowing you to style it using `.class`. | -For more information on styling, please see the [styling guide](styling-guide). \ No newline at end of file +For more information on styling, please see the [styling guide](styling-guide). diff --git a/docs/modules/Launcher.md b/docs/modules/Launcher.md index 4a68c30..2c93432 100644 --- a/docs/modules/Launcher.md +++ b/docs/modules/Launcher.md @@ -15,7 +15,7 @@ Optionally displays a launchable set of favourites. | | Type | Default | Description | |-----------------------------|---------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| -| `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher | +| `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher. | | `show_names` | `boolean` | `false` | Whether to show app names on the button label. Names will still show on tooltips when set to false. | | `show_icons` | `boolean` | `true` | Whether to show app icons on the button. | | `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | diff --git a/src/bar.rs b/src/bar.rs index 518cadb..73feba2 100644 --- a/src/bar.rs +++ b/src/bar.rs @@ -8,7 +8,9 @@ use gtk::gdk::Monitor; use gtk::prelude::*; use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType}; use gtk_layer_shell::LayerShell; +use std::collections::HashMap; use std::rc::Rc; +use std::sync::Arc; use std::time::Duration; use tracing::{debug, info}; @@ -23,6 +25,7 @@ pub struct Bar { name: String, monitor_name: String, monitor_size: (i32, i32), + icon_overrides: Arc>, position: BarPosition, ironbar: Rc, @@ -43,6 +46,7 @@ impl Bar { app: &Application, monitor_name: String, monitor_size: (i32, i32), + icon_overrides: Arc>, config: BarConfig, ironbar: Rc, ) -> Self { @@ -92,6 +96,7 @@ impl Bar { name, monitor_name, monitor_size, + icon_overrides, position, ironbar, window, @@ -268,6 +273,7 @@ impl Bar { output_name: &self.monitor_name, location: $location, icon_theme: &icon_theme, + icon_overrides: self.icon_overrides.clone(), } }; } @@ -398,9 +404,17 @@ pub fn create_bar( monitor: &Monitor, monitor_name: String, monitor_size: (i32, i32), + icon_overrides: Arc>, config: BarConfig, ironbar: Rc, ) -> Result { - let bar = Bar::new(app, monitor_name, monitor_size, config, ironbar); + let bar = Bar::new( + app, + monitor_name, + monitor_size, + icon_overrides, + config, + ironbar, + ); bar.init(monitor) } diff --git a/src/config/mod.rs b/src/config/mod.rs index 52363ea..f4666d7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -388,6 +388,13 @@ pub struct Config { /// /// Providing this option overrides the single, global `bar` option. pub monitors: Option>, + + /// Map of app IDs (or classes) to icon names, + /// overriding the app's default icon. + /// + /// **Default**: `{}` + #[serde(default)] + pub icon_overrides: HashMap, } const fn default_layer() -> gtk_layer_shell::Layer { diff --git a/src/main.rs b/src/main.rs index 03e5091..0fe9480 100644 --- a/src/main.rs +++ b/src/main.rs @@ -383,6 +383,7 @@ fn load_output_bars( }; let config = ironbar.config.borrow(); + let icon_overrides = Arc::new(config.icon_overrides.clone()); let display = get_display(); // let pos = output.logical_position.unwrap_or_default(); @@ -406,6 +407,7 @@ fn load_output_bars( &monitor, monitor_name.to_string(), output_size, + icon_overrides, config.clone(), ironbar.clone(), )?] @@ -418,6 +420,7 @@ fn load_output_bars( &monitor, monitor_name.to_string(), output_size, + icon_overrides.clone(), config.clone(), ironbar.clone(), ) @@ -428,6 +431,7 @@ fn load_output_bars( &monitor, monitor_name.to_string(), output_size, + icon_overrides, config.bar.clone(), ironbar.clone(), )?], diff --git a/src/modules/focused.rs b/src/modules/focused.rs index 250493e..87fc81d 100644 --- a/src/modules/focused.rs +++ b/src/modules/focused.rs @@ -132,8 +132,6 @@ impl Module for FocusedModule { context: WidgetContext, info: &ModuleInfo, ) -> Result> { - let icon_theme = info.icon_theme; - let container = gtk::Box::new(info.bar_position.orientation(), 5); let icon = gtk::Image::new(); @@ -152,10 +150,17 @@ impl Module for FocusedModule { container.add(&label); { - let icon_theme = icon_theme.clone(); + let icon_overrides = info.icon_overrides.clone(); + let icon_theme = info.icon_theme.clone(); + glib_recv!(context.subscribe(), data => { - if let Some((name, id)) = data { + if let Some((name, mut id)) = data { if self.show_icon { + + if let Some(icon) = icon_overrides.get(&id) { + id = icon.clone(); + } + match ImageProvider::parse(&id, &icon_theme, true, self.icon_size) .map(|image| image.load_into_image(&icon)) { diff --git a/src/modules/launcher/item.rs b/src/modules/launcher/item.rs index 3b2fa37..0bcd265 100644 --- a/src/modules/launcher/item.rs +++ b/src/modules/launcher/item.rs @@ -24,16 +24,23 @@ pub struct Item { pub open_state: OpenState, pub windows: IndexMap, pub name: String, + pub icon_override: String, } impl Item { - pub fn new(app_id: String, open_state: OpenState, favorite: bool) -> Self { + pub fn new( + app_id: String, + icon_override: String, + open_state: OpenState, + favorite: bool, + ) -> Self { Self { app_id, favorite, open_state, windows: IndexMap::new(), name: String::new(), + icon_override, } } @@ -108,6 +115,7 @@ impl From for Item { open_state, windows, name, + icon_override: String::new(), } } } @@ -167,7 +175,9 @@ impl ItemButton { } if appearance.show_icons { - let input = if item.app_id.is_empty() { + let input = if !item.icon_override.is_empty() { + item.icon_override.clone() + } else if item.app_id.is_empty() { item.name.clone() } else { item.app_id.clone() diff --git a/src/modules/launcher/mod.rs b/src/modules/launcher/mod.rs index 2359aeb..fa8c206 100644 --- a/src/modules/launcher/mod.rs +++ b/src/modules/launcher/mod.rs @@ -138,7 +138,7 @@ impl Module for LauncherModule { fn spawn_controller( &self, - _info: &ModuleInfo, + info: &ModuleInfo, context: &WidgetContext, mut rx: mpsc::Receiver, ) -> crate::Result<()> { @@ -149,18 +149,24 @@ impl Module for LauncherModule { favorites .iter() .map(|app_id| { + let icon_override = info + .icon_overrides + .get(app_id) + .map_or_else(String::new, |v| v.to_string()); + ( app_id.to_string(), - Item::new(app_id.to_string(), OpenState::Closed, true), + Item::new(app_id.to_string(), icon_override, OpenState::Closed, true), ) }) .collect::>() }); let items = arc_mut!(items); - let items2 = Arc::clone(&items); + let icon_overrides = info.icon_overrides.clone(); + let tx = context.tx.clone(); let tx2 = context.tx.clone(); @@ -180,7 +186,13 @@ impl Module for LauncherModule { item.merge_toplevel(info.clone()); } None => { - items.insert(info.app_id.clone(), Item::from(info.clone())); + let mut item = Item::from(info.clone()); + + if let Some(icon) = icon_overrides.get(&info.app_id) { + item.icon_override = icon.clone(); + } + + items.insert(info.app_id.clone(), item); } } } @@ -210,7 +222,11 @@ impl Module for LauncherModule { let item = items.get_mut(&info.app_id); match item { None => { - let item: Item = info.into(); + let mut item: Item = info.into(); + + if let Some(icon) = icon_overrides.get(&app_id) { + item.icon_override = icon.clone(); + } items.insert(app_id.clone(), item.clone()); diff --git a/src/modules/mod.rs b/src/modules/mod.rs index edc0169..e1b8335 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fmt::Debug; use std::rc::Rc; use std::sync::Arc; @@ -71,6 +72,7 @@ pub struct ModuleInfo<'a> { pub monitor: &'a Monitor, pub output_name: &'a str, pub icon_theme: &'a IconTheme, + pub icon_overrides: Arc>, } #[derive(Debug, Clone)]