Plugins, plugins, plugins – or how KDE Frameworks learned to Wayland

Several of KDE’s frameworks have windowing system specific code. This means that they need adjustments if they should be run on more than just X11. The frameworks were already adjusted to only call into X11 specific code if they are used on the X11 platform, but a proper Wayland port was still missing.

Over the last weeks I prepared several frameworks to support Wayland in a proper way. Especially I looked at KGlobalAccel, KIdleTime and KWindowSystem. For all three frameworks there is no “generic” Wayland solution available. That is there is no official interface available which could be used. So in order to add support we need to restrict the usage to KWin for the moment. This is especially the case for KGlobalAccel where the aim is to integrate directly into KWin as described in a previous blog post.

For KWindowSystem I wanted to reuse some Plasma-specific interfaces which we had been developing for the Plasma 5.4 release anyway. As those interfaces are part of the KWayland repository it was an obvious idea to reuse KWayland instead of duplicating the code. But using KWayland from a framework – especially a tier 1 framework is not trivial. KWayland is part of Workspace, thus depending on KWayland would create circular project dependencies. Turning KWayland into a framework would adjust the tier for pretty much all frameworks. Clearly neither a good idea.

Thinking about the problem one realizes there is another project with similar problems and they solved it: Qt. QtWayland provides plugins for Qt and by that qtbase itself does not need to depend on Wayland. So for our frameworks plugins can also be a good solution. We can provide plugins which depend on the respective frameworks and KWayland. As KWin would (for the time being) the only compositor to provide the interfaces anyway, it’s not a problem to depend on the KWayland libraries which are part of Workspace.

So as a first step the frameworks got restructured to have their platform dependent code provided by plugins which get loaded at runtime depending on the platform they are run in. In a second step the header files for the plugin interface needed to be installed. This is a requirement for the integration plugins to provide a plugin.

Now as a third step the development of the interfaces was required. This happened in a new repository called kwayland-integration which will see the initial release with Plasma 5.4. So far this repository provides two plugins: one for KIdleTime, one for KWindowSystem.

For KIdleTime I designed a specific Wayland protocol which allows us to get notified when a seat went idle for a specified interval. This is an important feature for many applications, like screen brightness, setting chat to away, etc. Given that I think it’s an interface which might be in general useful and I think it could be a candidate for inclusion in Wayland. This is something I will look into after Akademy when I have more time for it.

KWindowSystem is a little bit more Plasma/KWin specific, so I doubt that we can have anything which is in general useful for all Wayland compositors. KWindowSystem is also on X11 a little bit KWin/Plasma specific, so there is no general difference.

Nevertheless platforms should provide plugins for these frameworks if they want to support frameworks based applications properly. That’s especially a hint to all those distributions who decided to create their own windowing system.

For the long term I think the way to go is to make KWayland part of frameworks (targeting tier 1) and then KWayland-Integration also a framework (current dependencies would aim for tier 2, but also tier 4 could be a reasonable target). This would be especially important if the idle time interface becomes a proper Wayland interface and would be provided by more compositors than just KWin.

More information about the bigger picture of KWayland-Integration and Plasma on Wayland at Akademy next weekend 🙂 We have great Wayland things to show.

Porting a KControl Module to KF5

Over the last days I ported a few KControl Modules (KCM) to frameworks 5. As it’s a rather simple task I decided to document the needed steps. Yesterday I ported over KInfoCenter with all it’s modules:

Aus 2013-10-15

First some preparation tasks. I highly recommend to configure kdevelop to not stop on the first compile error. This helps to find pattern in the errors during the porting and also allows to start with the most easy tasks and not have to start with a difficult one, which might turn out to be a non-issue once the other errors are corrected. I also recommend to have the KDE5PORTING.html from kdelibs-frameworks open in your browser.

Adjust CMakeLists.txt

First of all you need to re-enable the directory containing the KCM in CMakeLists.txt. Then one should do small adjustments in the KCM’s CMakeList.txt.

Drop any kde4_no_enable_final line – that got dropped:

kde4_no_enable_final(foo)

Remove a few definitions to get less compile errors – especially you don’t want a compile error for each cast from const char* to QString:

remove_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_STRICT_ITERATORS -DQT_NO_CAST_FROM_BYTEARRAY -DQT_NO_KEYWORDS)

Search for the target_link_libraries of the KCM and remove all variables with Qt4 and KDE4. Instead just add a few frameworks you can be sure to need:

target_link_libraries(kcm_foo
    KF5::KCMUtils
    KF5::KI18n
    ${KDE4Support_LIBRARIES}
)

This should be enough for getting most of a KCM to compile. Further frameworks should be added once you hit linker errors.

Adjust desktop file

The next step is rather simple. Look for the desktop file of the kcm. Most often called foo.desktop and look for the Exec line and change from kcmshell4 to kcmshell5:

 [Desktop Entry]
Exec=kcmshell5 foo

Common Compile Problems

Now it’s time to start the compile, fix loop till you hit linker errors. I just want to present the most common errors I have hit so far and how to fix them.

Remove QtGui/ from includes

/home/martin/src/kf5/kde-workspace/kcontrol/keys/kglobalshortcutseditor.cpp:37:32: fatal error: QtGui/QStackedWidget: No such file or directory
 #include <QtGui/QStackedWidget>
                                ^
compilation terminated.

This one is rather simple: just remove all QtGui/ or QtCore/ from the #include. There’s also a small helper application in the Qt source tree, but for a small code base it might be easier to just fix manually. Remember to use block selection mode if the includes are all nicely one below the other.

Q_SLOTS

A common problem is that the code uses slots and signals and that should be Q_SLOTS or Q_SIGNALS. A compile error looks like this:

/home/martin/src/kf5/kde-workspace/kcontrol/keys/select_scheme_dialog.h:38:9: error: expected ‘:’ before ‘slots’
 private slots:
         ^
/home/martin/src/kf5/kde-workspace/kcontrol/keys/select_scheme_dialog.h:38:9: error: ‘slots’ does not name a type

Easy to fix: just replace by Q_SLOTS. I recommend to directly recompile after one of those errors as they cause many compile issues.

i18n

In KDELibs4 the include of KLocale was needed for i18n, in KF5 it’s KLocalizedString. So this is bound to fail:

/home/martin/src/kf5/kde-workspace/kcontrol/keys/globalshortcuts.cpp:67:89: error: ‘i18n’ was not declared in this scope
                     i18n("You are about to reset all shortcuts to their default values."),
                                                                                         ^

The fix is really simple. Look for

#include <KLocale>

and replace by

#include <KLocalizedString>

In the uncommon situation that something from KLocale is used you of course need to keep it and add ${KDE4Attic_LIBRARIES} to the target_link_libraries in the CMakeLists.txt. Another possibility is to directly port to QLocale.

KGlobal::config()

In case you get a compile error about missing KGlobal when using KGlobal::config(), do not just add the missing include, but port over to the new way:

KSharedConfig::openConfig();

KComponentData

Each KCM I ported so far failed with the following error in the ctor:

/home/martin/src/kf5/kde-workspace/kcontrol/keys/globalshortcuts.cpp: In constructor ‘GlobalShortcutsModule::GlobalShortcutsModule(QWidget*, const QVariantList&)’:
/home/martin/src/kf5/kde-workspace/kcontrol/keys/globalshortcuts.cpp:37:13: error: ‘componentData’ is not a member of ‘GlobalShortcutsModuleFactory’
  : KCModule(GlobalShortcutsModuleFactory::componentData(), parent, args),
             ^

The solution is again very simple: just drop the call to componentData():

  : KCModule(parent, args)

KAboutData

KAboutData changed in frameworks with the old one being moved to K4AboutData. Luckily the changes are rather simple and a pattern can be used:

  • ki18n -> i18n
  • KLocalizedString() -> QString()
  • 0 -> QString()
  • wrap normal string in QStringLiteral()
    • As an example the old code:

           KAboutData *about =
               new KAboutData(I18N_NOOP("kcmfoo"), 0,
                              ki18n("KDE Foo Module"),
                              0, KLocalizedString(), KAboutData::License_GPL,
                              ki18n("(c) 2013 Bar FooBar, Konqui"));
      
          about->addAuthor(ki18n("Bar FooBar"), KLocalizedString(), "foobar@kde.org");
          about->addAuthor(ki18n("Konqui"), KLocalizedString(), "konqui@kde.org");
      

      becomes:

           KAboutData *about =
              new KAboutData(I18N_NOOP("kcmfoo"), QString(),
                             i18n("KDE Foo Module"),
                             QString(), QString(), KAboutData::License_GPL,
                             i18n("(c) 2013 Bar FooBar, Konqui"));
      
          about->addAuthor(i18n("Bar FooBar"), QString(), QStringLiteral("foobar@kde.org"));
          about->addAuthor(i18n("Konqui"), QString(), QStringLiteral("konqui@kde.org"));
      

      Common other problems

      Usages of KUrl can in most cases just be switched to QUrl and it will work as intended. The same is true for KAction, though if it sets global shortcuts you need to properly port following the steps in the porting guide. A usage of KFileDialog can be changed to QFileDialog – be aware that the order of arguments is different in QFileDialog.

      Linker errors

      If everything went fine you should reach a point where you hit linker errors. Now we need to add the required frameworks to the target link libraries. I try to locate the header file of a class which threw a linker error to get the framework. E.g.

      $ locate kiconloader.h
      /home/martin/src/kf5/kdelibs-frameworks/tier3/kiconthemes/src/kiconloader.h
      

      So the file is part of KIconThemes and thus one needs to add KF5::KIconThemes to target_link_libraries.

      Testing

      Once all linker errors are fixed, install the kcm, and run in your KF5 environment:

      $ kbuildsycoca5
      $ kcmshell5 foo
      

      kcmshell5 is part of kde-runtime. In case you don’t have that one installed you can also use systemsettings for a KCM that is listed there. Otherwise just build kde-runtime.

      And that’s it. Not much work and hardly any code to change.

Next step: running

Last week I reported that KWin compiles and links against Qt 5 and KF 5. This week I’m glad to report that I got KWin also to run. The biggest issue was a PEBKAC – if you try to run anything build against frameworks make sure to not have KDE 4 libraries in your LD_LIBRARY_PATH.

Aus KWin

Before you are tempted to run KWin next in the new Project Neon setup a word of warning: it will dead lock. The current code base I use for testing depends on not yet upstreamed changes in frameworks and Qt. Obviously I have not yet pushed the KWin code needing these library adjustments but without them KWin will hit a dead lock – more to that explained later on.

Project Neon has been a huge help over the last days. Harald reported again and again build issues which we were not able to detect on our system because we also have Qt 4 installed. One example was a file being included which does not exist anymore in KF 5. As it was installed in /usr/include I was not able to detect such a problem, but with a clean setup like Project Neon it becomes immediately obvious.

So what is already working in KWin on 5? The most obviously visible one is the compositor. This doesn’t surprise me much, I didn’t expect any problems there. So far I have mostly tested the XRender compositor as I’m currently mostly working with Xephyr which only provides llvmpipe OpenGL and I rather spent my CPU cycles on compiling than drawing triangles. Since yesterday I have also Oxygen shadows working again which I had initially disabled as it needed XCB porting. But it just looked too strange without them, so I had to enable it 😉 I think Hugo ported Shadows in Oxygen for the same reason.

Related to the compositor is the effect system and our effects. This was rather surprising for me: they just worked out of the box. The only major problem is that global shortcuts are not yet supported so I have problems triggering them. For some effects I solved this problem by just adding a DBus interface – might be an idea to keep this; some users might appreciate it. Only the scripted effects were not loaded because I did one mistake during the initial porting – this is fixed since today as you can see by the dialog parent effect being applied in the screen shot above.

Also window decorations work, though there is still quite some work to be done. For example the QML based Aurorae does not like to work which is the reason why I ported Oxygen over. It’s overall nice to see that it works, but it seems to be only working with compositing enabled. Not so surprising as this hits areas which changed a lot inside Qt.

The window manager seems also to be working, though obviously I have not tested all features and are using only a minimal sub set of the available functionality. Due to missing global shortcuts support it’s difficult to test all features and due to missing port of the configuration interfaces I cannot even adjust the configuration (well I could just edit the config file, but…).

Nevertheless there are still quite some issues which need investigation and fixing before I can start to consider using KWin 5 in production. The biggest problem at the moment is that all windows present at startup get unmapped and are kind of lost to the window manager. So far I have not yet been able to figure out why this is happening. That is for example a show stopper if you would want to use it in a neon setup. (Update: This issue is fixed as of 3bddd1100aa)

The biggest change for KWin is the port of the event filter from XLib to XCB and this is still causing some headaches to me. With XLib one was able to look into the future by inspecting the XEvent queue or to the extreme wait till a specific event has arrived. With XCB the event queue doesn’t allow to be inspected which makes porting properly a non-trivial task. KWin was using this functionality at three places (at least that’s what I found so far). During move/resize operations we only process the last mouse motion event currently in the event queue to limit the resizes. This functionality should be possible to emulate with a more async event handling approach. The second usage is that we do not deactivate a window on focus out event if there is also a focus in event following. The documentation says this is to prevent flickering. In a composited world it doesn’t really matter as the compositor should prevent the flicker, but also here a more async approach should be able to handle it.

The big problem though is the third usage: updating the current xTime. KWin needs to have the most recent X time to be able to properly compare timestamps. This is done by changing a property and waiting for the event which contains the timestamp. In addition KWin does some more tricks like looking at the first event in the queue containing a timestamp, to get it really correct. Now with XCB event queue not being available to us this is a sever issue as without this functionality KWin doesn’t function properly. While looking at how to solve the problem I discovered that the XCB QPA internally uses a method providing this functionality of getting a current timestamp. Not with all the bells and whistles as we used to have in KWin, but good enough for a start. So my solution at the moment is to have my local Qt copy to make this function available and by that solve the problem. That’s the change I talked about in the beginning of this blog post.

As you can see there has been quite some progress and I hope to get KWin in a dogfoodable state quite soon. And that’s something where you can help. There are many easy tasks available which just need you to be able to compile KWin and with Project Neon this just became easier. So drop by the Trello board and claim your task. This week I was already able to push one first time KDE commit with a small cleanup for our code base 🙂 So who wants to be next?

Help porting KWin to Frameworks 5

With Akademy behind me and the situation about “what is master” in kde-workspace resolved I decided to switch my work away from Wayland towards getting KWin on top of Qt 5 and KDE Frameworks 5. After a few days of hacking the compilation of KWin is re-enabled in the frameworks-scratch branch of the kde-workspace git repository.

This means that KWin compiles, links and installs when compiling against KF5. A quite important step and only very few code areas got ifdefed. The preparation work of the last months showed it values as for example the compile errors due to QPixmap were extremely easy to resolve (just delete the code) without loss in functionality.

But of course at the moment KWin does not work yet when compiled against KF5 as the event filter is not yet ported to xcb. This is what I will focus on next so that we can soon start testing a KWin on 5 and start to adjust the areas which need to be tested against a running KWin, where “ship it, it compiles” is not enough.

Of course getting KWin to KF5 is still a long road and we need help for this. There are many, many tasks which are rather easy and do not need a working KWin. It’s just a matter of changing for example KPushButton into QPushButton and verify that it still compiles. This means that right now is a perfect time to get started with KWin hacking.

And obviously I started to prepare for that and created a wiki page for KWin on Frameworks. I plan to update this page whenever new information becomes available like how to run KWin on 5. Most important I created a Trello board listing the tasks which can be done to help the porting. I will add tasks as I notice them. So if you want to get involved, just ping me, tell me your trello username and I’ll add you to the board and start hacking. If you look at the list you will notice that some tasks are really simple. Let’s rock to get KWin working on Qt 5 as fast as possible to get an awesome next release.

An update on KWin on 5

I realized I haven’t written a blog post to highlight the latest changes in KWin for quite some time. The reason for this is that we currently are mostly focused on getting KWin to work on Qt 5/KDE Frameworks 5. As I have mentioned already in the past KWin is a little bit special in the transition to Qt 5 as we used the low level native, non-portable functions provided by Qt (last week I found one usage of a native function which is not even documented). For us it mostly means that we transit from XLib to XCB and remove code which uses methods which got removed or replaced.

Although that means that we hardly have any new features there are quite some improvements all over KWin. Having to touch the code anyway allows us to also rethink how we tackle a problem.

For example we use Plasma functionality at a few places. The code got added before QtQuick existed so it uses QGraphicsView. With libplasma2 the QGraphicsView support is going to be removed which means we need to adjust our code. Over the last years some areas in KWin already made the transition from Plasma styled QGraphicsView to QtQuick, such as our Window Switcher or the Desktop Change OSD. But some areas remained: the close button in Present Windows and the add/remove desktop button in Desktop Grid. Here we have now a nice improvement ready for 4.11: these elements got rewritten in QML and they look way better now.

Aus KWin

For comparison just do Ctrl+F8 or Click here.

This was AFAIK the last bits of UI in KWin which hasn’t done the transition to QML yet. By using QML for all of our UIs the code becomes much easier to maintain, easier for users to improve it, easier to style it. The last point is really important for KWin adjustments for non-Plasma environments like Razor-Qt. Though they use a fair bit of Plasma styling already and with KF5 libplasma2 will be so small that it hardly matters 😉

The screenshot also shows another new improvement thanks to the transition to XCB. In the left upper corner a glow is shown when approaching the corner with the mouse cursor. If you use auto-hiding Plasma panels you already know this glow. This change became possible because the screen edge related code was one of our strongest user of XLib and a refactoring was needed anyway to support the world after X. The new design follows an approach which will make it easy to add support for a new windowing system – even if I do not know how exactly that will look like in a Wayland world (currently Qt5 is the highest priority). Also we plan to make KWin take care of the screen edges needed for the Plasma Panel. This removes quite some duplicated functionality from Plasma and solves the general “problem” that Plasma cannot listen to just all mouse events in a Wayland world.

One of the areas which has seen most adjustment so far is our XRender based compositor. It was a heavy user of the QPixmap/X pixmap relationship and needed to change. I still consider XRender as an important part of our compositing offering and therefore decided to do the porting. Interestingly the porting did also bring improvements to our OpenGL compositors. Again the reason is that we had to rethink. Our decoration rendering code used the QPixmap/X Pixmap relationship from the time when KWin only supported the native Qt graphicssystem. When we did the transition to raster the code did not get adjusted to the new world and that’s why we for example recommended the native graphicssystem for XRender. With the native system going away we just had to make it better and the improvements made for XRender benefit the OpenGL compositor in the same way. With Qt 5 I hope that we can get some further improvements for the QtQuick based window decorations. I was running KWin on XRender with raster and Plastik-QML as window decoration and was positively surprised: I couldn’t notice a difference in the speed compared to the OpenGL backend.

So how far are we with the transition to Qt 5? Last week I did a test compile against Qt 5 and KF 5. I hit a few issues but got it compiled. Apart from the known low-level issues (we still need some of the functions for Qt 4’s native graphicssystem) I only hit one compile issue with Qt 5 – given the source base that’s really a great job by the Trolls! In KF 5 I hit a few more issues – also because it’s not yet meant to be used. Well it doesn’t bother me much, I fixed the issues and started to integrate them either in KWin or in KF5.

But when it’s not yet supposed to be used, why am I investing time into it? The reason is the event filter. We need to transit our event filter from XLib to XCB and that’s something we can only test once we are running against Qt 5. I have some code prepared which at least compiles, though I know that it doesn’t cover everything and needs to be changed. I plan to give it a try over the next day, just to see how much breaks. But that’s the reason why we are doing it right now to have enough time till we do the final transition.