diff --git a/docs/modules/Launcher.md b/docs/modules/Launcher.md index 4a68c30b..e00371da 100644 --- a/docs/modules/Launcher.md +++ b/docs/modules/Launcher.md @@ -15,7 +15,8 @@ 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. | +| `icon_overrides` | `map` | `{}` | Map of app IDs (or classes) to icon names, overriding the app's default icon. | | `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/modules/launcher/item.rs b/src/modules/launcher/item.rs index 3b2fa37a..3d9af724 100644 --- a/src/modules/launcher/item.rs +++ b/src/modules/launcher/item.rs @@ -24,16 +24,18 @@ 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 +110,7 @@ impl From for Item { open_state, windows, name, + icon_override: String::new(), } } } @@ -167,7 +170,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 2359aeb6..c302d504 100644 --- a/src/modules/launcher/mod.rs +++ b/src/modules/launcher/mod.rs @@ -15,6 +15,7 @@ use gtk::prelude::*; use gtk::{Button, Orientation}; use indexmap::IndexMap; use serde::Deserialize; +use std::collections::HashMap; use std::process::{Command, Stdio}; use std::sync::Arc; use tokio::sync::{broadcast, mpsc}; @@ -29,6 +30,12 @@ pub struct LauncherModule { /// **Default**: `null` favorites: Option>, + /// Map of app IDs (or classes) to icon names, + /// overriding the app's default icon. + /// + /// **Default**; `null` + icon_overrides: Option>, + /// Whether to show application names on the bar. /// /// **Default**: `false` @@ -149,24 +156,33 @@ impl Module for LauncherModule { favorites .iter() .map(|app_id| { + let icon_override = self + .icon_overrides + .as_ref() + .and_then(|overrides| 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 = arc_mut!(self.icon_overrides.clone()); + let icon_overrides2 = Arc::clone(&icon_overrides); + let tx = context.tx.clone(); let tx2 = context.tx.clone(); let wl = context.client::(); spawn(async move { let items = items2; + let icon_overrides = icon_overrides2; let tx = tx2; let mut wlrx = wl.subscribe_toplevels(); @@ -180,7 +196,16 @@ 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()); + let icon_overrides = lock!(icon_overrides); + + if let Some(overrides) = icon_overrides.as_ref() { + if let Some(icon) = overrides.get(&info.app_id) { + item.icon_override = icon.clone(); + } + } + + items.insert(info.app_id.clone(), item); } } } @@ -210,7 +235,14 @@ 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(); + let icon_overrides = lock!(icon_overrides); + + if let Some(overrides) = icon_overrides.as_ref() { + if let Some(icon) = overrides.get(&app_id) { + item.icon_override = icon.clone(); + } + } items.insert(app_id.clone(), item.clone());