Fixing the theming problem with icons and cursors in snaps

This one thing can probably fix a lot of theming problems in snaps, if we can mount the user’s icon and themes folder in the /usr/share/{icons, themes} or by putting these folders in XDG_DATA_DIRS as

/var/lib/snapd/hostfs/usr/share/{icons, themes}

In this way, we have no problem ensuring that there is atleast something that’ll work, i.e bundling a default theme and then, following the user’s theme preferences. Now, what are the possible security issues with read access in these particular folder both in /usr and in $HOME/.local/share

It’d be great if @zyga @kenvandine @jamesh can shred some light on this.

Got some concept working with gnome based app tube-converter. I am using custom cursor and icon theme. I just appended the /var/lib/snapd/hostfs/usr/share to XDG_DATA_DIRS and voila! It works!

So, far, the downside I found

  1. Wasn’t able to make this possible with firefox
  2. Security concerns with these folders being exposed as read-only

Pros:

  1. No extra snap just to have some particular theme
  2. No snap with out of the place theming
  3. Seamless and doesn’t hamper the regular workflow

The apparmor changes needed were only these

/var/lib/snapd/hostfs/usr/share/icons/     r,
/var/lib/snapd/hostfs/usr/share/icons/**   r,
/var/lib/snapd/hostfs/usr/share/themes/    r,
/var/lib/snapd/hostfs/usr/share/themes/**  r,

I added these lines in the desktop interface.

The main reason we decided against this is that there is no guarantee that the theme data on the host system will be compatible with the libraries within the snap’s sandbox.

As a concrete example of this, the Yaru theme for GTK 4 distributed with Ubuntu 24.10 is incompatible with GTK < 4.15.2, since it uses new CSS Color Module Level 5 syntax. If you try to use it with an older GTK (such as GTK 4.14.4 from the gnome-46-2404 snap), the CSS is rejected and the app ends up with default Adwaita theming.

We ended up patching the problem in gtk-common-themes so that snaps could display correctly with the new accent colours:

This isn’t even the first time we’ve encountered this sort of problem. Way back, GTK 3.20 substantially changed it’s theme syntax (essentially renamed all the elements used in the CSS).

Part of the problem here is that we have no idea when these sorts of breakages might occur. If we’re using theme data from the host system, then each distro release could behave slightly different. It’s a much larger testing matrix, and app developers would have no guarantee that their snaps would work on new distro releases.

While there are pain points with are current solution to theming, it does result in more predictable behaviour.

I don’t think that problem will come up, because

  1. Gtk 4 apps aren’t themable at all that way, one needs to copy the gtk4 css file in $HOME/.config/gtk-4/gtk.css which one can easily do already per snap.
  2. KDE apps doesn’t need access to these folders directly, it reads the $HOME/.config/kdeglobals which I already added in this PR

To make it more safe, what we can least do is expose only the icons folder as they don’t need any css. That way, they’ll have a nearly similar theme in all over the system.

GTK 4 apps definitely are themed via CSS. You can see the files under e.g. /usr/share/themes/Yaru/gtk-4.0. Note that most of the data is packaged up in the gtk.gresource file: you can inspect it using the gresource list and gresource extract commands.

If you pointed a core24 snap at this theme data on Ubuntu 24.10 via /var/lib/snapd/hostfs/usr/share/themes, it would mis-render.

Yeah, they’re themed by CSS files, but for a regular user it was never possible to point to a different theme. Even the tweaks app was able to do it only for Gtk 3.

As I’m understanding James, this would break a default Ubuntu 24.10 installation without the users changing any defaults. Users who change configuration can usually be expected to have to work around some issues they may cause themself, but the incompatibility here is with the default config of every (newer) distribution, you’d break more theming than you’d fix because everyone would fall back to Adwaita’s defaults.

No, that’s not at all the case. /var/lib/snapd/hostfs/usr/share would be the last folder in the XDG_DATA_DIRS, thus what the snap is already shipping will be the default. And my main point was icon theming and cursor themes, not at all global themes, which Gnome has already kind of made worse, as a regular user cannot change it.

If what the snap is shipping is default, in what situation would appending it with lower priority work? You’d always search the content snaps first, and always find them, because they’re guaranteed to be there.

(This isn’t me being sarcastic or anything, just trying to understand the concept).

I think this partially solves certain issues e.g mouse cursors but not e.g the full theming components. Mouse cursors are almost always going to be fairly standardised vector/bitmaps right? But the CSS stuff is more complex and what most people think of for theming I feel.

If you see my above post, you’ll see, what I showed and emphasized on the cursor and icon theme, as the rest is already done by me for KDE.

In gnome, you cannot set a custom theme for libadwaita/gtk4 from some GUI frontend and even from terminal. It needs complete manual intervention. Recompiling the css and setting up a new gresource, which is not really something for normal user.

This is where the XDG environment variables come to the picture. Let me explain you, if you set a cursor theme named PhingerCursors, now what Gtk libraries do is, it looks for this icons/PhingerCursors folder in all the folders listed in

XDG_DATA_DIRS=/home/soumyaxubuntu/snap/firefox/5187/.local/share:/home/soumyaxubuntu/snap/firefox/5187:/snap/firefox/5187/data-dir:/snap/firefox/5187/usr/share:/snap/firefox/5187/gnome-platform/usr/share:/usr/share/ubuntu:/usr/share/gnome:/home/soumyaxubuntu/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop

You’ll find this value when you shell into a snap, in this case I shelled into firefox. Here, you see all these folders, and if it can’t find the above said folder, it’ll use a fallback cursor theme, which is most cases Adwaita. Now, let’s say 2 folders contain the same file.

  1. /home/soumyaxubuntu/snap/firefox/5187/.local/share
  2. /usr/share/ubuntu

The moment it finds the name in folder 1 it’ll stop looking for folder 2. The theme files shipped via snaps are in this folder

/snap/firefox/5187/data-dir

So, this will be looked into first, and then the folders which comes after it. This same thing you’ll see when you ship libraries in the snap that are already in the content snap. The libraries in the snap have precedent over the libraries in the content snap, because it goes through the list of these folders

soumyaxubuntu@soumyas-GF63-Thin-11UC:/home/soumyaxubuntu$ env | grep LD_LIBRARY_PATH
LD_LIBRARY_PATH=/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void:/snap/firefox/5187/usr/lib:/snap/firefox/5187/usr/lib/x86_64-linux-gnu:/snap/firefox/5187/gnome-platform/lib/x86_64-linux-gnu:/snap/firefox/5187/gnome-platform/usr/lib/x86_64-linux-gnu:/snap/firefox/5187/gnome-platform/usr/lib:/snap/firefox/5187/gnome-platform/lib:/snap/firefox/5187/gnome-platform/usr/lib/x86_64-linux-gnu/dri:/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl/vdpau:/snap/firefox/5187/gnome-platform/usr/lib/x86_64-linux-gnu/libunity:/snap/firefox/5187/gnome-platform/usr/lib/x86_64-linux-gnu/pulseaudio

You see above? /snap/firefox/5187/usr/lib is coming before /snap/firefox/5187/gnome-platform/usr/lib… that’s why it’s recommended to not ship redundant libraries and cleanup your snap with respect to the content snap.

Isn’t this what Ubuntu has been patching in from 22.04. I.E for Yaru:

With more thought, I feel the title might be a little confusing here. From my perspective what you’re suggesting seems reasonable in relation to custom icons (mouse cursor included). Whereas James’ concerns are also valid but apply to the greater context of theming in general, so this is more, a potential nice win to improve snaps compatibility but not an outright fix to e.g the content snaps themes being mostly the same but slightly different to your host.

That said, I would be mildly concerned with /var/lib/snapd/hostfs/usr/share/themes/ as although most platforms are transitioning to CSS and the like to define style, it’s still possible to find themes in the form of dynamic executable libraries (I remember GTK2 used to, and I’m unsure with KDE but think it still might). Since that location will likely be root owned, it’s probably “safe”, but would there then be concerns if e.g., a dynamic library was compiled for one release but is being run with the ABI of another? Is that common?

I think the first two lines in your AppArmor modification make sense but the second two might need further investigation, assuming they can’t just be dropped and still get your wins in the first post.

No this patch is to get the accent colors work with libadwaita, which didn’t have accent color support until Gnome 47 release. What @jamesh was talking about is this

Which I understand, but, for Gnome in Ubuntu, the theme that’s used by Libadwaita in Yaru and in rest places, everywhere its Adwaita. There are not many themes for Adwaita and neither you can easily just select or change the theme in a click.

You can look more about it from gtk inspector

Which you’ll get when you press Ctrl+Shift+I on a Gtk app (may be try with a snap).

KDE writes the CSS in a config file. It’s in $HOME/.config/kdeglobals and I have already fixed it with these 2

  1. i/b/desktop: add support for kdeglobals by soumyaDghosh · Pull Request #14172 · canonical/snapd · GitHub
  2. extensions/kde-neon-6: fix XDG_CONFIG_DIRS by soumyaDghosh · Pull Request #5104 · canonical/snapcraft · GitHub

For Gnome, well, there is no solution for global theming, for KDE it’s almost done. I think

/var/lib/snapd/hostfs/usr/share/themes/ will mostly help users from mate, cinnamon etc who are still with gtk2, gtk3 etc.

GTK 4 looks up its theme in the same ways as GTK 3 (and GTK 2, for supported windowing systems): XSETTINGS on X11, and GSettings on Wayland.

If your goal is to make a specific theme available for snaps, I would suggest packaging it yourself. An explicit goal was to let people package themes independent of the gtk-common-themes snap. If the user’s theme is not included in gtk-common-themes and there is a matching gtk-theme-* and/or icon-theme-* package available, they will be prompted to install it.

If you do package a theme, you will need to ask for a snap-declaration from the store that allows other snaps to auto-connect to your theme. But otherwise it is relatively simple to build such a snap.

Yes, Gtk does, but libadwaita doesn’t which Gnome is pushing now. Also, we can never confirm that a custom theme has the proper level of css. For example breeze theme in gtk-common-themes so old, that it’s naming conventions have already changed which haven’t taken into account yet.

Also, even though themes needs more discussions, icons and cursor themes can be easily allowed, as they are just normal svg files.

Also, with icons, I have often seen Gnome based snaps doesn’t have all the icons in other DEs, like in KDE

I am using the default Breeze Icon Theme and this should have worked, except it doesn’t, because there is no such theme in gtk-common-themes. Anyways, I still believe that we can atleast have icon themes and cursor themes allowed, and it’ll solve a huge problem. We don’t need any redundant snaps installed, which might or might not be maintained properly, and neither we can snap all those random icon packs available in the internet.

@jamesh I was thinking that instead allow this in experimental flags… or snapd configurations… if users want,

/var/lib/snapd/hostfs/usr/share and $HOME/.local/share will be readable and will be added in $XDG_DATA_DIRS, because currently, there is no way to get things done. As a user, when I am changing themes, I know what I am doing. And the problem is mostly in Gtk. The problem with outdated in the gtk-common-themes too. Specifically with breeze, elementary os themes etc, because they’re not regularly updated and also for a fact that they are version independent. There will always be issues with such cases. I believe that allow system cursors and icons should be allowed by default. And themes should be allowed if the users want, with a prompt or something. Maybe some GUI way like desktop-security-center to manage these options. This actually can be an awesome purpose of that app.