Proposal: support the icon theme spec for desktop icons

One issue that has come up recently among the folks working on Ubuntu’s icon theme is the poor appearance of the icons for snapped applications, and the inability to work around it (e.g. Gnome snaps in 19.04, 19.04 dailies: logs and system-monitor are suddenly upsteam Gnome icons).

These issues stem from the constraints snapd places on the desktop files provided by snaps. With no way to define new named icons, the only reliable way to structure the .desktop file is to use a path for the Icon key. There are two main problems with this:

  1. icons specified by path rather than icon name can not be overridden by the user’s chosen icon theme.
  2. icons specified by path can only be represented by a single image file.

While the first may not be particularly desirable for things outside of standard desktop tools (e.g. calculator, character map, etc), the second is likely to be generally useful. For example, while the .snap version of Firefox references a single 128x128 icon in its .desktop file, the .deb version references an icon name :

/usr/share/icons/hicolor/16x16/apps/firefox.png
/usr/share/icons/hicolor/32x32/apps/firefox.png
/usr/share/icons/hicolor/48x48/apps/firefox.png
/usr/share/icons/hicolor/64x64/apps/firefox.png
/usr/share/icons/hicolor/128x128/apps/firefox.png
/usr/share/icons/hicolor/symbolic/apps/firefox-symbolic.svg

The image appropriate to the size it will be rendered is used as the icon. The last is a GNOME extension to cover special monochrome icons that can be rendered in a theme-appropriate colour.

Even when using SVG icons, it may be desirable to provide multiple size versions: a small icon may remove detail and vary stroke thickness to ensure lines are visible at the smaller size.

So it would be useful for snap applications to do something similar to make named icons available to the host system. if we can also do it in a way that would work for a hypothetical snapped desktop, all the better. Below is a proposal for how this could look.

Directory Layout

According to the icon theme spec, an icon theme can be composed of multiple directories spread out over $XDG_DATA_DIRS, so it shouldn’t be necessary to write to /usr/share/icons to make icons available.

We already add /var/lib/snapd/desktop to $XDG_DATA_DIRS, so dropping icons in /var/lib/snapd/desktop/icons should make them visible to any conformant implementation. I propose that snapd copy files from the $SNAP/meta/icons directory to corresponding directories in /var/lib/snapd/desktop. So if the Firefox snap contained the following file:

$SNAP/meta/icons/hicolor/128x128/apps/firefox.png

… on installation that file would be copied to:

/var/lib/snapd/desktop/icons/hicolor/128x128/apps/firefox.png

Icon Theme Layout

The contents of an icon theme directory are not strongly specified: instead, the index.theme file describes a set of subdirectories and the types of icons they contain. This means that /usr/share/icons/hicolor/index.theme will also describe how to interpret the contents of /var/lib/snapd/desktop/icons/hicolor.

I think there are two ways we could handle this:

  1. try to find the index.theme for the icon theme, and verify that the snap is providing icons only in those directories for the theme.

  2. allow the snap to provide icons in any directory that looks like it could be an icon theme subdir. Perhaps requiring 1 to 3 ASCII components would be a reasonable check.

I’m leaning towards (2), since a snap could provide a custom icon for a theme that doesn’t exist on the host system, and that shouldn’t be an error. As we are not installing any index.theme files, this should just result in the icons being ignored.

What icon names should a snap be allowed to provide?

If Firefox installs a named icon, and references it in it’s .desktop file, we do not want other snaps to also provide images for that icon name. We probably also don’t want snaps overriding the icons for random applications on the host system. So we probably want to namespace the icon names a snap can provide. One option would be to only allow snaps to provide icons matching snap.${SNAP_NAME}.*. The snap. prefix ensures we don’t conflict with host system icon names, and ${SNAP_NAME} prevents squatting on other snaps’ icon names.

It’s not ideal, but it might be a good place to start. The main complaints I can see are:

  1. it’s not going to pick up existing icon overrides. For example, Ubuntu’s Yaru theme provides Yaru/256x256/apps/org.gnome.Calculator.png as a custom icon for gnome-calculator. Under this scheme, the gnome-calculator snap can not use this icon name. As Yaru is Ubuntu’s theme, it could probably provide a symlink to the snap icon name to work around this, but it might be hard to convince other theme authors to do the same.

  2. If we want snaps to be able to provide mime type icons (e.g. LibreOffice providing icons for its document formats), those icon names are named after the mime type with the slash replaced with a dash. So requiring the snap. prefix is a problem here. Perhaps this can be set aside until we look at how snaps can register new mime types.

Parallel installed snap instances

If the user installs a snap twice, there’s no guarantee that the two instances will provide the same icons (e.g. one instance on stable, the other instance on edge). This probably means we’d need the following:

  1. rewrite icon file names to use the correct instance name when copying over to the shared icon theme tree.
  2. rewrite the Icon field in any .desktop files that happen to specify an icon name to reference the correct instance.
6 Likes

For flatpaks they expect the application id, which is the appstream id, which is e.g. org.gnome.Calculator to be used as prefix for exported icons.

http://docs.flatpak.org/en/latest/manifests.html#file-renaming

I think from a theming POV it’d be handy if the names were actually the same for both flatpaks and snaps. To that end you I don’t think the snap prefix is needed at all. As you mention parallel installed instances of the same snap need mangling of the file name and Icon entry anyway, so you may just always disambiguate names.

snapfoo: installs org.gnome.calculator as icon

  • want to install icon file
  • no icons of that name installed yet
  • install icons as org.gnome.calculator-1
  • update the desktop file to change the Icon entry accordingly

snapbar: installs org.gnome.calculator too

  • want to install icon file
  • icon already installed by one snap
  • install icons as org.gnome.calculator-2
  • update the desktop file to change the Icon entry accordingly

This would smartly make use of the icon naming spec

The dash “-” character is used to separate levels of specificity in icon names, for all contexts other than MimeTypes. For instance, we use “input-mouse” as the generic item for all mouse devices, and we use “input-mouse-usb” for a USB mouse device. However, if the more specific item does not exist in the current theme, and does exist in a parent theme, the generic icon from the current theme is preferred, in order to keep consistent style.

That means theming will actually work consistently across all effected desktop files. Say my system uses Breeze as icon theme and going back to the example:

snapfoo.desktop has Icon=org.gnome.calculator-1 :arrow_right: icon resolver will attempt to find an icon of the name org.gnome.calculator-1 :arrow_right: won’t find one in breeze :arrow_right: will drop the last dash-part :arrow_right: resolver now looking for org.gnome.calculator :arrow_right: happens to be available in breeze :arrow_right: breeze icon for gnome calculator is used

If breeze has no icon for org.gnome.calculator the dash-parts are exhausted and the parent theme hicolor would get searched. There it would find org.gnome.calculator-1 and use that.

IOW: iff N snaps install the same icon name, they will get themed the same so long as the system theme has an option for the icon. If the system theme has no icon they’d use the provided stock icon of the snap (which may or may not be the same).

2 Likes

The icon naming spec seems to explicitly rule that out:

The “Applications” context should not use this method of falling back to more generic icons. An application must either use a generic application icon name provided by this specification, or install an icon named the same as the executable for running the application.

As far as using names like org.gnome.Calculator directly, I agree that it would be useful at some point: icon theme names are just one use case. We currently have a common-id field in snapcraft.yaml (intended to hold an AppStream ID), but it is essentially just self asserted info at this point rather than representing a unique namespace.

There’s nothing stopping me from publishing a package which claims the same common-id as an existing snap, and there’s nothing in snapd to prevent installing two snaps with the same common-id.

Uh, the more you know.

To be honest I think one could just install the desktop file icon in another icon context. I don’t think any of the specs says desktop file Icon entries need resolution against the apps context. In fact, I am almost certain there’s KDE software that is being lazy and uses icons from different contexts in lieu of a proper application icon.
It does sound a bit iffy, but then the spec hasn’t really considered the same application being installed more than once.

This looks fine to me assuming that we indeed start only allowing snap.${SNAP_NAME}.* icon names. To allow other kind of names we would need mechanism similar to aliases to grant ownership to global names.

@jdstrand any comments on this from your part?

1 Like

I’ve got a rough implementation of this proposal here:

It is enough to handle basic install/removal of snaps providing icons. I think I can get it to handle parallel installs with a few simple modifications. There are a few other todo items I’ve identified in the PR.

1 Like