Plasma Wayland and Qt 5.9 and beyond

As you might know Qt 5.8 created challenging problems for our Wayland session and threw our efforts back quite a bit. In this post I want to discuss the actual problems it created, how we are addressing them and looking into the future.

How our integration used to work

Our integration uses additional Wayland protocols. We have a protocol for server side window decorations which we use in our Plasma integration plugin to inform KWin whether the window should have a decoration or not. We have a protocol for client provided shadows which is e.g. used by our widget style Breeze to add shadows to the context menus. We have a protocol for the desktop shell, so that it can mark windows as desktop, panel, auto hiding panel, position the window, etc. Also we have a few protocols for interacting with our effect system, e.g. sliding popups, blur behind.

To use these protocols we need to interact with Qt in a low level way. We use the native interface in the Qt Platform Abstraction to get a wl_surface pointer for the QWindow. In order to not have to keep this simple for our applications our KWayland::Client API provides an API point for it: Surface::fromWindow(QWindow*) -> Surface*.

But when exactly to inject our own integration? We found a very handy way which worked much better than what we had used in the past for X11 (and based on that also transitioned X11 code to use it). Qt emits an event once it has created the native platform surface (in case of Wayland the wl_surface*) for a QWindow. Verbatim quote of the documentation:

The QPlatformSurfaceEvent class is used to notify about native platform surface events.

Platform window events are synchronously sent to windows and offscreen surfaces when their underlying native surfaces are created or are about to be destroyed.

Applications can respond to these events to know when the underlying platform surface exists.

Awesome! We get an event when the surface is created and when it gets destroyed. This made it very simple to create the integration and what is really important for us is that we get this event before the window is shown. So we can prepare everything so that KWin gets a good state.

And the KWin side was to a large part implemented on assumptions on how the sequence will work. We first get the surface, then the (xdg) shell surface, then the integration bits. Sure it would be nice if KWin handled also other sequences, but as the only implementation of this is Qt it doesn’t make sense to really care about it. We know that it was not perfect, we even had the test cases for it, which expect failed.

What broke with Qt 5.8?

In Qt 5.8 our complete integration broke. When the platform surface created event was emitted the wl_surface was not created, see QTBUG 58423. This is in my humble opinion a clear violation of the documented behavior and thus a breakage of the stability guarantees Qt provides, but others might disagree. After some discussion, trying out patches by those who had a Qt 5.8 build we had a patch for Qt which made things mostly work together with a patch to KWin. But at the time we had the patch ready Qt 5.8 was already declared end of life with no prospect of a Qt 5.8.1 bug fix release. For our Wayland session it was just impossible to get Qt 5.8 compatible again. All we could do was to advise distributions to not combine Qt 5.8 with the Wayland session. From our side it was fine for distros to ship Qt 5.8, but if they do they should make it impossible to install the Wayland session. The state was just too broken.

Qt 5.9

With Qt 5.9 the situation looks better. The required patch is merged, it’s an LTS release and we already had the first bug fix release. Qt wants to create more bug fix releases for it and this allows us to use it as a new target for integration. But still the situation is not as good as it used to be. If you currently use our Wayland session with Qt 5.9 you will still see quite some rough corners compared to where we were with Qt 5.7.

The main problem for us is that the platform surface regression was not the only change affecting us. Pre Qt 5.7 a wl_surface lived as long as a QWindow. Now the wl_surface gets destroyed whenever the window gets hidden and a new one created on every show. Unfortunately without a platform surface created event. This means our integration breaks as soon as a window gets hidden. E.g. after closing KRunner the integration for KRunner is broken.

We tried to address this problem in various places, but it is challenging. On the show event we don’t have the wl_surface yet (too early), on the expose event the window is already mapped (too late). This creates problems for KWin which is not prepared for the integration bits to hit when the window is mapped. Our protocols were designed with the platform surface created event semantics. For example in KRunner we face an issue with the integration. KRunner is a panel, which accepts focus and allows windows to go below, also it positions manually. Now when it gets re-shown KWin doesn’t know that this window is supposed to position itself and positions it. Now we get the request to put it as panel, KWin adjusts and moves maximized windows around. And then we get the request that the panel allows windows to go below. KWin shuffles the windows again as the maximized area changed again.

This is a rather tricky situation as we cannot really do something about it. If the window is mapped it’s too late. Even if we improve our API to handle the situation better it will be too late.

There are two possibilities to handle this: Qt stops to destroy the surface or sends a platform surface created event when it recreates the surface. The latter would be my personally preferred solution as this would match the documentation again and allow us to just use the one event handler.

Other regression

The situation around the changed behavior in Qt 5.8 caused a few steps back. Our code needed to be adjusted and that sometimes caused issues. We had a few regressions which also affected the compositor, so the stability of the whole system suffered. These issues are luckily investigated and fixed. But there are still bugs lurking in the system.

For me personally the most annoying bug is a crash in Qt which affects the auto completion of kdevelop. This makes hacking in a Wayland session rather difficult. I’m running currently a patched KWin which disables the virtual keyboard integration to not hit this issue.

A huge problem is that context menus are not marked as transient windows. This means that the Wayland compositor does not know that it is a menu and positions the menu anywhere on the screen. It gives the system a very unfinished touch.

If KRunner is closed through the escape key, the key starts to repeat on the window constantly and due to that it is not possible to open KRunner again. Similar if you start an application in Kickoff through the enter key, when opening Kickoff again it automatically launches the currently selected item. This again makes it very difficult to use the session and gives the whole system an unfinished look. We are working on a workaround for this issue in the server.

Towards the future

Qt 5.9 is here to stay and that’s what we have to use as integration target. Given that Qt 5.9 and Qt 5.7 behave very differently it will become difficult for us to maintain support for both. My suggestion is that we drop support for Qt 5.7 and require Qt 5.9 for the Wayland session. In addition there is hope that we can improve the integration. Marco and David have been working on adding support for XDG Shell unstable v6 which is already supported by Qt and makes it easier to integrate with. Once this landed in KWin Qt will be switched from wl_shell to xdg shell. This will improve the situation for us quite a bit as we then have one code path for both Qt and GTK applications.

How to prevent such regressions in the future

The change of behavior in Qt 5.8 threw our Wayland efforts back a few months. This is something we communicated to Qt quite early and it’s something which worries me a lot. We cannot spend time on changing our integration every time Qt releases a new version. Given that we need to look into how to prevent that such a situation happens again.

I hope that we can improve the integration on the testing front between Qt and KDE. We have a huge test suite which can find regressions in Qt. If Qt would run KDE’s tests during the integration phase Qt would notice regressions before they hit the code base. Given that all our tests are free software it should be possible for Qt to integrate them.

But also the other side would be interesting: if we could get the latest Qt into our CI system we could also discover breakages early. We have now a new docker based CI system which allows running multiple builds of the same change (e.g. Plasma gets build on openSUSE tumbleweed and on FreeBSD) – an image with a daily or weekly Qt snapshot could help us and Qt a lot to detect breakages early.

I also hope in openQA which allows to test the full operating system. This would spot regressions like the misplaced context menus even if KWin’s own auto tests would not spot them (KWin doesn’t care about Qt there, only about the Wayland and X11 protocols). There we might need to invest some work to make sure that KWin/Wayland can be properly run in the openQA tests.

I hope that our Plasma devs can discuss this in more detail with Qt devs during Akademy in person. Unfortunately I cannot be at Akademy this year 🙁 so I cannot discuss in person.

Last but not least it is important that developers test. It would help a lot if the developers working on QtWayland test their changes in a running Plasma Wayland session. We are now overall in a state that the session is suited for hacking on. I do all my Wayland hacking in a Wayland session, experiencing all the glitches like kdevelop crashing.

Of course you might wonder what about us? Shouldn’t we KDE devs also test against the latest Qt? For me personally that is not the case. I’m working on the server side and not on the client side. I’m also not testing the latest GTK for example. Nevertheless I tried to use Qt 5.9 before it got released. Used the installer, spent a day to compile everything on top of it it, just to notice that it doesn’t have QtWayland and won’t get it. I didn’t give up that easily. So I tried to compile QtWayland myself. But when I tried to use it, it turned out to not have any keyboard support, because qtbase was compiled without support for xbkcommon. At that point I gave up. Not having QtWayland is one thing, but not being able to use keyboard is another, it’s rather pointless. The only other option is to compile Qt, but that is hardly an option as it’s really difficult to compile an actually working Qt with all components. The last times I tried, I failed, wasting days compiling. If there were usable weekly images for Qt I would be happy to try it, but of course only with a properly compiled and included QtWayland.

38 Replies to “Plasma Wayland and Qt 5.9 and beyond”

    1. That would be a good idea, except, GTK breaks their own API with *every* release, and intentionally.

      So you wouldn’t see these issues every few releases, but with every single release, and you’d lose fractional HiDPI support (which Qt has, and which is very important with more and more people having different DPI screens).

    2. Here, take a toke. Ok, now we can fantasize about KDE built on top of GTK. Oh, crap. Such a bad trip. Here, have some water. Back to reality.

      1. There are plenty of reasons to switch from Qt to GTK. One is needing cross-platform support: Theoretically there, but good luck actually getting that to work on Qt.

        Then there is licensing: if you’re building some kind of commercial product, GTK really beats Qt on licensing alone as it’s possible to use LGPL.

        Then there’s a 3rd point: If you need a web rendering widget in your code, don’t use Qt or you’ll have a bad time, since QtWebEngine doesn’t allow poking around in the page for whatever reason. So if you need more than “view this, load that” then use something else for your web widget.

        And then there’s a really big pain in the ass: it’s written in C++, which on its own is pretty hostile to interoperability with code written in another language (even if you write a C wrapper you’ll still have a bad time due to Qt having many internal pointers to objects your code ideally might want to own, as well as the many many bugs introduced due to unsafe memory management).

        All this is to day that it’s a minor miracle that Martin can take that gunk called Qt and turn it into something usable, and he deserves high praise for it.

  1. Thank you Martin for the open words and for all your efforts to make it work again.
    I’ve seen most of the issues myself on Arch Linux with testing and kde-testing repos enabled. Yes, it was bad and I was unhappy with Qt’s slow bug fix mentality. But now the latest Qt 5.9.1 and KDE Plasma runs quite well with Wayland and I can use my Desktop for hours unless my computer goes idle for some time, it refuses to wake up… as soon as I know what’s wrong I will report a bug, I guess it’s related to the Mesa graphic drivers.
    I use KDE since many years and I appreciate the hard work to make Wayland work, can’t wait to switch all my machines 🙂

    1. > Thank you Martin for the open words and for all your efforts to make it work again.

      Yes, thanks for your efforts!
      And your blog posts are always a good read with the right level of detail.

  2. Another problem is that very few KDE developers run Plasma Wayland. If we can convince more developers using Wayland as their daily driver, we could probably spot more regressions, and earlier.

  3. Why aren’t Qt developers help out KDE? Isn’t it for their best interest to show how good and versatile their toolkit is?

    “All we could do was to advise distributions to not combine Qt 5.8 with the Wayland session.”
    This never works, only source based distro users can easily control their system. Manjaro, for example jumped to Qt5.8 right away even knowing about the bug. Ubuntu and Debian are always behind fresh releases so they could dodge a bullet once in a while.
    Snap or flatpack the whole KDE that is built with recommended Qt is the best course of action now unless Qt devs will start test their new code against KDE as you suggested.

    1. Hmm, The Gentoo dev’s just put Qt 5.8 behind a big warning – that it would break your system… 🙂

  4. Good read, this explains a lot. Can we expect a similar-to-X11 experience once Qt 5.10 (and corresponding plasma release) is out?

  5. That sounds very much likely like regression than planned changes in Qt. Am I mistaken there?

    Couldn’t that be fixed with a Qt 5.9 bugfix release rather than investing month in working around the issues?

    About integration testing .. ye, that would be great. Maybe they can work something out on Akademy.

    And for building Qt “properly”… ye, distros are doing a great job there. I tried and failed several times building my own Qt, and even the compile/install scripts seem to have a lot of issues. Just looking at packages doing … strange stuff to fit the Qt installer because otherwhise it wouldn’t work is strange.

  6. You can try to use Gentoo in docker to build git versions of qt with single command. If you need docker image with automated build, please let me know by email, then I could prepare it for you.

    1. For me what’s important is to have it in the base system. I must use it properly to see issues. If I run it in a VM/container/whatever I am not using it properly and it doesn’t really help much.

  7. Shamelessly promoting my favorite distribution, but I’m a Gentoo user and compiling qt is simple (thanks to the very active maintainers of the qt overlay).

    The overlay provides not only prereleases but also allows to compile the git version and this with specific useflags, so the problems, you described in the last paragraph, should not appear at all. See here for an example:
    https://github.com/gentoo/qt/tree/master/dev-qt/qtwayland
    https://github.com/gentoo/qt/commit/beb0cf65148908ddbc9753b525f4281d0909ae63

    (The stable packages are in the main Gentoo tree, currently 5.7: https://packages.gentoo.org/packages/dev-qt/qtwayland)

  8. Regarding the test of pre-release of Qt, couldn’t images like Neon/Agron/Krypton in their git unstable version provide “git versions” of Qt as well? That would allow to overcome the hassle of compiling Qt.

    Just my 2 cents, maybe this is stupid.

  9. To build Qt from sources, just check out the qt5 git repo with submodules and build that. I do that all the time. Last time I got a new laptop and did a full clone and build of all qt modules (except qtwebengine and qtwebkit) in less than two hours (those modules take just as long on their own on a laptop CPU). It is not really difficult and most of it builds pretty fast.

    1. Here are the magic commands:

      git clone git://code.qt.io/qt/qt5.git
      cd qt5
      git checkout 5.9
      ./init-repository
      git submodule update –recursive
      mkdir ../build-qt5; cd ../build-qt5
      MAKEFLAGS=-j8 ../qt5/configure -prefix=/opt/qt5 -opensource -confirm-license -release -force-debug-info -separate-debug-info -pch -nomake tests -nomake examples -skip webkit
      nice make -j8
      make -j4 install

      It does take a lot of disk space though, especially if you do a debug build instead especially of webengine. Which is why you keep it in a separate builddir so you can easily delete the entire builddir after installing.

      1. A Qt usable for running kdesrc-build needs both webkit and webengine. And now the fun starts. As I said I have problems compiling a working Qt with all components. Not a subset. And given the two bugs I linked even Qt itself is not able to do that. It neither has all components (no Wayland) nor is it working (no xkbcommon).

        1. xcbcommon is an optional dependency now, you can also have libinput, it should always have one of the two.

          1. On a desktop system it is not optional – your system is utterly defunct if you don’t have xkbcommon. Great it’s compile time optional, but it’s just broken without.

  10. I would suggest to create some kind of explicit plugin API for this kind of integration in QtWayland instead.

    1. This sounds nice in theory but in practice it would be highly problematic as we don’t have any influence over the Qt release model and when the Qt release hits the distribution. We have to expect that Qt 5.9 will be in most distributions for the next few years while only rolling release distros will go to 5.10 or later. Our code needs to work with 5.9 so that is just not a solution.

      Also I think that Plasma specific code doesn’t belong into Qt.

      1. Sure nothing to fix for Qt 5.9 but it will most likely break again going forward in Qt 5.10 or later, so I would still suggest to have some explicit API for the integration bits. It is much easier from Qt side to keep some explicit API stable than some implicit assumptions about order of events and instance creation etc.

        When it is a plugin API there is no need to have Plasma specific code in Qt itself (and there is an explicit way to version plugin APIs if there are changes required).

  11. Have you filed bugs for the Qt beta/release packages not including QtWayland or xkbcommon?

  12. Here’s a link to use to build QT 5 .9.1 base, webengine and webkit (3 pkgs) which gives a total QT5 build w/ wayland.

    http://www.linuxfromscratch.org/blfs/view/systemd/

    Just scroll to X Libs for build steps. Been using LFS for KDE/PL5 since it’s debut. Have enjoyed the work you guys have done for last few years. TY

    archetech on #lfs

  13. Currently can’t use wayland anyway as an amateur photographer I need color managed support (mostly to apply the monitor LUT and to have a way for applications to know which profile they need) but even tough this discussion starts once in a while on the mailing list the CMS people and the Wayland devs can’t seem to get to an agreement on this. So for now X11 is the only option for me 😉

  14. As already mentioned Gentoo has KDE and Qt repository overlays that will allow any developer to build beta, rc or git versions of needed packages.

    btw, since I’m running elogind I don’t know where this issue originates from, but it is impossible to return to plasma-wayland session after switching to text terminal like tty1. I only get black screen on switching back.
    Does this work with systemd-logind?

Comments are closed.