How would I be able to set custom icons via CSS?
menubutton arrow {
/* -gtk-icon-source: -gtk-icontheme('window-close'); */
-gtk-icon-source: image('close.png');
}
This doesn’t seem to be possible, even though the documentation says “-gtk-icon-source” accepts " Image, builtin
or none
".
Looking up the link, it shows how to use the image()
CSS function, so why doesn’t it work? What’s the correct way of setting a custom icon for GTK?
Say I want to set the X button from the WindowControls to instead be a SVG from Google Material Icons, how would I do that?
Hi,
Looking at the source code, it looks like the WindowControls are not themable by CSS, as they use GtkImage widgets with hardcoded icon names, and as far as i understand GtkImages will override whatever CSS icon is assigned (should have used a simple widget like gtk_builtin_icon instead for this to work).
Looks like you have to:
- create a new icon theme, let’s say “SuperAdwaita”, by copying the folders structure and index.theme from the Adwaita one.
- in the
index.theme
file, inherit from Adwaita:
[Icon Theme]
Name=SuperAdwaita
Inherits=Adwaita
- just add the new “window-close-symbolic” icons in appropriate subfolders, no need to add any other icons.
- set “SuperAdwaita” as your icon theme in the settings.
Side notes:
- in CSS3 “image” is a typedef, for getting an image reference I think you should use “url” instead:
-gtk-icon-source: url("close.png");
- but anyway themed symbolic icons (i.e.
-gtk-icontheme
) should be preferred, because they automatically recolor on dark/light themes.
1 Like
Hello,
Thanks for the reply! Since I’m using gtkrs
, how would I exactly be able to do this?
- set “SuperAdwaita” as your icon theme in the settings.
My guess is if I’m changing the GTK Icon theme to SuperAdwaita
on the system level, it won’t export when I build the project as an executable.
Is there some sort of function that I can use when initializing the window that sets the GTK Icon theme?
Ah, it’s for a single application only, not system-wide?
In this case, no need of CSS or custom icon themes; just name your new icon to window-close-symbolic.svg
and embed it as GResource.
You will need a resource XML file (replace “/org/example/App” by your app-ID):
<gresources>
<gresource prefix="/org/example/App/icons/symbolic/ui">
<file>window-close-symbolic.svg</file>
</gresource>
</gresources>
There is a guide how to embed a GResource with Rust in the doc (the example is for composite templates, but works the same way for icons).
See also the GTK icons doc.
1 Like
Thanks for the reply!
I’ve tried your solution and it worked - but the icon wasn’t found.
My guess is that the icon_name
is invalid, here’s how I set it:
gtk::gio::resources_register_include!("icons.gresource").unwrap();
// [...]
let x = gtk::Button::builder().css_name("tab-close").build();
x.set_icon_name("close");
And here’s how the GResource looks like:
<gresources>
<gresource prefix="/org/a/b/icons/symbolic/ui">
<file>close.svg</file>
</gresource>
</gresources>
I’m curious how the gresource finds the name for the file icon, does it take everything before the .[extension]
? Maybe I’m missing an attribute for the icon name, although looking at the GTK icons docs, my code seems about right.
Here’s the file structure in case it helps!
There is some info in the GtkApplication docs:
GtkApplication
will also automatically setup an icon search path for the default icon theme by appending “icons” to the resource base path.
Not sure what’s wrong here, your example looks correct.
Do you use a GtkApplication for auto-loading? and do you call resources_register_include
before calling the application’s run()
?
Do you use a GtkApplication for auto-loading? and do you call resources_register_include
before calling the application’s run()
?
Yeah, here’s the main function:
fn main() -> glib::ExitCode {
gtk::gio::resources_register_include!("icons.gresource").unwrap();
let app = adw::Application::builder().application_id(APP_ID).build();
app.connect_startup(|_| load_css());
app.connect_activate(build_ui);
app.run()
}
Maybe the last 2 parts of the gresource prefix have a connection to this? Since I haven’t seen them be used anywhere else in the icons docs
<gresource prefix="/org/a/b/icons/
symbolic/ui
">
The icon seems to be set correctly in the GTK inspector, so I have no clue what went wrong either
These subpaths are defined in the default index.theme which is embedded in the libgtk library.
Well, now that I look at it, indeed this “symbolic/ui” subpath isn’t listed there… (I took the subpath based on my local Adwaita icon theme, that may be incorrect…)
When I look into the libgtk resouces, there are actually multiple instances of the window-close-symbolic
icons, in scalable and raster (png) formats. I suspect that when a raster is present, gtk will use it, to avoid expensive SVG conversions. But exactly which resolution will depend on the scaling factor, I think (by 1:1 the 16x16 should be the one used I suppose)
I fear that you’ll have to override all the occurrences of window-close-symbolic
to be sure to always load your version.
There is a debug variable to print infos about how gtk resolves its themed icons, let me recheck…
Found it, it’s
GTK_DEBUG=icontheme
(source)
Well, now that I look at it, indeed this “symbolic/ui” subpath isn’t listed there
That was it!
It works if the prefix is like this:
<gresources>
<gresource prefix="/org/a/b/icons/">
<file>close.svg</file>
</gresource>
</gresources>
I’m gonna try to list all the necessary code for people that run into the same problems.
The Rust source code:
// main.rs
gtk::gio::resources_register_include!("icons.gresource").unwrap();
// build.rs
fn main() {
glib_build_tools::compile_resources(
&["src/resources"],
"src/resources/icons.gresource.xml",
"icons.gresource",
);
}
// whereever you have a GTK widget
variable.set_icon_name("close");
File structure:
One last question - how can I set the icon names for the WindowControls
widget?
I suppose I have to create a new WindowControls
and replace the existing one, then loop through each button and set their icons, but if I recall correctly creating another WindowControls
wasn’t the correct way of doing it.
Assuming the close
icon is already registered in the application, I tried the -gtk-icon-source
CSS property on .close
class, yet nothing changed.
Great news!
Regarding CSS, it’s not possible to use -gtk-icon-source
to change the icon. Only widget that call gtk_css_style_snapshot_icon()
in their snapshot()
can support that, which is not the case of Gtk.Image.
Looping through the WindowControls
and calling set_icon_name()
is a possible solution.
Or create your own widget (a GtkBox respecting the decoration-layout) with custom buttons.
1 Like