KDecoration2 – The road ahead

Yesterday I blogged about why Breeze is not the default window decoration in KWin 5.0. The blog post touched a little bit the problems with our decoration API. In short: it’s QWidget based and that doesn’t fit our needs any more. It uses a QWidget as an X11 window. At the same time KWin intercepts the rendering and also input handling, redirects it and forwards it. So why use a QWidget at all? Also using a QWidget is quite a memory waste in the Qt5 world. The QWindow behind the QWidget uses a QXcbShmImage with the same size as the window. As explained in yesterdays blog post the window has the size of the managed window plus the decoration. So for a maximized window we hold an image of the size of the complete window while we just need the titlebar strip. We can do better 🙂

Our decoration API is also showing it’s age. It’s cumbersome to use, too difficult to use. In fact there is a KDecoration and a KCommonDecoration – the latter trying to make KDecoration easier to use by for example providing buttons. The API got extended several times to support more features which are all optional. The API is difficult to use from KWin side as it’s not stateful and quite often needs to call into the decoration API calling virtual methods the decoration API provider needs to implement. Last but not least it’s difficult to test new decorations as we don’t have a dedicated viewer application to test the interaction and painting. You have to kind of use KWin as the development host. Not the best solution.

The idea for a new API had been in the room for a long time. I opened a bug report for it more than two years ago. Last week I finally started with the implementation and tackled three things at the same time:

  • New decoration API
  • Viewer application
  • Breeze decoration

In the current state it looks like this:

The outer decoration is the existing Aurorae theme. It looks already quite good, but there is of course still lots of work to do. The API is not yet feature complete, it needs implementation in KWin and Breeze needs a pixel perfectionist to get it right (which I am not). And that’s where you can help! Thanks to our sysadmins we have a new todo board and I requested a project for KDecoration2 and prefilled it with very easy tasks. This is a wonderful opportunity to work on easy and new code and helping both KWin and the Visual Design Group achieving an important new step. Without your help we won’t have this in 5.1 and it would be so important for both KWin and the overall design of the Plasma desktop. So please grab the code and start hacking. Grabbing the code, where? The new decoration API can be found in the git repository kde:kdecoration, the viewer application in git repository kde:kdecoration-viewer and the new Breeze window decoration in git repository kde:breeze in branch “graesslin/kdecoration2”.

So what makes KDecoration2 better? Obviously it’s no longer QWidget or QWindow based. Instead it’s a pure QObject based API. It provides a paint method a plugin needs to implement which gets a QPainter passed into. This allows KWin to control the rendering and to render to the best suited backend for the current compositor (e.g. just a QImage or a Shm shared pixmap). Also the input handling will be controlled from the backend side by sending appropriate events to the decoration. The API takes care of all of the handling – activating the buttons forwarding title bar presses, etc. This alone makes the API hopefully much easier to use from plugin side. It also provides the base implementation for all the required buttons, so that the decoration only needs to provide the painting of the buttons. Simplified the API looks like the following:

There’s an additional singleton DecorationSettings which provides common settings for the decoration. Also there’s an additional second private API which must be implemented by a backend. This will allow us to use KDecoration2 in multiple places. I want to see it uses in KWin, but in future I’d also like to provide our decorations for QtWayland. For this I hope that KDecoration plugins can also be a solution.

14 Replies to “KDecoration2 – The road ahead”

  1. Animations .. looking at the code, it seems that they will be done by the decoration holding a QTimeline / QAbstractAnimation and calling the update(QRect) method at the appropriate ticks. How will kwin manage that? On each frame, check if the decoration is dirty and call a repaint at that point; or an immediate repaint with the blit to screen of the results on the next frame?

    1. The trivial solution is to follow how it currently works: trigger a compositor repaint, check for dirty in the painting pass, update and render to screen. But I want to go further by being inspired by QtQuick and Wayland: move the rendering to a thread and throttle with callbacks from the compositing thread when a frame was rendered.

      1. That was pretty much what I was wondering: were you going to stick with the current method or try something a little more ambitious such as you described. I was hoping for the latter, so that’s some great news to my ears! 🙂 Cheers …

  2. Currently there is only one paint method, which paints both title bar and borders.
    Perhaps it would be better to draw the 4 parts in several calls, so the compositor could render to 4 QImage/pixmaps :
    – no need to fill the middle like currently done in the breeze example
    – smaller memory usage (at least for the pixmap case, for the QImage the compositor could already upload the 4 parts to different textures, or to a texture atlas)

    1. You interpret that the wrong way. It’s up to the backend to decide on how to use the area. E.g. it could call the paint method four times with a different part of a QImage set to the origin and using the clip region to ensure that nothing else gets rendered.

      1. Then the theme should check the clip region for the complex parts to be fully optimized. In Breeze currently paintTitleBar always calls elidedText and drawText, which, unlike simple fillRect, will do some work even it everything happens to be clipped.
        Also, you don’t need to paint the transparent background behind the title bar, just use CompositionMode_Source for the gradient.

    1. I’m sorry about that. It’s an ipv6 address and unfortunately I cannot or didn’t figure out how to change the address used in the mail. I tried disabling the complete email service but apparently failed.

  3. Oh, this is wonderful. I was taking a look at your previous posts about decorations along with some existing decoration themes and, quite frankly, I was intimidated by the sheer amount of code required. To see this work coming along so well so quickly is a big relief, so thank you. This revised approach seems much more logical and straightforward.

  4. Does new api will extend functionality for decorations?
    One of the thing that interest me, will decoration have ability to save user space.
    For example menu integration in header (without shortcut as for now), or app header integration in KDE panel when app is expanded?

    Just asking )

Comments are closed.