I’ve been experimenting with using the new content interface as a way of handling themes, and have got to a point where other people might find it interesting. The good news is that it looks like the new version of the content interface is sufficient for this use case.
For the experiment, I put together a set of snap packages whose snapcraft.yaml files can be found here:
… and binaries here:
Since there are no store assertions, it is necessary to connect up the content interfaces after installing the snaps:
snap connect gtk3-demo:gtk3-themes ubuntu-themes:gtk3-themes snap connect gtk3-demo:icon-themes ubuntu-themes:icon-themes snap connect gtk3-demo:gtk3-themes adwaita-theme:gtk3-themes snap connect gtk3-demo:icon-themes adwaita-theme:icon-themes snap connect gtk3-demo:gtk3-themes evopop-theme:gtk3-themes
(yes, this is connecting the plugs to multiple slots simultaneously). At this point, the
gtk3-demo snap can use any of the themes provided by the theme snaps. For example, I can launch it with the EvoPop theme:
GTK_THEME=EvoPop snap run gtk3-demo
To get this to work, I use the content interface plugs to populate
$SNAP/share/icons with the data from the themes:
$ snap run --shell gtk3-demo ... $ ls $SNAP/share/themes Adwaita Adwaita-dark Ambiance EvoPop EvoPop-Azure Radiance $ ls $SNAP/share/icons Adwaita Humanity Humanity-Dark ubuntu-mono-dark ubuntu-mono-light
If I install more themes providing the
gtk3-themes slot and connect them up to the app, they will be visible too. This has a few benefits:
- there is no need for application snaps to have knowledge of individual themes: the single plug acts as an extension point for all themes.
- since we can connect all installed theme snaps up at once, we can support multi-user systems where different users have picked different themes. There’s no need to e.g. replug all the interfaces on login.
So where do we go from here?
Good experience for default themes
Without store support, we can’t easily determine which snap provides which themes. However, we could package the default themes of major Linux distros together and make that snap the default provider for the plug on the app.
When snapd gains support for automatically installing snaps required to satisfy content plugs, it would also handle this default themes snap.
This would not preclude the packaging of additional themes as their own snaps: we just wouldn’t have a way to automatically install said snaps. This might not be so bad in the short term, since users will generally need to install additional themes manually anyway.
As you can see in my sample gtk3-demo
snapcraft.yaml file, I had to add extra boilerplate plug definitions to support this. It would be nice to avoid this, since it adds another opportunity to introduce errors.
I think we could improve this with a fairly simple modification to Snapcraft:
slotssections under each part in
- when constructing the
meta/snap.yamlfile, iterate through each part level plug or slot:
- if a plug/slot of the same name doesn’t exist, copy it up to the top level
- if there is an existing definition, perform a deep comparison with the top level version and error out if they differ.
This would make it possible for a cloud part to introduce new plug/slot definitions into projects that use them.
What about Qt apps?
There’s two basic modes that a Qt app can run in:
- use the
libqgtk3.soplatform theme plugin
- use some other platform theme plugin
Case (1) is what you’d normally see when running Qt apps on GTK based desktops (GNOME 3, Unity, Mate, Budgie, etc). Since it defers to the GTK theme, it will work just as well as any GTK app.
Case (2) is what you’d see on a KDE desktop. Instead, the theme is implemented by a shared library that needs to be provided via a Qt plugins directory hierarchy.
If we can share individual files via the content interface, we might be able to present all platform theme shared libraries in a single directory. If not, then we’d probably need to rely on
desktop-launch to construct a
QT_PLUGIN_PATH based on the directories made available by the content interface.