1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-16 22:31:03 +02:00

Merge pull request #837 from BowDown097/master

feat: icon overrides
This commit is contained in:
Jake Stanger 2025-02-15 22:43:46 +00:00 committed by GitHub
commit 49ab7e0c7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 77 additions and 18 deletions

View file

@ -281,9 +281,10 @@ 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: The following table lists each of the top-level bar config options:
| Name | Type | Default | Description | | Name | Type | Default | Description |
|--------------------|-----------------------------------------|---------|---------------------------------------------------------------| |--------------------|-----------------------------------------|---------|-------------------------------------------------------------------------------|
| `ironvar_defaults` | `Map<string, string>` | `{}` | Map of [ironvar](ironvars) keys against their default values. | | `ironvar_defaults` | `Map<string, string>` | `{}` | Map of [ironvar](ironvars) keys against their default values. |
| `monitors` | `Map<string, BarConfig or BarConfig[]>` | `null` | Map of monitor names against bar configs. | | `monitors` | `Map<string, BarConfig or BarConfig[]>` | `null` | Map of monitor names against bar configs. |
| `icon_overrides` | `Map<string, string>` | `{}` | Map of app IDs (or classes) to icon names, overriding the app's default icon. |
> [!TIP] > [!TIP]
> `monitors` is only required if you are following **2b** or **2c** (ie not the same bar across all monitors). > `monitors` is only required if you are following **2b** or **2c** (ie not the same bar across all monitors).

View file

@ -15,7 +15,7 @@ Optionally displays a launchable set of favourites.
| | Type | Default | Description | | | 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_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. | | `show_icons` | `boolean` | `true` | Whether to show app icons on the button. |
| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | | `icon_size` | `integer` | `32` | Size to render icon at (image icons only). |

View file

@ -8,7 +8,9 @@ use gtk::gdk::Monitor;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType}; use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType};
use gtk_layer_shell::LayerShell; use gtk_layer_shell::LayerShell;
use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tracing::{debug, info}; use tracing::{debug, info};
@ -23,6 +25,7 @@ pub struct Bar {
name: String, name: String,
monitor_name: String, monitor_name: String,
monitor_size: (i32, i32), monitor_size: (i32, i32),
icon_overrides: Arc<HashMap<String, String>>,
position: BarPosition, position: BarPosition,
ironbar: Rc<Ironbar>, ironbar: Rc<Ironbar>,
@ -43,6 +46,7 @@ impl Bar {
app: &Application, app: &Application,
monitor_name: String, monitor_name: String,
monitor_size: (i32, i32), monitor_size: (i32, i32),
icon_overrides: Arc<HashMap<String, String>>,
config: BarConfig, config: BarConfig,
ironbar: Rc<Ironbar>, ironbar: Rc<Ironbar>,
) -> Self { ) -> Self {
@ -92,6 +96,7 @@ impl Bar {
name, name,
monitor_name, monitor_name,
monitor_size, monitor_size,
icon_overrides,
position, position,
ironbar, ironbar,
window, window,
@ -268,6 +273,7 @@ impl Bar {
output_name: &self.monitor_name, output_name: &self.monitor_name,
location: $location, location: $location,
icon_theme: &icon_theme, icon_theme: &icon_theme,
icon_overrides: self.icon_overrides.clone(),
} }
}; };
} }
@ -398,9 +404,17 @@ pub fn create_bar(
monitor: &Monitor, monitor: &Monitor,
monitor_name: String, monitor_name: String,
monitor_size: (i32, i32), monitor_size: (i32, i32),
icon_overrides: Arc<HashMap<String, String>>,
config: BarConfig, config: BarConfig,
ironbar: Rc<Ironbar>, ironbar: Rc<Ironbar>,
) -> Result<Bar> { ) -> Result<Bar> {
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) bar.init(monitor)
} }

View file

@ -388,6 +388,13 @@ pub struct Config {
/// ///
/// Providing this option overrides the single, global `bar` option. /// Providing this option overrides the single, global `bar` option.
pub monitors: Option<HashMap<String, MonitorConfig>>, pub monitors: Option<HashMap<String, MonitorConfig>>,
/// Map of app IDs (or classes) to icon names,
/// overriding the app's default icon.
///
/// **Default**: `{}`
#[serde(default)]
pub icon_overrides: HashMap<String, String>,
} }
const fn default_layer() -> gtk_layer_shell::Layer { const fn default_layer() -> gtk_layer_shell::Layer {

View file

@ -383,6 +383,7 @@ fn load_output_bars(
}; };
let config = ironbar.config.borrow(); let config = ironbar.config.borrow();
let icon_overrides = Arc::new(config.icon_overrides.clone());
let display = get_display(); let display = get_display();
// let pos = output.logical_position.unwrap_or_default(); // let pos = output.logical_position.unwrap_or_default();
@ -406,6 +407,7 @@ fn load_output_bars(
&monitor, &monitor,
monitor_name.to_string(), monitor_name.to_string(),
output_size, output_size,
icon_overrides,
config.clone(), config.clone(),
ironbar.clone(), ironbar.clone(),
)?] )?]
@ -418,6 +420,7 @@ fn load_output_bars(
&monitor, &monitor,
monitor_name.to_string(), monitor_name.to_string(),
output_size, output_size,
icon_overrides.clone(),
config.clone(), config.clone(),
ironbar.clone(), ironbar.clone(),
) )
@ -428,6 +431,7 @@ fn load_output_bars(
&monitor, &monitor,
monitor_name.to_string(), monitor_name.to_string(),
output_size, output_size,
icon_overrides,
config.bar.clone(), config.bar.clone(),
ironbar.clone(), ironbar.clone(),
)?], )?],

View file

@ -132,8 +132,6 @@ impl Module<gtk::Box> for FocusedModule {
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>, context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
info: &ModuleInfo, info: &ModuleInfo,
) -> Result<ModuleParts<gtk::Box>> { ) -> Result<ModuleParts<gtk::Box>> {
let icon_theme = info.icon_theme;
let container = gtk::Box::new(info.bar_position.orientation(), 5); let container = gtk::Box::new(info.bar_position.orientation(), 5);
let icon = gtk::Image::new(); let icon = gtk::Image::new();
@ -152,10 +150,17 @@ impl Module<gtk::Box> for FocusedModule {
container.add(&label); 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 => { glib_recv!(context.subscribe(), data => {
if let Some((name, id)) = data { if let Some((name, mut id)) = data {
if self.show_icon { 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) match ImageProvider::parse(&id, &icon_theme, true, self.icon_size)
.map(|image| image.load_into_image(&icon)) .map(|image| image.load_into_image(&icon))
{ {

View file

@ -24,16 +24,23 @@ pub struct Item {
pub open_state: OpenState, pub open_state: OpenState,
pub windows: IndexMap<usize, Window>, pub windows: IndexMap<usize, Window>,
pub name: String, pub name: String,
pub icon_override: String,
} }
impl Item { 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 { Self {
app_id, app_id,
favorite, favorite,
open_state, open_state,
windows: IndexMap::new(), windows: IndexMap::new(),
name: String::new(), name: String::new(),
icon_override,
} }
} }
@ -108,6 +115,7 @@ impl From<ToplevelInfo> for Item {
open_state, open_state,
windows, windows,
name, name,
icon_override: String::new(),
} }
} }
} }
@ -167,7 +175,9 @@ impl ItemButton {
} }
if appearance.show_icons { 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() item.name.clone()
} else { } else {
item.app_id.clone() item.app_id.clone()

View file

@ -138,7 +138,7 @@ impl Module<gtk::Box> for LauncherModule {
fn spawn_controller( fn spawn_controller(
&self, &self,
_info: &ModuleInfo, info: &ModuleInfo,
context: &WidgetContext<Self::SendMessage, Self::ReceiveMessage>, context: &WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
mut rx: mpsc::Receiver<Self::ReceiveMessage>, mut rx: mpsc::Receiver<Self::ReceiveMessage>,
) -> crate::Result<()> { ) -> crate::Result<()> {
@ -149,18 +149,24 @@ impl Module<gtk::Box> for LauncherModule {
favorites favorites
.iter() .iter()
.map(|app_id| { .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(), 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::<IndexMap<_, _>>() .collect::<IndexMap<_, _>>()
}); });
let items = arc_mut!(items); let items = arc_mut!(items);
let items2 = Arc::clone(&items); let items2 = Arc::clone(&items);
let icon_overrides = info.icon_overrides.clone();
let tx = context.tx.clone(); let tx = context.tx.clone();
let tx2 = context.tx.clone(); let tx2 = context.tx.clone();
@ -180,7 +186,13 @@ impl Module<gtk::Box> for LauncherModule {
item.merge_toplevel(info.clone()); item.merge_toplevel(info.clone());
} }
None => { 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<gtk::Box> for LauncherModule {
let item = items.get_mut(&info.app_id); let item = items.get_mut(&info.app_id);
match item { match item {
None => { 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()); items.insert(app_id.clone(), item.clone());

View file

@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -71,6 +72,7 @@ pub struct ModuleInfo<'a> {
pub monitor: &'a Monitor, pub monitor: &'a Monitor,
pub output_name: &'a str, pub output_name: &'a str,
pub icon_theme: &'a IconTheme, pub icon_theme: &'a IconTheme,
pub icon_overrides: Arc<HashMap<String, String>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]