[GH-ISSUE #1039] GTK symbolic icons are not themed #3136

Closed
opened 2026-05-22 23:54:13 +01:00 by JakeStanger · 7 comments
Owner

Originally created by @Rodrigodd on GitHub (Jun 9, 2025).
Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1039

Describe the bug

The battery module, for example, displays a symbolic icon (battery-missing-symbolic in my case), but the icon is not themed. The same happens with other uses of symbolic icons in Ironbar.

To reproduce
Steps to reproduce the behavior:

  1. Add any module that displays a GTK symbolic icon, such as battery.
  2. The icon appears with a dark gray color:

Image

Expected behavior

My system is configure with theme "Adwaita:dark", so the icon should be white like so:

Image

System information:

  • Distro: [e.g. Arch Linux, Ubuntu 22.10]
  • Compositor: [e.g. Sway]
  • Ironbar version: [e.g. 0.16.1]

Possible fixes

In my fork, I’m using the following diff:

diff --git a/src/image/provider.rs b/src/image/provider.rs
index 5004c37..ee22ea7 100644
--- a/src/image/provider.rs
+++ b/src/image/provider.rs
@@ -4,6 +4,7 @@ use crate::{glib_recv_mpsc, send_async, spawn};
 use cfg_if::cfg_if;
 use color_eyre::{Help, Report, Result};
 use gtk::cairo::Surface;
+use gtk::gdk::RGBA;
 use gtk::gdk::ffi::gdk_cairo_surface_create_from_pixbuf;
 use gtk::gdk_pixbuf::Pixbuf;
 use gtk::prelude::*;
@@ -198,6 +199,10 @@ impl<'a> ImageProvider<'a> {
 
         let pixbuf = match &self.location {
             ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale),
+            // ImageLocation::Icon { name, theme } => {
+            //     image.set_icon_name(Some(name));
+            //     return Ok(());
+            // }
             ImageLocation::Local(path) => self.get_from_file(path, scale),
             ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale),
             #[cfg(feature = "http")]
@@ -231,7 +236,14 @@ impl<'a> ImageProvider<'a> {
     fn get_from_icon(&self, name: &str, theme: &IconTheme, scale: i32) -> Result<Pixbuf> {
         let pixbuf =
             match theme.lookup_icon_for_scale(name, self.size, scale, IconLookupFlags::empty()) {
-                Some(_) => theme.load_icon(name, self.size * scale, IconLookupFlags::FORCE_SIZE),
+                Some(info) => info
+                    .load_symbolic(
+                        &RGBA::WHITE,
+                        Some(&RGBA::GREEN),
+                        Some(&RGBA::new(1.0, 1.0, 0.0, 1.0)),
+                        Some(&RGBA::RED),
+                    )
+                    .map(|(pixbuf, _symbolic)| Some(pixbuf)),
                 None => Ok(None),
             }?;

I found two possible approaches for this. One is to use image.set_icon_name(Some(icon_name)) instead of loading a Pixbuf, but that does not respect the icon_theme defined in the Ironbar configuration.

The other is to call load_symbolic on the IconInfo returned by lookup_icon_for_scale, but that requires explicitly passing the colors for the icon, rather than inheriting them from the current GTK theme.

Ideally, the fix should respect both the GTK icon theme set in the Ironbar configuration and whatever defines the colors for symbolic icons when using Image::set_icon_name. Because I couldn't come up with a solution that satisfies both requirements, I haven't submitted a PR.

Originally created by @Rodrigodd on GitHub (Jun 9, 2025). Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1039 **Describe the bug** The battery module, for example, displays a symbolic icon (`battery-missing-symbolic` in my case), but the icon is not themed. The same happens with other uses of symbolic icons in Ironbar. **To reproduce** Steps to reproduce the behavior: 1. Add any module that displays a GTK symbolic icon, such as `battery`. 2. The icon appears with a dark gray color: ![Image](https://github.com/user-attachments/assets/efa2b89e-8fc4-434f-b0c1-43fe2d0fe762) **Expected behavior** My system is configure with theme "Adwaita:dark", so the icon should be white like so: ![Image](https://github.com/user-attachments/assets/8c5f78ce-625f-4eae-8a6c-6658181146cf) **System information:** - Distro: [e.g. Arch Linux, Ubuntu 22.10] - Compositor: [e.g. Sway] - Ironbar version: [e.g. 0.16.1] **Possible fixes** In my fork, I’m using the following diff: ```diff diff --git a/src/image/provider.rs b/src/image/provider.rs index 5004c37..ee22ea7 100644 --- a/src/image/provider.rs +++ b/src/image/provider.rs @@ -4,6 +4,7 @@ use crate::{glib_recv_mpsc, send_async, spawn}; use cfg_if::cfg_if; use color_eyre::{Help, Report, Result}; use gtk::cairo::Surface; +use gtk::gdk::RGBA; use gtk::gdk::ffi::gdk_cairo_surface_create_from_pixbuf; use gtk::gdk_pixbuf::Pixbuf; use gtk::prelude::*; @@ -198,6 +199,10 @@ impl<'a> ImageProvider<'a> { let pixbuf = match &self.location { ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale), + // ImageLocation::Icon { name, theme } => { + // image.set_icon_name(Some(name)); + // return Ok(()); + // } ImageLocation::Local(path) => self.get_from_file(path, scale), ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale), #[cfg(feature = "http")] @@ -231,7 +236,14 @@ impl<'a> ImageProvider<'a> { fn get_from_icon(&self, name: &str, theme: &IconTheme, scale: i32) -> Result<Pixbuf> { let pixbuf = match theme.lookup_icon_for_scale(name, self.size, scale, IconLookupFlags::empty()) { - Some(_) => theme.load_icon(name, self.size * scale, IconLookupFlags::FORCE_SIZE), + Some(info) => info + .load_symbolic( + &RGBA::WHITE, + Some(&RGBA::GREEN), + Some(&RGBA::new(1.0, 1.0, 0.0, 1.0)), + Some(&RGBA::RED), + ) + .map(|(pixbuf, _symbolic)| Some(pixbuf)), None => Ok(None), }?; ``` I found two possible approaches for this. One is to use `image.set_icon_name(Some(icon_name))` instead of loading a `Pixbuf`, but that does not respect the `icon_theme` defined in the Ironbar configuration. The other is to call `load_symbolic` on the `IconInfo` returned by `lookup_icon_for_scale`, but that requires explicitly passing the colors for the icon, rather than inheriting them from the current GTK theme. Ideally, the fix should respect both the GTK icon theme set in the Ironbar configuration and whatever defines the colors for symbolic icons when using `Image::set_icon_name`. Because I couldn't come up with a solution that satisfies both requirements, I haven't submitted a PR.
JakeStanger 2026-05-22 23:54:13 +01:00
Author
Owner

@JakeStanger commented on GitHub (Jun 9, 2025):

The GTK documentation states you can pass null (None in our case) to the colour arguments for load_symbolic and it uses the "default". Generally that means it should pick it up from the theme. Does it do that here?

<!-- gh-comment-id:2956225960 --> @JakeStanger commented on GitHub (Jun 9, 2025): The GTK documentation states you can pass `null` (`None` in our case) to the colour arguments for `load_symbolic` and it uses the "default". Generally that means it should pick it up from the theme. Does it do that here?
Author
Owner

@Rodrigodd commented on GitHub (Jun 9, 2025):

I didn't notice that. I didn't test it but I believe it should work (so I didn't have to specify those colors in my diff). But that is the case only for the success, warning and error colors - the fg color cannot be NUL/None, but I guess it should also come from the theme? Or respect some CSS variable? I am not that familiar with GTK theming system. It should at least be white on dark theme, and black on light theme (not sure how well Ironbar is suppose to handle light themes).

<!-- gh-comment-id:2957126270 --> @Rodrigodd commented on GitHub (Jun 9, 2025): I didn't notice that. I didn't test it but I believe it should work (so I didn't have to specify those colors in my diff). But that is the case only for the success, warning and error colors - the `fg` color cannot be `NUL`/`None`, but I guess it should also come from the theme? Or respect some CSS variable? I am not that familiar with GTK theming system. It should at least be white on dark theme, and black on light theme (not sure how well Ironbar is suppose to handle light themes).
Author
Owner

@JakeStanger commented on GitHub (Jun 11, 2025):

not sure how well Ironbar is suppose to handle light themes

It's supposed to handle them without issue! It's just an area that hasn't got as much love because I don't use light themes.

The correct approach (I think?) for loading the icon with the system foreground colour is to use load_symbolic_for_context. I've no idea how you get the context though. It looks like since all the style info is attached to the screen, you can just call StyleContext::new()?

<!-- gh-comment-id:2963220347 --> @JakeStanger commented on GitHub (Jun 11, 2025): > not sure how well Ironbar is suppose to handle light themes It's supposed to handle them without issue! It's just an area that hasn't got as much love because I don't use light themes. The correct approach (I think?) for loading the icon with the system foreground colour is to use [load_symbolic_for_context](https://docs.gtk.org/gtk3/method.IconInfo.load_symbolic_for_context.html). I've no idea how you get the context though. It looks like since all the style info is attached to the screen, you can just call `StyleContext::new()`?
Author
Owner

@Rodrigodd commented on GitHub (Jun 18, 2025):

I tried using load_symbolic_for_context and it worked. But a problem is that the icon does not reload when changing styles.css, and it does not respect the -gtk-icon-theme CSS property.

diff
diff --git a/src/image/provider.rs b/src/image/provider.rs
index 5004c37..5637c0f 100644
--- a/src/image/provider.rs
+++ b/src/image/provider.rs
@@ -6,8 +6,8 @@ use color_eyre::{Help, Report, Result};
 use gtk::cairo::Surface;
 use gtk::gdk::ffi::gdk_cairo_surface_create_from_pixbuf;
 use gtk::gdk_pixbuf::Pixbuf;
-use gtk::prelude::*;
 use gtk::{IconLookupFlags, IconTheme};
+use gtk::{StyleContext, prelude::*};
 use std::path::{Path, PathBuf};
 #[cfg(feature = "http")]
 use tokio::sync::mpsc;
@@ -197,7 +197,9 @@ impl<'a> ImageProvider<'a> {
         let scale = image.scale_factor();
 
         let pixbuf = match &self.location {
-            ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale),
+            ImageLocation::Icon { name, theme } => {
+                self.get_from_icon(name, theme, scale, &image.style_context())
+            }
             ImageLocation::Local(path) => self.get_from_file(path, scale),
             ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale),
             #[cfg(feature = "http")]
@@ -228,10 +230,18 @@ impl<'a> ImageProvider<'a> {
     }
 
     /// Attempts to get a `Pixbuf` from the GTK icon theme.
-    fn get_from_icon(&self, name: &str, theme: &IconTheme, scale: i32) -> Result<Pixbuf> {
+    fn get_from_icon(
+        &self,
+        name: &str,
+        theme: &IconTheme,
+        scale: i32,
+        context: &StyleContext,
+    ) -> Result<Pixbuf> {
         let pixbuf =
             match theme.lookup_icon_for_scale(name, self.size, scale, IconLookupFlags::empty()) {
-                Some(_) => theme.load_icon(name, self.size * scale, IconLookupFlags::FORCE_SIZE),
+                Some(info) => info
+                    .load_symbolic_for_context(context)
+                    .map(|(pixbuf, _symbolic)| Some(pixbuf)),
                 None => Ok(None),
             }?;
 
diff --git a/src/modules/tray/icon.rs b/src/modules/tray/icon.rs
index a187702..548012e 100644
--- a/src/modules/tray/icon.rs
+++ b/src/modules/tray/icon.rs
@@ -6,6 +6,7 @@ use glib::translate::ToGlibPtr;
 use gtk::ffi::gtk_icon_theme_get_search_path;
 use gtk::gdk_pixbuf::{Colorspace, InterpType, Pixbuf};
 use gtk::prelude::IconThemeExt;
+use gtk::traits::WidgetExt;
 use gtk::{IconLookupFlags, IconTheme, Image};
 use std::collections::HashSet;
 use std::ffi::CStr;
@@ -66,8 +67,10 @@ fn get_image_from_icon_name(item: &TrayMenu, icon_theme: &IconTheme, size: u32)
     });
 
     if let Some(icon_info) = icon_info {
-        let pixbuf = icon_info.load_icon()?;
         let image = Image::new();
+        let pixbuf = icon_info
+            .load_symbolic_for_context(&image.style_context())
+            .map(|(pixbuf, _symbolic)| pixbuf)?;
         ImageProvider::create_and_load_surface(&pixbuf, &image)?;
         Ok(image)
     } else {

Using Image::set_icon_name addresses both problems, but I could not find a good way to change the application default icon theme, respecting the icon_theme field in ironbar configuration file. The best idea I come up is generating and loading a CSS file at runtime with -gtk-icon-theme property set.

Do you think that just removing the icon_theme field from the configuration, and directing the user to configure -gtk-icon-theme in styles.css instead is a good solution?

diff
diff --git a/src/image/provider.rs b/src/image/provider.rs
index 5004c37..585d137 100644
--- a/src/image/provider.rs
+++ b/src/image/provider.rs
@@ -197,7 +197,11 @@ impl<'a> ImageProvider<'a> {
         let scale = image.scale_factor();
 
         let pixbuf = match &self.location {
-            ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale),
+            ImageLocation::Icon { name, theme } => {
+                image.set_icon_name(Some(name.as_str()));
+                image.set_pixel_size(self.size);
+                return Ok(());
+            }
             ImageLocation::Local(path) => self.get_from_file(path, scale),
             ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale),
             #[cfg(feature = "http")]
test-config

For reference, below is the configuration I was using to test the changes:

Image

  • IRONBAR_CONFIG=test-configs/icons.corn IRONBAR_CSS=test-configs/icons.css cargo run
  • icons.corn:
{
  icon_theme="Pop"
  start=[
    {type="custom" class="a" bar=[
      {type="label" size=18 label="Test A: " }
      {type="image" size=18 src="network-wireless-disabled-symbolic"}
      {type="image" size=18 src="dialog-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="task-past-due-symbolic"}
      {type="image" size=18 src="dialog-warning-symbolic"}
      {type="image" size=18 src="printer-warning-symbolic"}
      {type="image" size=18 src="task-due-symbolic"}
      {type="image" size=18 src="battery-level-90-charging-symbolic"}
    ]}

    {type="custom" class="b" bar=[
      {type="label" label="Test B: " }
      {type="image" size=18 src="network-wireless-disabled-symbolic"}
      {type="image" size=18 src="dialog-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="task-past-due-symbolic"}
      {type="image" size=18 src="dialog-warning-symbolic"}
      {type="image" size=18 src="printer-warning-symbolic"}
      {type="image" size=18 src="task-due-symbolic"}
      {type="image" size=18 src="battery-level-90-charging-symbolic"}
    ]}

    {type="custom" class="c" bar=[
      {type="label" label="Test C: " }
      {type="image" size=18 src="network-wireless-disabled-symbolic"}
      {type="image" size=18 src="dialog-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="task-past-due-symbolic"}
      {type="image" size=18 src="dialog-warning-symbolic"}
      {type="image" size=18 src="printer-warning-symbolic"}
      {type="image" size=18 src="task-due-symbolic"}
      {type="image" size=18 src="battery-level-90-charging-symbolic"}
    ]}

    {type="custom" class="d" bar=[
      {type="label" label="Test D: " }
      {type="image" size=18 src="network-wireless-disabled-symbolic"}
      {type="image" size=18 src="dialog-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="network-error-symbolic"}
      {type="image" size=18 src="task-past-due-symbolic"}
      {type="image" size=18 src="dialog-warning-symbolic"}
      {type="image" size=18 src="printer-warning-symbolic"}
      {type="image" size=18 src="task-due-symbolic"}
      {type="image" size=18 src="battery-level-90-charging-symbolic"}
    ]}
  ]
}
  • icons.css:
* {
    margin: 2px;
}
.a {
    color: #ffffff;
}
.b {
    color: #000000;
    background-color: #ffffff;
    -gtk-icon-theme: "Pop";
}
.c {
    color: #80ff80;
    text-shadow: 3px 3px black;
    -gtk-icon-theme: "Adwaita";
    -gtk-icon-shadow: 3px 3px black;
    -gtk-icon-palette: warning #0000ff, error #ff00ff, success #00ffff
}
.d {
    color: #ffffff;
    -gtk-icon-theme: "Adwaita";
}
<!-- gh-comment-id:2982272601 --> @Rodrigodd commented on GitHub (Jun 18, 2025): I tried using `load_symbolic_for_context` and it worked. But a problem is that the icon does not reload when changing `styles.css`, and it does not respect the `-gtk-icon-theme` CSS property. <details> <summary>diff</summary> ```diff diff --git a/src/image/provider.rs b/src/image/provider.rs index 5004c37..5637c0f 100644 --- a/src/image/provider.rs +++ b/src/image/provider.rs @@ -6,8 +6,8 @@ use color_eyre::{Help, Report, Result}; use gtk::cairo::Surface; use gtk::gdk::ffi::gdk_cairo_surface_create_from_pixbuf; use gtk::gdk_pixbuf::Pixbuf; -use gtk::prelude::*; use gtk::{IconLookupFlags, IconTheme}; +use gtk::{StyleContext, prelude::*}; use std::path::{Path, PathBuf}; #[cfg(feature = "http")] use tokio::sync::mpsc; @@ -197,7 +197,9 @@ impl<'a> ImageProvider<'a> { let scale = image.scale_factor(); let pixbuf = match &self.location { - ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale), + ImageLocation::Icon { name, theme } => { + self.get_from_icon(name, theme, scale, &image.style_context()) + } ImageLocation::Local(path) => self.get_from_file(path, scale), ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale), #[cfg(feature = "http")] @@ -228,10 +230,18 @@ impl<'a> ImageProvider<'a> { } /// Attempts to get a `Pixbuf` from the GTK icon theme. - fn get_from_icon(&self, name: &str, theme: &IconTheme, scale: i32) -> Result<Pixbuf> { + fn get_from_icon( + &self, + name: &str, + theme: &IconTheme, + scale: i32, + context: &StyleContext, + ) -> Result<Pixbuf> { let pixbuf = match theme.lookup_icon_for_scale(name, self.size, scale, IconLookupFlags::empty()) { - Some(_) => theme.load_icon(name, self.size * scale, IconLookupFlags::FORCE_SIZE), + Some(info) => info + .load_symbolic_for_context(context) + .map(|(pixbuf, _symbolic)| Some(pixbuf)), None => Ok(None), }?; diff --git a/src/modules/tray/icon.rs b/src/modules/tray/icon.rs index a187702..548012e 100644 --- a/src/modules/tray/icon.rs +++ b/src/modules/tray/icon.rs @@ -6,6 +6,7 @@ use glib::translate::ToGlibPtr; use gtk::ffi::gtk_icon_theme_get_search_path; use gtk::gdk_pixbuf::{Colorspace, InterpType, Pixbuf}; use gtk::prelude::IconThemeExt; +use gtk::traits::WidgetExt; use gtk::{IconLookupFlags, IconTheme, Image}; use std::collections::HashSet; use std::ffi::CStr; @@ -66,8 +67,10 @@ fn get_image_from_icon_name(item: &TrayMenu, icon_theme: &IconTheme, size: u32) }); if let Some(icon_info) = icon_info { - let pixbuf = icon_info.load_icon()?; let image = Image::new(); + let pixbuf = icon_info + .load_symbolic_for_context(&image.style_context()) + .map(|(pixbuf, _symbolic)| pixbuf)?; ImageProvider::create_and_load_surface(&pixbuf, &image)?; Ok(image) } else { ``` </details> Using `Image::set_icon_name` addresses both problems, but I could not find a good way to change the application default icon theme, respecting the `icon_theme` field in ironbar configuration file. The best idea I come up is generating and loading a CSS file at runtime with `-gtk-icon-theme` property set. Do you think that just removing the `icon_theme` field from the configuration, and directing the user to configure `-gtk-icon-theme` in styles.css instead is a good solution? <details> <summary>diff</summary> ```diff diff --git a/src/image/provider.rs b/src/image/provider.rs index 5004c37..585d137 100644 --- a/src/image/provider.rs +++ b/src/image/provider.rs @@ -197,7 +197,11 @@ impl<'a> ImageProvider<'a> { let scale = image.scale_factor(); let pixbuf = match &self.location { - ImageLocation::Icon { name, theme } => self.get_from_icon(name, theme, scale), + ImageLocation::Icon { name, theme } => { + image.set_icon_name(Some(name.as_str())); + image.set_pixel_size(self.size); + return Ok(()); + } ImageLocation::Local(path) => self.get_from_file(path, scale), ImageLocation::Steam(steam_id) => self.get_from_steam_id(steam_id, scale), #[cfg(feature = "http")] ``` </details> <details> <summary>test-config</summary> For reference, below is the configuration I was using to test the changes: ![Image](https://github.com/user-attachments/assets/afc19250-7f61-42c9-a225-3e1da73cb8af) - `IRONBAR_CONFIG=test-configs/icons.corn IRONBAR_CSS=test-configs/icons.css cargo run` - icons.corn: ```corn { icon_theme="Pop" start=[ {type="custom" class="a" bar=[ {type="label" size=18 label="Test A: " } {type="image" size=18 src="network-wireless-disabled-symbolic"} {type="image" size=18 src="dialog-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="task-past-due-symbolic"} {type="image" size=18 src="dialog-warning-symbolic"} {type="image" size=18 src="printer-warning-symbolic"} {type="image" size=18 src="task-due-symbolic"} {type="image" size=18 src="battery-level-90-charging-symbolic"} ]} {type="custom" class="b" bar=[ {type="label" label="Test B: " } {type="image" size=18 src="network-wireless-disabled-symbolic"} {type="image" size=18 src="dialog-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="task-past-due-symbolic"} {type="image" size=18 src="dialog-warning-symbolic"} {type="image" size=18 src="printer-warning-symbolic"} {type="image" size=18 src="task-due-symbolic"} {type="image" size=18 src="battery-level-90-charging-symbolic"} ]} {type="custom" class="c" bar=[ {type="label" label="Test C: " } {type="image" size=18 src="network-wireless-disabled-symbolic"} {type="image" size=18 src="dialog-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="task-past-due-symbolic"} {type="image" size=18 src="dialog-warning-symbolic"} {type="image" size=18 src="printer-warning-symbolic"} {type="image" size=18 src="task-due-symbolic"} {type="image" size=18 src="battery-level-90-charging-symbolic"} ]} {type="custom" class="d" bar=[ {type="label" label="Test D: " } {type="image" size=18 src="network-wireless-disabled-symbolic"} {type="image" size=18 src="dialog-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="network-error-symbolic"} {type="image" size=18 src="task-past-due-symbolic"} {type="image" size=18 src="dialog-warning-symbolic"} {type="image" size=18 src="printer-warning-symbolic"} {type="image" size=18 src="task-due-symbolic"} {type="image" size=18 src="battery-level-90-charging-symbolic"} ]} ] } ``` - icons.css: ```css * { margin: 2px; } .a { color: #ffffff; } .b { color: #000000; background-color: #ffffff; -gtk-icon-theme: "Pop"; } .c { color: #80ff80; text-shadow: 3px 3px black; -gtk-icon-theme: "Adwaita"; -gtk-icon-shadow: 3px 3px black; -gtk-icon-palette: warning #0000ff, error #ff00ff, success #00ffff } .d { color: #ffffff; -gtk-icon-theme: "Adwaita"; } ``` </details>
Author
Owner

@slowsage commented on GitHub (Nov 17, 2025):

@Rodrigodd , can you try https://github.com/slowsage/ironbar/tree/symbolic.

Can you check if the theme/color behavior matches what you expect? (I had a slightly different issue - would not even load).

<!-- gh-comment-id:3539574697 --> @slowsage commented on GitHub (Nov 17, 2025): @Rodrigodd , can you try https://github.com/slowsage/ironbar/tree/symbolic. Can you check if the theme/color behavior matches what you expect? (I had a slightly different issue - would not even load).
Author
Owner

@Rodrigodd commented on GitHub (Nov 17, 2025):

@slowsage Yes, it appears to work:

Image

In the image above, the battery icon is themed correctly, since it uses IconButton, and the Network Manager icons are unaffected because they use Picture directly.

What your commit does is replace Picture with Image when the source is an icon, and use set_icon_name, right? Yeah, I think that’s the best solution available. Before the migration to GTK4, in my fork I was using set_icon_name inside the ImageProvider type, as I described in my previous comment. But I guess that now in GTK4 you need to use Picture for some types of image sources.

So the proper solution would be to create an abstraction like IconButton that changes the underlying widget based on the image source, and use that in every widget instead of Picture directly. But that has the effect of making the icon_theme configuration ineffective, as I mentioned in my previous comment.

<!-- gh-comment-id:3543233712 --> @Rodrigodd commented on GitHub (Nov 17, 2025): @slowsage Yes, it appears to work: <img width="469" height="262" alt="Image" src="https://github.com/user-attachments/assets/908f325f-ba22-4e86-98f7-92db6e071864" /> In the image above, the battery icon is themed correctly, since it uses `IconButton`, and the Network Manager icons are unaffected because they use `Picture` directly. What your commit does is replace `Picture` with `Image` when the source is an icon, and use `set_icon_name`, right? Yeah, I think that’s the best solution available. Before the migration to GTK4, in my fork I was using `set_icon_name` inside the `ImageProvider` type, as I described in my previous comment. But I guess that now in GTK4 you need to use `Picture` for some types of image sources. So the proper solution would be to create an abstraction like `IconButton` that changes the underlying widget based on the image source, and use that in every widget instead of `Picture` directly. But that has the effect of making the `icon_theme` configuration ineffective, as I mentioned in my previous comment.
Author
Owner

@slowsage commented on GitHub (Nov 19, 2025):

@Rodrigodd, Thanks a lot! Cleared up some things.
The code is now working with icon_theme (tested with "breeze" - horizontal battery icon) but need to clean up. Will submit a pr in a few days. This is pretty core and may be missing something - lmk if any issues jump out.

<!-- gh-comment-id:3550688506 --> @slowsage commented on GitHub (Nov 19, 2025): @Rodrigodd, Thanks a lot! Cleared up some things. The code is now working with `icon_theme` (tested with `"breeze"` - horizontal battery icon) but need to clean up. Will submit a pr in a few days. This is pretty core and may be missing something - lmk if any issues jump out.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
JakeStanger/ironbar#3136
No description provided.