How to add icon for window (GTK4 C)

Hello! I have default application with just one window and an icon for this window (Icon for desktop panel). I have to set this icon to my window. I surfed the Internet and found the code below:

static void
activate (GtkApplication* app, gpointer user_data){

	GtkIconTheme *icon_theme;
	icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
	gtk_icon_theme_add_search_path(icon_theme, "rcs/hincolor/apps/48x48");

	if (!gtk_icon_theme_has_icon (icon_theme, "icon")){
		printf("icon error.\n");
	}

	GtkWidget *window;

	window = gtk_application_window_new (app);
	gtk_window_set_title (GTK_WINDOW (window), "Window");
	gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

	gtk_window_present (GTK_WINDOW (window));
}

It runs without errors (it doesn’t write “icon error”) but it doesn’t set the icon I need. What should I do to set an icon to my window?

Hi,

You also need to call one of these:

By the way, for the search path, this should be enough:

gtk_icon_theme_add_search_path(icon_theme, "rcs");

the subpath can be resolved automatically if you rename your folder “hincolor” to “hicolor”.

Last tip: if you embed your icon as GResource, you can then skip adding the icon search path entirely, as long as the resource path matches your application-ID.

Thank you for your response gwillems. I rewrote the code and tried your advice with resource directory. Unfortunately, the application still has no icon. Moreover, use only “rcs” in gtk_icon_theme_add_search_path is not enough even if “hincolor” is renamed “hicolor”.

Maybe PNG format is not supported anymore? Or my picture is broken?

The code I wrote is below:

static void
activate (GtkApplication* app, gpointer user_data){

	GtkIconTheme *icon_theme;
	icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
	gtk_icon_theme_add_search_path(icon_theme, "rcs/hincolor/apps/48x48");

	if (!gtk_icon_theme_has_icon (icon_theme, "icon")){
		printf("icon error.\n");
	}

	GtkWidget *window;

	window = gtk_application_window_new (app);
	gtk_window_set_title (GTK_WINDOW (window), "Window");
	gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
	gtk_window_set_default_icon_name ("icon");

	gtk_window_present (GTK_WINDOW (window));
}

When using the “hicolor” theme, the subpath must match one of those specified in hicolor.index.theme

This works on my side:

gtk_icon_theme_add_search_path(icon_theme, "rcs");

with the icon path:
rcs/hicolor/48x48/apps/icon.png

Hm… it’s pretty strange. I tried it one more time and there is no good result. The code is the same. Maybe compile command is wrong?
gcc `pkg-config --cflags gtk4` *.c -o app `pkg-config --libs gtk4`

Or maybe I should do something with application in the main function?

Code:

static void
activate (GtkApplication* app, gpointer user_data){

	GtkIconTheme *icon_theme;
	icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
	gtk_icon_theme_add_search_path(icon_theme, "rcs");

	if (!gtk_icon_theme_has_icon (icon_theme, "icon")){
		printf("icon error.\n");
	}

	GtkWidget *window;

	window = gtk_application_window_new (app);
	gtk_window_set_title (GTK_WINDOW (window), "Window");
	gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
	gtk_window_set_default_icon_name ("icon");

	gtk_window_present (GTK_WINDOW (window));
}

Well, as it mentioned in GNOME Developer documentation, /usr/share/icons/hicolor/48x48/apps/ (or 256x256 which is strongly encouraged) should be used for application icon.
I have there an icon for gtk-demo so for example it should be enough. I tried:

gtk_icon_theme_add_search_path(icon_theme, "/usr/share/icons/hicolor/256x256/apps");
...
gtk_window_set_icon_name (GTK_WINDOW (window), "gtk3-demo");

But in vain. It doesn’t send any errors but doesn’t show the icon! I’m totally lost here…

The following code works perfectly on my side:

#include <gtk/gtk.h>

static void
on_activate (GtkApplication* app, gpointer user_data)
{
	GtkIconTheme *icon_theme;
	icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
	gtk_icon_theme_add_search_path (icon_theme, "rcs");

	if (!gtk_icon_theme_has_icon (icon_theme, "icon"))
	{
		printf("icon error.\n");
	}

	GtkWidget *window;

	window = gtk_application_window_new (app);
	gtk_window_set_title (GTK_WINDOW (window), "Window");
	gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
	gtk_window_set_default_icon_name ("icon");

	gtk_window_present (GTK_WINDOW (window));
}

int
main (int argc, char *argv[])
{
	GtkApplication *app = gtk_application_new ("com.example.Application", G_APPLICATION_DEFAULT_FLAGS);

	g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);

	return g_application_run (G_APPLICATION (app), argc, argv);
}

Maybe try to run your app with GTK_DEBUG=icontheme to see what’s being done.

1 Like

Hello! I run it with GTK_DEBUG and it shows the icon_name. In the previous code it writes: “gtk3-demo”. Everything is good here (as I see and understand) but the icon isn’t shown :smiling_face_with_tear:
Which parameters I should show?

Maybe there are other ways to pin an icon to application or window? For example, with xml files or something else?

ah, wait… are you running the code under Wayland?

If yes, I heard that wayland can’t use the window’s “icon-name” property, but instead reads the application-ID and looks for an icon with the same name in the system icon paths… or something like this, not sure exactly (I’m not using wayland).

Can wayland users confirm?

1 Like

There are so many combinations wayland/xwayland use and parts on different systems, on some of them starting WAYLAND_DISPLAY= ./app in wayland session is enough to get that icon for GTK4 app with gtk_window_set_icon(), on some other ones - not.

p.s. I believe that icon from .desktop works almost in all cases

1 Like

Under GNOME, the application icon comes from the desktop file:

Your desktop file must match your application id (minus the .desktop extension), so that GNOME can associate your windows to the desktop file, and extract the icon.

If you’re using an X11 session, GNOME can also use the _NET_WM_ICON_NAME and _NET_WM_ICON properties on the window, but those are fallback values, and given the nature of X11 properties, do not produce high quality results.

1 Like

Well, I checked this page and now it’s become much harder (to me) to understand. What was done:
- I renamed icon name (now it’s com.example.Application.png) and moved it into the /usr/share/icons/hicolor/256x256/apps
- I created com.example.Application.desktop file. It’s moved into /usr/share/applications directory.
- Exec is moved into the /usr/bin and /bin directories.

.destop file:

[Desktop Entry]
Name=Example Application
Comment=Example application
Exec=com.example.Application
Icon=com.example.Application
Terminal=false
Type=Application
StartupNotify=true
Categories=Development;GTK;
NoDisplay=true

Results: The application is being displayed in the application grid but with default icon.

I definitely don’t understand something…

UPD: I have Wayland

There is a step forward! I found this: icons from /usr/share/icons/hicolor/... are ignored or something else but it doesn’t work. And .desktop files look for an icon in /var/cache/swcatalog/icons/repo-oss/128x128.
Moreover icons cannot be used if application is not installed. How does it work? I mean I write an application that uses this icon that exists but I can’t use it, strange…
I checked it with icon for GTK Demo and it works. Now we have to understand why icons from /usr/... are ignored, gentlemen.

if I’m not mistaken, caches can be updated with gtk-update-icon-cache(1) and update-desktop-database(1) correspondingly, an application launch tested with gtk-launch(1)

But why do I need to update cache in this situation? What do I really need is upload an icon from /usr/share/icons/hicolor/256x256/apps directory or from local project’s directory with other resources (the last one preferred)

I’m not too much into it. That’s usually properly done at installation by some package manager, or postinst script of used build system for a project.

Have you tried with a SVG icon in /usr/share/icons/hicolor/scalable/apps ?

I don’t know if bitmaps icons are supported by the display server…

This topic is a mess.

The second location is not a thing that even matters, unless the desktop file is literally hardcoding a path.

Named icons for applications—i.e. icons used without an extension, Icon=org.gtk.Demo4—are taken from the icon theme. You are supposed to:

  • install your application’s icon under the hicolor icon theme
  • call gtk-update-icon-cache

Follow the tutorial and the integration guidelines.

The “display server” has nothing to do with this, so please don’t confuse things even further.

Upload where? You don’t “upload” anything.

Once again: the icon of an application in GNOME is determined by the desktop file’s Icon key; your application ID must match the name of the desktop file, so that GNOME can associate a window to the desktop file.

Installing an icon inside the theme requires updating the icon cache at installation time. There are literally thousands of free and open source software applications that conform to this, and you can check their build system to see how that works.

You are getting confused by trying to reverse engineer a system that gives you the code and documentation for what you have to do.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.