Open probonopd opened 7 years ago
Are you sure?
Icons are searched in XDG_DATA_DIRS
, there is no DATA_HOME
currently in use to my knowledge.
And since the home directory is in the default list of XDG paths, dropping an icon into ~/.local/share/icons/hicolor/<size>/apps/
will just work.
I am not aware of any desktop which doesn't implement that, and it definitely works on both GNOME and KDE.
Are you sure?
Tested with kubuntu-16.04-desktop-amd64.iso
and neon-useredition-20160901-1018-amd64.iso
, I get consistent, reproducible behavior:
$HOME/.icons
and $HOME/.local/share/applications/
qtcreatoricon.png
in $HOME/.icons
qtcreator.desktop
in $HOME/.local/share/applications/
The results are:
Icon=/home/me/.icons/qtcreatoricon.png
-> icon is shown on the desktop file and in the menuIcon=qtcreatoricon.png
-> icon is NOT shown on the desktop file and in the menuIcon=qtcreatoricon
-> icon is NOT shown on the desktop file and in the menu (works in Ubuntu Unity, Ubuntu MATE, Xubuntu, elementary OS, etc. but not in KDE Plasma)So @ximion how do you read the spec, is KDE Plasma spec compliant or is it violating the spec?
The default ENV is:
$ env | grep XDG
XDG_VTNR=7
XDG_SESSION_ID=3
XDG_SESSION_CLASS=user
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session2
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
XDG_CONFIG_DIRS=/etc/xdg/xdg-/usr/share/xsessions/plasma:/etc/xdg:/usr/share/kubuntu-default-settings/kf5-settings
XDG_SESSION_TYPE=x11
XDG_SEAT=seat0
XDG_SESSION_DESKTOP=KDE
XDG_DATA_DIRS=/usr/share//usr/share/xsessions/plasma:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
XDG_RUNTIME_DIR=/run/user/999
XDG_CURRENT_DESKTOP=KDE
An a workaround, I can put in the absolute path as the value for the Icon=
key for now but I would like to avoid that if possible.
Yeah, but .icons
is a non-standard path almost nobody supports.
Put your icons into ~/.local/share/icons/hicolor/<size>/apps/
which is the canonical location.
If the icons don't show up, the XDG_DATA_DIRS variable would need another entry for the current user (easy enough to set, Flatpak sets a custom location too).
@ximion thanks, ~/.local/share/icons/hicolor/<size>/apps/
would work of course, but what do I do for icons which I don't know the size for? (e.g., stuff coming from usr/share/pixmaps
)?
@probonopd I would not support them - share/pixmaps is bad for various reasons. If you do want some level of support, you could determine the size of the images and then place them correctly named in the right directory.
Sigh. it works everywhere but KDE...
$HOME/.icons
is legacy and should die. Use $XDG_DATA_DIRS/icons
(~/.local/share/icons/hicolor/<size>/apps/
) and you should be fine. The latter works everywhere and is what everyone, including proprietary stuff, uses.
Looks like /home/me/.local/share/icons/hicolor/scalable/apps/appimagekit_f9178380f3005f0de7f4ca115e454e9e_openscad.png
is not recognized in Ubuntu but copying it to /home/me/.local/share/icons/
does the trick for Ubuntu :-/ Why can't all distros just agree on one place where to put icons of which I don't know the size, or are in a non-standard size.
@probonopd The ~/.local/share/icons/hicolor
directory is the standard - you just need to use it correctly. Putting .png (= pixmaps, non-scalable) icons into scalable/apps
is not okay (it can work, but there are no guarantees). See /usr/share/icons/hicolor/index.theme
on how the directories are defined. Further information can be found in the XDG icon theme spec.
So, determine the size of the pixmap and place it in ~/.local/share/icons/hicolor/<size>/apps/<pixmap>.png
and you should be fine. Of course, the .desktop file's icon name must contain the icon name (without .svg/.png suffix!) in its Icon=
entry.
The system needs to know the size without opening up the icon file for speed reasons, and we need the different sizes to provide UIs which scale on different form factors and display sizes as well as different places (e.g. menus vs desktop-icons). There is no way around doing it right ;-) Just determine the icon size at appimage build or install time and do the right thing (also ensure that the icon size falls into one of the icon sizes supported by the hicolor theme). Or make people provide an svg icon and put it into the scalable location.
OK, so it looks like I really have to parse the images and determine their size. One way to do this is
// sudo apt install libcairo-dev
// gcc getsize.c -I/usr/include/cairo/ -lcairo -o getsize
// or
// gcc getsize.c $(pkg-config --libs --cflags cairo) -o getsize
#include <cairo.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
cairo_surface_t *image;
image = cairo_image_surface_create_from_png(argv[1]);
int w = cairo_image_surface_get_width (image);
int h = cairo_image_surface_get_height (image);
fprintf(stderr, "w = %i\n", w);
fprintf(stderr, "h = %i\n", h);
cairo_surface_destroy (image);
return 0;
}
But now the question arises, what do I do with icons that do not fit into the usual suspect sizes like 48x48, 64x64, 128x128, and so on.
$ ./getsize /home/me/.icons/appimagekit_99af24415f947efc83d8203d60a92c2e_graphmonkey.png
w = 61
h = 52
Do I really have to resize them first in order for the desktop environment to be able to display them?
Also, can I be sure to find these sizes on every system?
$ ls /usr/share/icons/hicolor/
1024x1024 22x22 42x42 8x8 symbolic
128x128 24x24 48x48 96x96
16x16 256x256 512x512 icon-theme.cache
192x192 32x32 64x64 index.theme
20x20 36x36 72x72 scalable
grep apps /usr/share/icons/hicolor/index.theme | grep x | cut -d x -f 1 | cut -d "[" -f 2 | sort -n | uniq
Directories=16
16
22
24
32
36
48
64
72
96
128
192
256
512
Probably not... so this is really messy...
So for now I will probably go with something like this:
// sudo apt install libcairo-dev
// gcc getsize.c $(pkg-config --libs --cflags cairo) $(pkg-config --libs --cflags glib-2.0) -o getsize
#include <cairo.h>
#include <stdio.h>
#include <glib.h>
gchar* determine_icon_destination (gchar *icon_path)
{
gchar *dest_dir;
if((g_str_has_suffix (icon_path, ".svg")) || (g_str_has_suffix (icon_path, ".svgz"))) {
dest_dir = g_build_path("/", g_get_user_data_dir(), "/icons/hicolor/scalable/apps", NULL);
}
if((g_str_has_suffix (icon_path, ".png")) || (g_str_has_suffix (icon_path, ".xpm"))) {
cairo_surface_t *image;
if(g_str_has_suffix (icon_path, ".xpm")) {
// TODO: GdkPixbuf has a convenient way to load XPM data. Then you can call
// gdk_cairo_set_source_pixbuf() to transfer the data to a Cairo surface.
fprintf(stderr, "XPM size parsing not yet implemented\n");
return NULL;
}
if(g_str_has_suffix (icon_path, ".png")) {
image = cairo_image_surface_create_from_png(icon_path);
}
int w = cairo_image_surface_get_width (image);
int h = cairo_image_surface_get_height (image);
// FIXME: The following sizes are taken from the hicolor icon theme.
// Probably the right thing to do would be to figure out at runtime which icon sizes are allowable.
// Or could we put our own index.theme into .local/share/icons/ and have it observed?
if((w != h) || ((w != 16) && (w != 24) && (w != 32) && (w != 36) && (w != 48) && (w != 64) && (w != 72) && (w != 96) && (w != 128) && (w != 192) && (w != 256) && (w != 512))){
fprintf(stderr, "%s has nonstandard size w = %i, h = %i; please fix it\n", icon_path, w, h);
return NULL;
}
cairo_surface_destroy (image);
dest_dir = g_build_path("/", g_get_user_data_dir(), "/icons/hicolor/", g_strdup_printf("%ix%i", w, h), "/apps", NULL);
}
return(dest_dir);
}
int main (int argc, char *argv[])
{
gchar *dest_dir = NULL;
dest_dir = determine_icon_destination(argv[1]);
fprintf(stderr, "dest_dir = %s\n", dest_dir);
return 0;
}
But now the question arises, what do I do with icons that do not fit into the usual suspect sizes like 48x48, 64x64, 128x128, and so on.
That's a bug in the application which should be resolved by the software authors.
Do I really have to resize them first in order for the desktop environment to be able to display them?
Would be ideal, but you could also place them in the size-directory that is the best match. Would be quite ugly, but the DEs will display an icon then (and maybe stretch and distort the image when displaying it, so picking the right size would really be better).
Also, can I be sure to find these sizes on every system?
Yes. That's why we have a standard for it. Having the hicolor theme with the current set of sizes is guaranteed on every DE following the XDG spec (which is, as far as I know, every DE).
So for now I will probably go with something like this: [...]
Looks okay :)
Thanks @ximion I am going this route now.
Please move this to tge appimaged repo
With the current implementation, the menu icons work without issues on Kubuntu 18.10.
I also went ahead and tested other KDE based distributions and it also works without issues on them:
I also went ahead and tested other KDE based distributions and it also works without issues on them:
* KDE Neon user edition 18.04
I am using the most up-to-date version of KDE Neon and it does not work with several appimages (Cryptomator, Jetbrains Toolbox, KeePassXC and many others). https://i.imgur.com/yTMgfq8.jpg
May well be KDE related since it seems to work in Xfce, tested with https://dl.bintray.com/cryptomator/cryptomator/1.4.9/cryptomator-1.4.9-x86_64.AppImage and https://github.com/keepassxreboot/keepassxc/releases/download/2.4.1/KeePassXC-2.4.1-x86_64.AppImage:
The Icon Theme Specification actually does not specify
$XDG_DATA_HOME
as a source for icons, hence applications in userspace do not have a standard way to place their icons. Although Ubuntu Unity, XFCE, and other desktops do pick icons up from there, but KDE Plasma doesn't.https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
@ximion, am I reading the XDG spec correctly, and do you think we should propose a change? https://bugreports.qt.io/browse/QTBUG-48417
This seems to be a 12-year old issue: https://lists.freedesktop.org/archives/xdg/2004-September/003280.html
In the KDE Plasma GUI there is no notion of per-user icons either: http://askubuntu.com/questions/788386/how-to-add-icons-on-the-kde-menu-editor-icon-source
In addition, KDE Plasma seems to ignore icons in
$HOME/.icons
.Effectively leaving no way for an user-space application like appimaged to install icons for applications.