Jan Grulich

Qt theming in Fedora Workstation

We have been working on and using custom Qt theming in Fedora Workstation for many years now. By custom Qt theming, I’m talking about the QGnomePlatform and Adwaita-qt projects. If you haven’t heard of them, you can read my recent blog post explaining what they are. While these projects are in some ways better than what Qt upstream has to offer, there were also drawbacks/issues and that’s why I decided to make a final decision and discontinue both projects. The issues are explained in the aforementioned blog post, but one of the main drawbacks is that we are in this development alone and not working directly in the upstream makes it less attractive for other contributors. It’s also not used by default anywhere other than Fedora, so it’s not properly tested by other developers working on Qt applications using different distributions. These reasons led me to submit a Fedora 39 feature to remove our custom Qt theming in Fedora Workstation in favor of Qt’s defaults. The only problem is that if we just go with Qt’s default, we would go backwards a bit. This is because upstream Qt does not provide any decent client-side window decorations (problem #1), and the QGtkTheme in Qt5 (QGnomePlatform equivalent) is a bit behind its Qt6 version with many improvements and integration goodies (problem #2) recently made by Axel Spoerl of the Qt Group, whom I met during this year’s KDE Akademy.

Solution to problem #1

QGnomePlatform used to be our solution to this problem, as QGnomePlatform implemented it’s own version of the QWaylandAbstractDecoration plugin. This was a GTK 3-like decoration plugin that used Adwaita-qt for button rendering and QGnomePlatform bits (e.g. GSettings configuration) to get the titlebar layout. Since we are going to remove QGnomePlatform, we needed an alternative. So I started working on the QAdwaitaDecorations project. This is supposed to be a an intermediate step as I would like to have a proper GNOME/Gtk decorations directly in Qt upstream, but since I was in a hurry to get everything done in time for Fedora 39, we have this for now. QAdwaitaDecorations plugin is based on the decorations we have in QGnomePlatform, but there is no dependency on GTK or Glib (e.g. GSettings) or on Adwaita-qt. We use xdg-desktop-portal to get the titlebar layout and do our own drawing instead. This decoration plugin should also have now a GTK 4-like style so the buttons and colors of the decorations are different.

Below is a screenshot of Wireshark (Qt6) using QAdwaitaDecorations plugin + QGtkTheme + Fusion:

Solution to problem #2

Since Qt5 is no longer actively developed, the only possible solution is to backport all QGtkTheme improvements from Qt6, so I did that + modified some of those changes to avoid breaking binary compatibility. This results in about ~15 related backports to Qt5 so far, and it seems to work pretty well. I also made sure that Fedora 38 and older will still use QGnomePlatform by default, so we don’t change the behavior for existing users. Also, a small change to our QtWayland package was needed to make it use the new decoration plugin by default.

Future plans

As mentioned, I would really like to have everything directly in Qt upstream (talking about QAdwaitaDecorations). That way we get other contributions and thus fixes/improvements for free and a lot more users. Another thing is that QGnomePlatform supports things that are not yet supported/implemented in QGtkTheme, like support for xdg-desktop-portal instead of just relying on GSettings. Not to mention that GTK 4 has been around for a while, and both QGnomePlatform and QGtkTheme are still GTK 3 based. I will definitely try to make some of these things happen for Fedora 40, but knowing myself, it’s better not to make any promises, as things usually don’t go according to plan.

Explained: QGnomePlatform and Adwaita-qt

I decided to write this post to explain everything I can about these two projects. There have been discussions and people demanding these projects should not be used by default in Fedora. As part of this, some issues were raised and it might not be clear which component might be responsible for what. I ended up constantly defending these projects in many discussions and ended up being exhausted by doing so over and over, so take this as an explainer to shed some light.

Brief introduction to QGnomePlatform and Adwaita-qt

To give you some context before I go into details, you can think about Adwaita-qt as the UI representation and QGnomePlatform as the integration between GNOME and Qt. QGnomePlatform applies your GNOME configuration and behavior to Qt apps, together with some integration bits, like dialogs or client-side decorations. Adwaita-qt is responsible for the style of the app itself, including the style of all visible parts (widgets/buttons).

QGnomePlatform

What is QGnomePlatform?

QGnomePlatform is a Qt Platform Theme (part of Qt Platform Abstraction API), where such a plugin is responsible for the app integration into the desktop environment. It is designed to provide integration between Qt apps and the GNOME platform. To explain in an example. Without any platform integration, Qt apps running on GNOME would use default styling and configuration so your fonts, icon theme, dialogs would not fit into the desktop. Also in the case of QGnomePlatform you would not have GNOME-like client-side decorations.

What QGnomePlatform provides?

QGnomePlatform provides the following integration for Qt apps running in GNOME:

  • Font configuration *
  • Icon theme *
  • Cursor size and cursor theme *
  • Static hints (like double-click time, long-press time etc.) *
  • Dialogs:
    • File dialog (both using GTK3 * and native dialog using xdg-desktop-portal)
    • Font dialog using GTK3 *
    • Color dialog using GTK3 *
  • Client-side decorations
  • Support for Settings portal from xdg-desktop-portal settings
    • Unlike the built-in GTK3 theme that can get everything only from GSettings
    • Brings support for light/dark theme switching introduced in GNOME 42
  • Use Adwaita-qt theme by default (elephant in the room) and Adwaita color palette
    • Also provides support for additional themes, like Kvantum
  • Support for Cinnamon desktop

* these can also be provided by built-in GTK3 platform theme in Qt itself (just for comparison what QGnomePlatform does extra)

Issues QGnomePlatform gets wrongly blamed for

Client-side decorations

As stated above, QGnomePlatform provides an implementation of CSD. It’s actually the only Qt CSD implementation I’m aware of, excluding the reference implementation provided by QtWayland, named Bradient. Below is a screenshot comparing QGnomePlatform (left) and Bradient (right).

I saw many times people complaining about missing shadows support and resizing issues. The truth is that officially there was no proper shadows support in the Qt API until I introduced it with Qt 6.2. That’s the reason we don’t have it for Qt5, unless you are a Fedora user, where this support has been backported and enabled in QGnomePlatform build. I also fixed all kinds of CSD related issues in QtWayland.ven though Qt has proper support for shadows in Qt6 now, the reference implementation doesn’t use them.

Misplaced popups/menus

This has nothing to do with Qt platform theme or CSD implementation, because it was actually a bug in QtWayland. Unfortunately this fix is only in Qt 6 and cannot be backported officially to Qt 5 as it would break KDE Plasma. I managed to at least patch QtWayland in Fedora and Flatpak KDE runtime, where I modified this patch to not affect KDE Plasma at all.

What can QGnomePlatform be blamed for?

Forcing Adwaita-qt color palette

QGnomePlatform sets Adwaita-qt color palette to each Qt app so applications can use QPalette API to get access to colors used in the style itself. This can be for example useful when an app creates custom widgets that would not get styled by the QStyle itself. This creates a problem for KDE applications using the KColorScheme API. 

Examples of this issue:

The reason is that KColorScheme and QPalette are out of sync and there might be color roles that are in KColorScheme, but not in QPalette. If an app requests a color from KColorScheme that’s not in QPalette, KColorScheme will default to Breeze style and a color that’s not going to fit the Adwaita-qt style will be provided, causing the app to mix light and dark colors.

Luckily, we have identified a workaround that can be done in QGnomePlatform to avoid this issue. Here is the QGnomePlatform bug with more details.

I think this is the most visible and user-facing issue we currently have and get blamed for so I would like to fix this as soon as possible.

Adwaita-qt

Adwaita-qt is a Qt style for widgets. Qt style is again part of Qt Platform Abstraction. You can think of it as a theme for your application. It’s what changes the visualization of your widgets like buttons, checkboxes etc. and it’s the only thing that changes the appearance of the application itself. For comparison, the screenshot below is Adwaita-qt (light) and the second one is the Qt’s default Fusion style used on Linux used without any QGnomePlatform influence so basically what you would get by default.

I can also add that Adwaita-qt supports HighContrast variants, which are useful for visually impaired people.

What issues can Adwaita-qt be blamed for?

I already mentioned the color mismatch issue which is not really Adwaita-qt’s fault. There are of course issues in Adwaita-qt itself and it’s far from being perfect. The whole style needs a complete overhaul, because the last one was done in 2019 and the Adwaita theme changed a lot recently with GTK4. Another issue is that while the majority of common widgets are styled just fine, there are still some widgets that are rarely used and might have issues with this style.

Another issue is that  apps that customize standard widgets (e.g. through CSS), might get into trouble. Below is a screenshot of Wireshark (pure Qt app) compared to Breeze in KDE.

Another example can be seen in the Black Chocobo app, which uses some customization:

 
Below is Black Chocobo using Fusion style.

Should QGnomePlatform get removed/replaced?

Definitely not. It has many benefits and extras compared to Qt’s default platform and most importantly gives you CSD support. Once I fix the color mismatch issue, there shouldn’t be anything users should complain about. Obviously, this would not be an issue when Breeze is used instead of Adwaita-qt, but still an issue when Fusion is used so it would still need to be addressed. You can see a screenshot below showing Fusion style used in combination with GNOME set to dark theme:

Should Adwaita-qt get removed/replaced?

Maybe. It depends on the alternatives. Obviously using Breeze would get rid of all the widget issues one might experience with Adwaita-qt, however, it is problematic to ship it by default due to bringing dependencies on KDE Frameworks and Plasma breeze style. With the default Fusion style you will also get many widget issues fixed, but you still need to set the color palette through QGnomePlatform in case you want Fusion to be “dark” and fit into the desktop, otherwise you will always end up using the default “light” variant no matter what configuration you set in GNOME.

Conclusion

I hope that this post is useful for those observing issues with Qt apps under GNOME, and will help them to understand which component is responsible for what, as well as the issues involved. In case you are interested and would like to either contribute a patch or report an issue, here are links to QGnomePlatform and Adwaita-qt repositories.

Integration of sandboxed Qt applications

We have been using various tweaks to make sandboxed Qt apps well integrated into the system. For KDE Plasma integration, we have been allowing access to kdeglobals config file, where we store the most common configuration, like used icon theme, widget style, etc. A similar approach has been used by Gnome, where they need to allow access to DConf, otherwise applications will not be able to read default system configuration. These tweaks have been usually set in the runtimes and applications using these runtimes automatically inherited all the needed permissions during the build. This has some weak spots, because changing permissions in the runtime requires all applications to be rebuild to pick up the changes, or applications not using the runtimes at all had to allow all the access themself and really not everyone knows what everything needs to be enabled.

This will change with upcoming release of xdg-desktop-portal (version 1.2), which will bring new portal to solve this problem (for both Flatpak and Snap). There is new “Settings” portal, allowing apps to request various configuration from the sandbox, without need to have access outside (kdeglobals, dconf). For Gnome configuration, this has been built in directly in xdg-desktop-portal so there is no need for specific backend support. For KDE Plasma configuration, we have our specific code reading kdeglobals config file in xdg-desktop-portal-kde. This support has already been merged and will be part of Plasma 5.15 release in February. To make applications automatically ask for this configuration through the portal, instead of reading kdeglobals/dconf, I added support to both widely used Qt QPA plugins. For applications running under Plasma we have now this implemented in plasma-integration plugin. This support will be also released with Plasma 5.15 in february. For Qt apps running in Gnome, I added this support into QGnomePlatform, which has been released already some time ago and is already available in Flathub.

Hopefully with all of this released soon and more widely used, we can slowly start removing all the hardcoded permissions for both dconf and kdeglobals config file in the runtimes.

Gnome integration for Qt based applications in Flatpak

Following blog post from Patrick Griffis about new themes support in Flatpak, we started working on supporting this new feature too. Currently wherever you start a Qt application, it would always look like a KDE application or something would be missing, like icons so you would end up with bad experience and mixed feelings. This is going to change now as we now support Gnome in form of icons, widget style and Qt platform theme and with this, when you run a Qt application in Gnome, it will look definitely better and more natively than before. We packaged regular adwaita icons which are used by default in Gnome as extension of freedesktop runtime. For widget style we use adwaita-qt style, which is a Qt style attempting to look like Gtk’s adwaita and the most important part putting this all together is QGnomePlatform, a Qt platform theme which reads your Gnome configuration and applies it to running Qt applications. QGnomePlatform also enforces Qt apps to use adwaita icons and adwaita-qt style by default so that’s another reason why it is important. Both adwaita-qt and QGnomePlatform projects are by the way authored by Martin Bříza, a collegue of mine from Red Hat so if you meet him in person somewhere buy him a beer for that he cares about Qt integration in Gnome :). Now coming to a question how to install this and make it work. Basically all you need to do is install following extensions and you shold be done:

flatpak install kderuntime org.freedesktop.Platform.Icontheme.Adwaita
flatpak install kderuntime org.kde.KStyle.Adwaita
flatpak install kderuntime org.kde.PlatformTheme.QGnomePlatform

Your Qt apps running in flatpak should then automatically pick up all of these extensions without any further modification, same way it does automatically when you run it outside the sandbox. Simply done!. I’m also aware that there are more Gtk themes, like adwaita-dark or high-contrast, both are also available in form of Qt style and we will probably package them later, but at this point it is mostly proof of concept that this can be done and works nicely. You can follow our wiki page if you want more information about runtimes, repository with applications and so on and from me it’s all for now.

Btw. below you can see okular running in flatpak and using adwaita-qt style with adwaita icons.

Scroll To Top