Reasonable DPI in Plasma Next

We are currently looking into how we can improve Plasma (but in extension also other applications, including QWidget-based ones) on hardware that sports unusually high DPI (also called “reasonable DPI”). In this article, I’ll outline the problem space and explain our tools to improve support for high DPI devices in Plasma.

First, let’s take a step back, however, to explain the problem space to those who haven’t yet spent that much thinking on this. Most of today’s desktops and laptops have have roughly the same amount of pixels per square inch of screen space. The amount of pixels per inch is measured in DPI (dots per inch) or PPI (pixels per inch). This value is around 100 DPI for laptops. Tablets and smartphones are already available with much higher DPI screens, making for sharper fonts and overall higher fidelity graphics. A while ago, Apple has started producing laptops with high DPI displays as well, these are the so-called Retina screens. There are Macbooks on the market with 220 DPI.

Test Plasmoid showing a scaled UI
Test Plasmoid showing a scaled UI

Some people have complained for years about the low DPI value of screens available on the market (and I am one of them), higher DPI simply allows for nicer looks, and reduces the need for “dirty tricks” such as subpixel rendering algorithms (which come with their own set of problems). Graphics chips also have become fast enough (and with enough memory) to not have a problem with high resolutions (think 4K on your laptop, for example).

I’ve done some research (Well, lazy-webbing, mostly), and it seems that higher DPI screens for desktop systems, but also for laptops are still quite rare, and when you find one, they’re often really, really expensive. I believe this is caused by two reasons: production-line quality is not always good enough to produce high DPI screens, one could say that the more pixels there are on a given device, the higher the chance that one or more of them are dead, making the display unsellable, and thus increasing the price of the ones that are pixel-perfect. Also, tablets and smartphones, which often already sport high DPI screens are currently taking up almost all of the production capacity. The obvious result is scarcity and a high price. I believe it’s only a matter of time until high DPI displays become more common, however. A few friends of mine already have high DPI displays, so there is a real need to support this kind of screen well.

Battery Widget without icon scaling
Battery Widget without icon scaling

So what’s the problem? Many applications assume a fixed DPI size, or at least that the DPI value of the screen is within a certain range, so that when you render an icon at 22 pixels, it will look like a small icon, compared to text, and that its details are visible. Also, icons and sizing of fonts are loosely related, so an icon that is way smaller than the size of the text as rendered will look weird and cause layouting problems. (Imagine huge letters and cut off text, for example.)
For graphical elements, this is a real problem, but less so for text. Today’s text rendering engines (Freetype, for example) take the DPI value of the screen into account. This means that this at least partly solves our problem. Luckily, it solves the problem for very complex cases, so at least this is not of great concern. It’s only a partial solution, however, so this at best eases finding a complete solution. We need to fix these problems in different areas, and all need to have well-thought out solutions.

Limitations in X11

The bad news is that this problem is only partly solvable in an X11 world. X11 has no real concept of different DPI values per screen. This is not so much a problem for single screen systems — we just use the DPI of the only screen. As soon as you attach a second screen that has a different DPI, this is going to be a problem, and it’s not possible to solve this completely in an X11 world. We’re planning to first make it work in a single DPI environment, and then work towards supporting different DPI values per screen. (Of course we’ll keep multi-DPI-screens in mind, so that we don’t have to take too many steps back once we are actually in a position to be able to support this. This means Wayland, basically.)

Battery Widget using icon scaling
Battery Widget using icon scaling

Cheating with fonts

A pretty easy, yet neat solution is to use font metrics to compute sensible dimensions for graphical elements on the screen. The very short version is to stop thinking in numbers of pixels, and to start thinking in lines of text and with of characters as they end up on the screen. This is not a pure solution to the DPI problem, which in many cases is actually an advantage. The size (for example height) of a given letter rendered on the screen depends on a number of properties:

  • The DPI value of the screen which is used to render the text
  • The font size setting
  • The size of the font itself, as it is designed (this is usually more relevant for the aspect ratio between width and height)

This means that taking the font height as rendered, we actually can compute values for sizing elements that not only take the low-level technical properties of the hardware into account, but also user preferences (or system presets). In Plasma 2, we started using this mechanism in a number of places, and so far we’re pretty happy with the results. Some examples which where we use this is the sizing of popups coming out of the panel (for the notification area and the calendar for example), but also the sizing of the icons in the notification area (or system tray). This means instead of hardcoding pixel sizes, these UI elements grow and shrink depending on your settings. This solves a part of the problem, but is obviously not a complete solution. If you would like to implement this mechanism, here’s two snippets of code, which, with some necessary adaption, you can use to make your app work well on High DPI devices.

in Qt C++ code:

const int fontHeight = QFontMetrics(QApplication::font()).boundingRect("M").size().height();

This gives you the height of the letter “M” as it would be rendered on the screen. It’s a useful mechanism to get you a pixelsize that is dependent on the DPI value of the screen. Note that you want to use an int here, in order to not end up aligning UI elements at half pixels, as this leads to blurriness in your UI.)

We’ve bridged this API in the Plasma Theme class, which is available from QML applications by importing org.kde.plasma.core (the global property theme will be automatically set, which allows you easy access to Plasma::Theme from everywhere, in case you’re wondering where the “theme” variable is coming from).

import org.kde.plasma.core 2.0 as PlasmaCore

/* Paint an orange rectangle on the screen that scales with DPI 
   This example makes the rect big enough to paint about 8 rows
   of text (minus spacing), and allows for a column with of about 
   60 characters. Mileage varies on fonts used, and the text 
   itself, so this is an approximation.
 */
Rectangle {
    width: theme.mSize(theme.defaultFont).height * 8
    height: theme.mSize(theme.defaultFont).width * 60
    anchors.margins: units.largeSpacing

    Item {
        anchors.fill: parent
        /* ... more stuff ... */
    }
}

In the second example, you see that we’re using another property, “units.largeSpacing” for the margins. This is another piece of DPI-dependent UI which you can use to apply margins and spacing that take DPI (actually font-as-rendered-settings) into account.
To get the size of a piece of text on the screen, in QtQuick code, you can use the paintedWidth property of a Text elements, but not that this can be tricky due to text elision, line breaks, etc., so this is to be dealt with with care.

Icons and other graphical elements

Another interesting case which affects the usability of our graphcal interfaces on high-DPI screens is the sizing of icons. We are using standard sizes there, which you access via properties “units.iconSizes.small”, “units.iconSizes.large”, etc.. In Plasma, these sizes now get interpolated with the DPI value of the screen, while making sure the icons are still getting rendered correctly. The sizing is done in steps, and not linearly to avoid getting washed-out icons. This mechanism works well and automatically solves another piece of the puzzle. The result of doing this is a more balanced look and better alignment and spacing across some widgets (notably the battery gains quite a bit of beauty with this treatment).
In other UI elements, especially the toolkitty widgets we provide in PlasmaComponents, we often already scale with the text, which works just fine for reasonably-but-not-excessively high DPI values. We have done some experiments with scaling up the graphical elements that are used to, for example, render a button. As we are using SVG graphics throughout the user interface, we don’t have to resolve to dirty tricks such as doubling pixels, and we can get quite neat results. This needs some more work, and it hasn’t been merged into master yet.

The Higher-Level Picture

Now, having discussed lots of technical details, how does the user-facing side of this look and work? The changes we’ve done right now only affect the user in one way: More UI elements scale with the DPI of the screen, this means no change for displays around 100 DPI. On my laptop (which has a 180 DPI screen), this gives a more balanced picture.
As Plasma is making its way onto a wider range of target devices (think tablets, media centers, as well as high-dpi laptops or monitors), this topic becomes increasinly important. I have good hopes that we will be able to solve this problem in a way that really leverages the power of this kind of hardware. In Plasma Next, we’re now providing some of the basic tools to make UIs work well on high-DPI displays, and we’ll continue this route further on. The user will notice that in Plasma Next, most of the problems that could be seen on high DPI screen are gone, and that the whole behaves much better without many tricks.

Plasma and a new beginning

The Plasma team is meeting in Barcelona, Spain these days to work on the next major version of KDE’s popular workspaces. As we are in a transition period, technically and organisationally, this is a very important meeting. I won’t go into too many details in this post, as they are still being fleshed out, but to give you an idea what we are talking about, here’s a quick run-down of some of the things we talked about.

Process & Transpareny

We do not have firm technical results, we are sharing the proposals we come up with here in the meeting on the Plasma mailinglist for feedback first. This is a change we are making in our development and decision-making process. In the past, we sometimes got the feedback that the Plasma team as a group appears a bit too exclusive to the outside. This stands in contrast to its architectural position. One of the things that make it very interesting to work on Plasma is the scope. This scope is usually work on the workspace UI, and of a specific technology. User interfaces don’t stand on themselves, but they express something and allow access. Examples are hardware integration, where issues like powermanagement, device management, etc. have to be presented in the workspace in a way that first of all makes sense technically, but that also is consistent with the way other “things” are presented, and that is beautiful and engaging with the user, while getting out of the way of doing real work. This is a thin line to walk, and in order to achieve great results, it needs close involvement from all sides.

Related to this is the transparency in decision-making processes. Some people have complained that decisions have been made inside a tight group, and that they don’t feel to be part of this process. This stands in the way of team growth (and no growth means shrinking), making it hard to maintain a high level of quality on the one hand, and on the other hand to improve existing functionality and develop new features. We want to change this. Of course this must not stand in the way of firm direction, but the responsibility has to be shared by more people, meaning that not one person is seen as responsible for more controversial changes, but we as a team stand behind it. This reduces stress on individuals, and leads to a fairer distribution of also the negative sides of responsibility.

Social environment

Lately, we’ve been struggling with an unwelcoming atmosphere in the Plasma communication channels. We’ve talked about this issue, and everybody present agreed that in order to keep our working environment pleasant, we have to be more friendly and respectful to each other. It’s totally not acceptable to lash out against each other, or to answer emails in condescending ways, to talk to people assuming they’ve bad intentions or anything like that. We need to rebuild some mutual trust, but we also need to step in when things threaten to escalate. As an in-person meeting is a good opportunity to talk about these issues in person, this was an important topic. My personal feeling is that we have reestablished strong standards, and everybody is on the same page and willing to defend this newly found balance. We all share the same goals, and we want our working environment to be friendly and enjoyable, as this forms the baseline for being productive and achieving great results as a team.

Drinking from the firehose

Finally, another topic was the situation of Plasma issues in KDE’s Bugzilla. We have a lot of bugs, and are currently lacking the resources to handle this stream of incoming bugs. We do need to do something about this, since it’s an important tool for support and to increase the quality of our codebase, and in extension the user experience. This means that we will, for the technological transitions deprecate a number of bugs of which we know fairly certainly that they do not apply in Plasma 2 anymore. We’ll also draw clearer boundaries around components supported by the core team (essential functionality), and community-supported addons. This means that we will be able to categorize and prioritize better, and hopefully get a grip on the rather messy situation in our issue tracker. Right now, trying to make sense of the issue reports for Plasma very much feels like this:

Visual Guidelines

On the design side, we’ve started on visual guidelines. This is a tool for us to achieve greater beauty and consistency across the components. Plasma 1 feels, in some places, like a collection of individual, separate components. This is of course true, and it has specifically and purposefully designed like that — it’s a good thing technically, but the architecture should not bleed into the visual appearance. We’ve done a lot of work to ensure visual consistency in our components, and we’d like to take this to the next level. For this reason, we’ve worked on visual design guidelines. We’ve taken the new Plasma calendar as a starting point, since that resonated very well with the community, and with professional designers, and we started to extract guidelines that are commonly applicable also to other parts. This is about usage of fonts, spacing and alignment. On the technical side of this, Digia’s Mitch Curtis, who works on the calendar components in QtQuick Components has joined us for a day of design, planning and hacking, so we have some really nice collaboration going on there as well.

Responsible Evolution

Plasma Desktop running on top of Qt 5 and KDE Frameworks 5
Plasma Desktop running on top of Qt 5 and KDE Frameworks 5

Exciting times. I am working on the lower-right corner of the desktop right now, and thought I could give a quick visual update of progress there, as well as some sense of direction where we’re heading, how the user interface evolves, Plasma’s new architecture, and underlying software stack and the device spectrum. A whole mouthful, so grab a cup of tea.

Two areas in particular are catching my attention these days, the notification area (“system tray”, that row of icons which show you the status of all kinds of things), and the clock with its calendar popup. The calendar shows quite nicely some things we want to pay attention to in Plasma 2: consistency and elegance. We are making more use of pronounced typography, are fixing alignment problems, and are looking for a generally more elegant way of presenting the common functionality. In that, the plan is not to make a lot of changes to the functionality itself, not cutting down the UI, but polishing what is already there. By reducing the workspace’s mental friction for the user makes the tools take a step back and give more room to the content and interaction that is presented. Doing that, the workspace should be functional, yet elegant. The migration should feel like an upgrade of something familiar. We want to make it functionality-wise equivalent, but more polished. On top of that, we’re readying the technology for future use cases, and evolution of the underlying technology stack.

Calender popping up from the Plasma panel
Calender popping up from the Plasma panel

QtQuick 2 actually makes these things a lot easier, as it is much more correct in terms of calculating font metrics reliably, which we need to (sub-)pixel-perfectly align text and other UI elements. Trying to make this exact in Qt4 and on top of QGraphicsView was a shortcut into madness. Ever so slightly off font metrics, and wonky layouts get you to tear your hair out pretty quicky. This is much better now, (though certainly not perfect in all areas), so it allows us to finally fix these jarring little mis-alignments that nag the eye. The calendar already does it pretty well, and serves as a nice example. This implementation takes the physical size of the pixel on the screen into account by correcting for DPI in the whole layout, so it works nicely on all resolutions and pixel densities. With higher pixel-density displays, the rendering gets more details, fonts look neater, but the size of interaction areas, and the effective size on the screen don’t change much. The screenshots have been taken on a 170 DPI display, so if the fonts seem huge on your display (or small, as I hope for you), this would be the reason for that.

Battery Monitor
Battery Monitor

In the notification area, you might notice that the widgets that have been living in there are now contained in the same popup. This results in less window management and layering of small popups in the notification area, clearer navigation and a cleaner look. The currently active icon has slightly pronounced visuals compared to the others.
The calendar will of course show information about tasks and agenda (this part doesn’t work yet). One neat thing which the new architecture allowed use to do very easily is lazy-loading the calendar. As just loading the calendar can result in quite a bit of loading underneath, delaying to loading it on-demand speeds up start-up time and lowers memory consumption in a lot of cases.

Below the surface, the changes are more radical. Qt5 and with it the move to QtQuick 2, the scenegraph-based successor to QtQuick 1, a new QML and javascript engine which is smaller and more optimized for Qt data types and conventions than V8, new sandboxing features, being able to render and composite pretty much entirely on the graphics card, share textures between compositor and workspace shell, addition of Wayland as a fully supported target platform, and along with all that new input and security features.

Network ManagementNetwork Management in the notification area
Network Management in the notification area

Plasma 2 is a converging user interface. It allows to control the Look and Feel at different levels. On the lower level / higher detail side of the scale, we look at adjusting input areas, sizing of ui elements, and interaction schemes by swapping out and “overriding” parts of the UI toolkit with, for example, touch friendly versions of widgets. On a higher level, we support laying out the furniture of the workspace (think of alt+tab window switcher, log in, lock, etc. features) by more code sharing and a different logic to how they’re loaded (and swapped out). Plasma shell allows dynamic switching of shell layouts at run-time. The shell is equipped to morph between workspace presentations, so should your tablet suddenly get a keyboard and mouse plugged in, it changes its disguise to a traditional (actually your own customized) desktop layout. While this is cool, in reverse, it allows us to isolate changes that are done to suit other devices from the “Desktop Experience”. Just because the workspace support multiple devices, the user doesn’t get the lowest common denominator, but specialization. Different devices are different for a reason, and so should the UI be. “Mobile-friendly” shouldn’t mean “misses features”, but “responsibly designed” (excuse the pun).

Our tricks allow to use the same system on a range of devices, with the user interface adopting to specialties of hardware it runs on, such as input, display, but also usage scenarios specific that device. Much like the Linux kernel, which “mostly figures out how to run properly in a device it’s booted on”, and which can be configured as small and as big as one wants, the user-interface uses “UI plugins” at different layers, and detects changes and adopts to the form factor. You use a media center “driver” if you want to use it on the TV in your living room, you use a tablet “driver” on your tablet on the go, you use desktop driver on the laptop, and you can switch the device’s UI when needed. Laptop or tablet + HDMI cable ~= media center, isn’t it?

Klipper manager showing the clipboard's content
Clipboard interaction

You see, many different construction sites. We’re working a lot on all these things and you should definitely consider joining. Nothing is set in stone yet, and you should consider the imagery functional mock-ups, rather than the final thing. It’s not perfect and lacking in all kinds of places, it even crashes in some and what is presented is just a snapshot of work in progress. Many details remain to be hashed out. Still, I’m running Plasma 2 about half of the time on my laptop now. It’s just about to be becoming usable and almost dogfoodable for more than just a very small handful of people with an elevated pain threshold and a debugger at hand.

“When?”, I hear you ask. We’re aiming at a stable, end-user ready release of the new Desktop shell in summer 2014, at the end of Q2. On of the next milestones will be a tech-preview, which is planned for mid-December, so just about a month away from today. From December, where we’ll reach the point of having the basic functionality in place, we’ll spend time on filling in the missing bits, making sure everything runs on Wayland, and on polishing and quality improvements. Integrating additional workspaces, such as Plasma Active and Plasma MediaCenter are also next year’s roadmap. These will become the tablet, resp. media center drivers.

Plasma Next: What’s changing?

In the past week, we hit something that really feels like a milestone in Plasma development. Plasma 2 has become somewhat usable, at least if your pain level is high enough. It occurred to me after I realized after a few hours of using it that the workspace shell running on my laptop was not actually the current stable release of Plasma, but the development version. Great thing, I thought, went ahead and fixed a sizing bug in the systemtray widget, then changed the default layout to include Kickoff, Taskmanager and Systemtray in the panel, as these elements are the most important ones to have in the panel — exposure even to just our development team surely won’t hurt. This experience also marks a point where we have to take a step back and look at our general direction. Sure, we could do a “minimal port” and just make everything build and work on top of Qt5.

I can hack on Plasma2 using Plasma2!
I can hack on Plasma2 using Plasma2!

One of the technologies we’ve been using more and more in the Plasma workspaces is QtQuick, a declarative language that allows you to very easily write stunning UIs, without the need to use C++ for these parts. Our experience is that it makes developing, improving and maintaining applications a lot easier, and generally leads to much nicer user interfaces. QtQuick, being a very young technology in Qt4, has matured since then, and received a major technology update in Qt5. It moved from a traditional painter-based mechanism to a scenegraph model, and much closer onto the graphics hardware. That means that we usually get much better performance out of it, and that it allows a whole bunch of neat tricks on top of that. In Qt 5.2 (which is the Qt release we’re basing our work on), it received another big upgrade. The scenegraph renderer has been replaced, with huge performance gain as the result. (Read Gunnar’s article about it, it’s really impressive!) QtQuick also received a new QML engine, which brings major improvements to its internal data handling, but also to important topics such as maintainability. The new v4 engine uses Qt types internally, so a lot less marshalling is needed between runtime objects, and some architectural barriers have also been removed. Lars has written an excellent article about the new QML engine.

So on a technological level, we have decided to not do this. We want a more modular software stack underneath, so we decided to rework the KDE Development Platform into something that is more useful in its pieces. The result of that (the process isn’t finished yet, but rapture lines are becoming very visible) is KDE Frameworks 5, a modular set of Qt-based libraries with well-defined dependencies which separately are all very useful to 3rd party developers, and combined give you all the functionality to build highly integrated complex applications on top. Plasma next builds on Frameworks 5. In the past 1.5 years, we have spent a lot of time on reworking the build system and removing interdependencies between various “sublibraries” that made up kdelibs. This has progressed really well, we are in fact able to build and use many of our libraries standalone already. We’re currently restructuring the last libraries to accommodate a split, and will then “physically” split the libs into separate repositories. In order to not make the effort to build a KDE application or workspace explode, we have developed tooling that can build sets of modules for you. You get to choose the granularity we work with. In order to make it easier for third parties to find and use our libraries, we have set up Inqlude.org, which has information about these (and other) libraries. This is very much work in progress, but it does already give a good picture of what’s to come.

For the user, we want to keep this whole process as smooth as possible. Porting applications to Frameworks 5 is rather easy, as regarding kdelibs, it mostly involves changes to the build system, some mild Qt5 porting, and only a few API changes. It is nowhere nearly as disruptive as the move from KDE3 to KDE4 (yes, our software was still called KDE${N} back then!).
In Plasma, it’s a little more complicated, as much more changed under the hood (a completely new way to get graphics onto the screen, deprecation of larger parts of our API, more device-independence reflected in our architecture). Our goal for the first release is to not introduce functional regressions however. We want to keep the basic usecases of a Desktop fully working, preferably noticeably improved. In the past years, we have already moved a lot of the individual components (such as the task manager, widgets for battery, network management, etc.) that make up our workspace to QML, this pays off now as those things are rather easy to port, and give a very mature impression right off the bat. We do realize that we have some cleaning up to do, and now is a good time to do this. We want to introduce a greater degree of consistency across the workspace experience. Technically, this can be achieved by more and smarter sharing of code, so common UI patterns become more, well, common. Plasma’s design language will be more pronounced, and at the same time, easier to change to your liking. More on that in another article, however.

As it currently looks like, we will release a first technology preview of both, Frameworks 5 libraries and Plasma Next in December. This won’t be a complete thing by any means, but a way to check on and gauge progress. At the same time, you’ll get to have a good look at Plasma Next, which, while building on the new technology stack, will resemble our current offering quite a bit still. It is much more a technology preview, than a user experience preview. So don’t judge too early, rather, get your hacking shoes on and join the fun. :)

Reconstructing Plasma

Desktop Workspace with Widgets Explorer
Desktop Workspace with Widgets Explorer
We are currently in the process of porting bits and pieces that make up Plasma Desktop to QtQuick2, KDE Frameworks 5 and Plasma 2. In this endeavour, we are going over all the basic components, such as Kickoff, the task manager, the pager, the system tray, battery and network management widgets, and of course the clock. We are also porting other workspace components such as the powermanagement policy daemon (powerdevil), the KDE Daemon (kded) and the splash screen.

For Plasma components, this work involves first porting C++ portions of the code to Qt5 and adjusting the build-system to build this code against Qt5 and Frameworks 5 libraries, which have been split up. C++ code has to be moved into imports, which can then be used from QML code.
Configuration dialogs in Plasma 2 are something, we have redesigned. As all other UI code, the configuration dialogs seen in Plasma are also moving to QML. In Plasma 1, the configuration is done using traditional widgets. This made it hard for developers to provide complex configuration user interfaces without having to write these portions in C++. In Qt 5.1, QtQuick Controls have arrived, and are further polished in Qt 5.2. QtQuick controls are traditional widgets, done in QML instead of hand-written C++ layouts or Qt Designer .ui files. They reuse the widget styling engine (the Oxygen style, for example), but you can write these in QML. This allows us to keep the user experience. Plasmoids in Plasma 2 now use QtQuick, and get the full possibilities along with that.

Desktop settings and Toolbox
Desktop settings and Toolbox

Over the past years, we have already moved most of the standard elements of a Plasma workspace to QML, which greatly simplifies porting. To the user, this will not feel like a rewrite, but like an update of the user experience.
In many ways, Plasma 2 will be very similar to what is known today, and that’s a good thing. Familiar interfaces that have been developed and polished over the years provide great value, we definitely want to keep the work that has gone into that, but we also want to elevate its possibilities going forward to a new level. While going over the code, we often improve things here and there, so it’s not just a “stupid port” but provides actual value to the user. From a UI point of view, we expect Plasma 2 to be an evolutionary release, which, while keeping existing workflows intact gives us greater flexibility in how the system is set up, and used. The move to Plasma 2 means that we can improve on things that have been nagging us architecturally, so we can get rid of some accumulated baggage. Then, there is of course Wayland, which we aim at fully supporting in Plasma 2.

Notifications
Notifications
In the screenshots, you can see a few of our widgets that make up the desktop, just to give you an idea of what is there right now. Some elements have just seen straight ports (the network management and battery widgets, for example), others are in the process of being reimplemented. One of the things that we will likely improve it the layout of the widgets explorer, which you can see in the first screenshot. The horizontal list does not work very well in practice (in theory it really does! ;-)), as it is harder for a human brain to scan a horizontal list, compared to a vertical one.

When looking at the screenshots, keep in mind that this is all very much work in progress, and that almost all the work has been done on the underlying architecture (KDE Frameworks 4 and the Plasma Framework), and that we are only now starting to shift towards more UI-oriented work. For that purpose, we will have a meeting on IRC later this week to hash out further strategies and take the pieces we have now to make it One. More on that, however, later.

As an exercise to the reader, what improvements and bugs and missing things can you notice? :)

Kickoff Launcher
Kickoff Launcher
Network Mangement
Network Mangement
Battery Monitor
Battery Monitor
Notification Area a.k.a System Tray
Notification Area a.k.a System Tray

Plasma 2 Snapshot Demo

For those interested in the progress of KDE Frameworks 5 and Plasma 2, I’ve recorded a demo video which shows a few aspects of the current state of development of the upcoming version of your favourite Desktop.

The demo video shows the new Plasma shell running, including a panel with the task manager. It shows a demo applet doing some OpenGL tricks. The Kwin window manager and compositor is running in its Qt5 / Frameworks 5 incarnation, and there’s konsole, which has also already been ported to Frameworks 5.

Of course, all the usual warnings apply: This is a very early state of development, many things are missing, unstable or do not perform well yet. There’s also a fair bit of user interface cleanup and streamlining to be expected.

We are just about to enter a state where the desktop becomes dogfoodable, so we can use it ourselves regularly and find and iron out all kinds of bugs. The good news is of course that this is the perfect time to get involved. While we’re not looking quite at the blank canvas that Plasma was when it came to be, right now we really are shaping the future of Plasma, you can take part in it and make it happen. We’ve compiled a list of tasks for Plasma 2 that need to be tackled. There’s of course also a lot of work still to be done for KDE Frameworks 5: many tasks, big and small are longing for attention. If there’s something interesting in there for you, or if you would like to see it happen more quickly, jump in! If you’re interested, in the release plans for all this new goodness, I recommend reading this article on KDE’s Dot. Rumours say that there’s an interesting follow-up article planned, so stay tuned!

If you want to give it a spin, you can build the whole thing from our git repositories, or use the Kubuntu Neon 5 packages to set up a test system.

KDE Frameworks 5: Plugin Factory Guts

In this article, I explain changes to the plugin loading mechanism in KDE Frameworks 5. The article is intended for a technical audience with some affinity to KDE development.

Over the past weeks, I’ve spent some time reworking the plugin system in KDE Frameworks 5. The original issue I started with is that we are shifting from a plugin system that is mostly KDE specific to making more use of Qt’s native plugin system. Qt’s plugin system has changed in a few ways that caused many of our more complex plugins to not work anymore. On the other side, moving closer to Qt’s plugins makes our code easier to use from a wider range of applications and reduces dependencies for those that just want to do plugin loading (or extending their app with plugins). A mostly complete, and I must say spiffy, solution is now in place, so here’s a good opportunity to tell a little about the technical background of this, what the implications for application developers are, and how you can use a few new features in your plugins.

Bye bye, K_EXPORT_PLUGIN

In the KDE Platform 4, the K_EXPORT_PLUGIN macro did two things. It provided an entry point (qt_plugin_instance()) function which loads the plugin. With Qt5, the need for the entry point is gone, since plugins are now QObject based, so the methods defined in Q_INTERFACE can be relied on as entry points. K_EXPORT_PLUGIN also provided PLUGIN_VERIFICATION_DATA, which can be used to coarsely identify if a plugin was built against the right version. In most cases, this wasn’t very useful, as it would only catch a relatively small class of errors. The plugin verification data is missing in the new implementation so far, but we plan to get it back in another form: being able to specify the version in the plugin, and checking against that. This part is not yet there, but it’s also not a problem for now, as it’s not required and won’t produce fatal errors.

K_PLUGIN_FACTORY

The heavy lifting is done by this macro, which is often used together with K_EXPORT_PLUGIN: You create a factory class using this macro, and then, in the old world, you’d use K_EXPORT_PLUGIN to create the necessary entry points. Since we’re already defining the plugin factory instance using Q_DECLARE_INTERFACE, Qt is happy about that, and the stuff in K_EXPORT_PLUGIN becomes useless. Basically, we’ve moved the interesting bits from K_EXPORT_PLUGIN to K_PLUGIN_FACTORY. For porting that means, in the vast majority of cases, you can just remove K_EXPORT_PLUGIN from your code, and be done. (If you don’t remove it, it’ll warn during build, but will still work, so it’s source-compatible. Mostly, in some cases, .moc can’t pick up the macro, in this case, either move it into the .h file, or include the corresponding .moc file in your .cpp code.)

K_PLUGIN_FACTORY, or rather its base class, KPluginFactory is pretty neat. It’s mostly assembled by macros and templates, which makes it a bit hard to read and understand, but once you realize what kind of effort is saved for you by that, you’ll happily go for it (you don’t have to care about its internals as it is well encapsulated, of course). The really interesting piece is this:

template
T *create(const QString &keyword, QObject *parent = 0, const QVariantList &args = QVariantList());

This is a method available in the factory (generated by K_PLUGIN_FACTORY) that is the base of your plugin, basically what you get from QPluginLoader::instance() from your plugin once you’ve loaded the .so file. You basically call (roughly)

MyFancyObject* obj = pluginLoader->instance()->create<MyFancyObject*>(this);

to load your code into the app hosting the plugin. (Of course, MyFancyObject can be either the class actually defined in the plugin, or, more commonly, the baseclass of it (you don’t want to include your plugin’s header in the app, as that defeats the point of the plugin in the first place). You only do the above if you go through QPluginLoader directly, KService and Plasma::PluginLoader can do most of this work for you (also, here the API didn’t change, so no worries).

K_PLUGIN_FACTORY_WITH_JSON or where is the metadata?

Qt5’s new plugin system allows you to bake metadata into the plugin binary itself. They’re specified as an extra argument to the Q_PLUGIN_METADATA macro, and basically point to a json file containing whatever info you want in the plugin. The metadata is compiled into the ELF section of the plugin, can be found very fast, and the plugin itself doesn’t need to be dlopened in order to read it. With Qt’s previous plugin system, the plugin shared object files would have to be loaded, which significantly impacts performance.

This mechanism is very useful for something we’ve been doing in KDE for a long time, namely the data included in the .desktop files. Those are being installed separately, into a services install dir, indexed by ksycoca for faster access and searching. These .desktop files (which really are the plugin’s metadata contain all the usual stuff, name, icon, author, etc., but also the plugin name, dependencies, and most importantly, the ServiceType (e.g. Plasma/DataEngine). KService uses them to find a plugin (often by service type) and load it from the plugin name.

Having the metadata baked into the plugin allows us to not use KServiceTypeTrader (which handles the searching through the sycoca cache) but to ask QPluginLoader directly. Right now, we’re still using sycoca for the lookup, but this mechanism allows us to move away from it in the future.

Something we do use the metadata for already, at least in Plasma::DataEngine is the creation of a KPluginInfo object. (This object basically exposes the metadata, and can be instantiated from a .desktop file. With the above changes, I also added a constructor to KPluginInfo that instantiates a KPluginInfo object from the json metadata baked into the plugin. This is one nail in the coffin of KServiceTypeTrader (and in extension KSyCoCa), but obviously not its death blow.

K_PLUGIN_FACTORY_WITH_JSON simply takes an extra argument, the metadata file, and bakes that into the plugin (by inserting it, internally, into the Q_PLUGIN_METADATA macro which is included in the KPluginFactory implementation.

kservice_desktop_to_json kcoreaddons_desktop_to_json

In order to ease the transition from .desktop files to baked-in metadata, we introduced a cmake macro to help you with that. It’s pretty simple, you just write (in your CMakeLists.txt):

kcoreaddons_desktop_to_json(mypluginmetadata.desktop)

and during build time, a file called mypluginmetadata.json will be generated. You can include this file using the K_PLUGIN_FACTORY_WITH_JSON macro in your code, and the metadata will be baked in. When the plugin is loaded, your ctor will have a QVariantList as argument, which you can just pass to KPluginInfo, and get a valid plugininfo object back. If you’re interested what the .json file looks like, either peak into your build directory, or use the command

$ desktoptojson -i mydesktopfile.desktop

to generate a json file. (You usually want to run this at build time, and not put it in your repo, since otherwise, changes to the .desktop file, for example translations, will not be picked up.)

Edit: the kservice_desktop_to_json macro is deprecated in favor of kcoreaddons_desktop_to_json, use that.

So, tl;dr

  • Changes are largely source-compatible (K_EXPORT_PLUGIN can just go away, you might have to include the .moc file explicitely)
  • You can optionally use JSON metadata in your plugin to create KPluginInfo objects

If you want to create a plugin, do the following:

  • In your CMakeLists.txt file, convert your old .desktop file at build-time using kservice_desktop_to_json() and use the resulting file (replace .desktop with .json) in the following step
  • In your plugin .cpp file, add a K_PLUGIN_FACTORY macro, this does Q_DECLARE_INTERFACE and Q_PLUGIN_METADATA for you. Optionally pass a .json file
  • Use QPluginLoader, KServiceTypeTrader or Plasma::PluginLoader to load your plugin.

These changes are documented in the API documentation of KPluginFactory and in our KDE5Porting document.

Personal thanks go out to kdelibs hacker extraordinaire David Faure, who has been patiently guiding me through making these changes to our plugin system.

Update by David Faure


One thing it doesn’t detail (because you didn’t directly work on that) is differences in where plugins get installed (the install dir changed), and how they are found ($QT_PLUGIN_PATH).

One of the porting ideas is: if you don’t need the trader to find your plugins, don’t use it anymore. E.g. if you can put all your plugins into a subdirectory of the plugin path, and you don’t need any filtering (you just want to load them all), iterate over that, no servicetype and no trader needed. We still have to solve the use case of filtering/querying though, ideally in Qt (so that the json metadata can actually be useful).

Spooning, not forking

One thing that strikes me here during Akademy is the sense of community convergence one gets.

While other Free software projects drift apart, splitting up in multiple forks that stop talking to each other, differentiate based on the wrong reasons, what we see here during Akademy is projects growing closer to each other. This is a good development, so let’s look at it a bit more detailed.

KDE is continually evolving, becoming more diverse by the day. As an organisation, we realised that, and many see KDE as an umbrella organisation for Free software, rather than a “project doing a desktop environment”. When we published the KDE Manifesto, we set the tone for this to happen, and now we see it unfold. The KDE manifesto defines KDE as a community of like-minded Free software people. One of the most important adjectives to describe KDE is inclusive, that means that we define ourselves in terms of commonalities, rather than trying to differentiate ourselves from our peers.

Also, as an organisation that is in the business for 17 years, we have gathered a large body of expertise, best practises, knowledge how to run a community. We have also proven to be a sustainable and stable organisation.

At Akademy, the KDE community is joined by a wide variety of people not directly involved with KDE. We have VLC here, Razor Qt, Mer and of course our long-time friends from Qt present. This, on the one hand provides excellent opportunities for cross-pollination and solving common problems (or even just sharing pain!), on the other hand it makes us think if we’re at the right level of collaboration right now. Is there more to share among these distinct organisation, does it make sense to merge some of them and share the overhead?

This surely is food for thought, and I expect this class of discussions to last until long after Akademy, but it is very refreshing to see. It also increases the value of all our communities. Synergy through convergence.

It’s also an excellent way to make new friends, and look outside our own frame of reference.

Tokamak 6 Kicking Off: Why switch graphics stacks?

We (the KDE Plasma Team) are sitting at the SUSE office in Nürnberg, Germany right now, kicking off the already 6th edition of Tokamak, which is the name for (most of) our Plasma meetings. A Tokamak is a container for Plasma, which uses magnetic force to keep the Plasma in one (very hot) place. For the Plasma team, it provides a high-bandwidth setting where we can discuss, design, review and hack on the technology behind the Plasma workspaces. This meeting’s topic is Plasma2, the evolution of Plasma into the Qt5 and Wayland world.

First, we agreed on a bottom line: “Plasma 2 will be at least as good as the current Plasma, and probably better in many aspects.” This means that we’ll have to invest considerable effort and time into stabilization. At this point, where we are probably still a year or so away from a Plasma2-based release, making it part of our planning now will allow us to focus on the things that we think, matter. Among that is making sure the transition to KDE Frameworks 5, Plasma 2 and Wayland will be as seamless as possible, and perceived as an upgrade to our users.

But why are we doing this? Why are we putting so much work into it, what’s the benefit for the user?

Why switch graphics stacks?

In the past years, the landscape of graphics under Linux has changed quite a bit. Many things, like memory management of the graphics stack, rendering of primitives, font rendering, and a few other things involved in the process of “getting pixels onto your screen” have changed, and they’ve changed for the better. With a stack based on Wayland (and in extension Qt5), we are able to utilise modern graphics hardware better, to reduce maintainance effort and hopefully grow the community around the graphics stack, and not at least, to make sure that every frame that ends up on the screen is perfect. In the X11 world, we can’t really control it, since we have no idea when something is painted, in which way it is, where it’s painted, and when the pixels end up on the screen. With Wayland, this process of event processing, rendering and blitting is structured and guaranteed to happen in a certain order. In the end, this transition will enable us to put 60 perfect frames every second on the screen.
The new architecture also allows us to split the rendering into its own thread, so data processing or event handling in the application doesn’t end up delaying rendering. 60 frames per second will make the UI feel smooth as buttery silk, leading to less strain on the eyes and a nicer user experience.

What’s going on in Plasma Workspaces 2?


While moving its codebase to Qt5, the KDE Development Platform is undergoing a number of changes that lead to a more modular codebase (called KDE Framework 5) on top of a hardware-accelerated graphics stack. In this post, you’ll learn a bit about the status of Frameworks 5 and porting especially Plasma — that will be known as Plasma Workspaces 2, paying credit to its more convergent architecture.

Let’s start with something visual, before we get to the nitty-gritty:


Video showing a basic port of a Plasma Desktop Containment to Plasma 2

Frameworks 5

A whole bunch of libraries can now be built, installed and packaged separately. Those include (in tier1) Solid, Threadweaver, kdecore, karchive, kwindowsystem, and more, and in tier2 kauth and kconfig. Plasma has already moved into its own repository, and can of course also be built separately.

Kevin has been plugging away at removing problematic interdependencies between those libs, and recently could ditch (i.e. move to kde4support) a few classes that make it easier to just use Qt machinery (QApplication & friends) to bring up “KDE applications”. KAction has gone, KAboutData, so KDE Applications are now less “special” in the Qt world — a good thing for portability.
Splitting and untangling kdeui from kdelibs proves to be a bit more work- intensive than initially hoped. Fracture lines are becoming visible. The problem here is that this task is holding up the parallelization of development, so this has a high priority right now.

We’re also using a continuous integration system now to keep us on our toes with respect to “buildability” (which can be a bit daunting with so heavily shifting ground in kdelibs, this will calm down at some point though).


Video showing a Plasma 2 OpenGL shader demo widget

Plasma & KWin

Good progress, especially in the last month, in three areas:

API reviews: we’ve been doing weekly sessions for libplasma2 API reviews, where we’re going through the entire API and think about improvements for the Plasma 2, post-graphicsview world. As a result, libplasma2 has shrunk to about 1/3 in (compiled) size in its current state. We don’t expect it to grow much, since, in the scenegraph world, it plays another role than previously (although developers used to QML won’t really notice). (Join in the Hangout, if you like, we usually start on Monday morning around 10.00 UTC, just pop up in the #plasma channel and ask Marco to invite you). Our mutual status updates and Cool New Development is recorded and made available on Youtube for interested people, Last Monday’s session can be found here, but today we skipped it — you get this more detailed blog post in return. :)

Imports: Basically our QML runtime, it consists of Plasma Components, extras, bindings for things like dialog, framesvg and dataengines, drag and drop, krunner models, and a bunch of other stuff. I’m working on this right now, and have about 95% of the imports originating from kde-runtime working in Plasma2. We’ll be able to offer almost the same API to Plasma2 QML users, as in Plasma1, so porting of your QML code will be very easy.

Shell: In Plasma2, instead of having specific plasma-desktop, plasma-netbook, plasma-device shells, we will use one “generic” shell that loads containments (which then load applets), wallpaper, toolbox, etc. The shell can dynamically replace these components (change wallpaper, for example).

A few things are new here: in Plasma2, plasmoids provide their config ui via QML files, that are part of the package. That solves the problem that we could not really influence the behaviour of the configuration UIs from QML in Plasma1. It will also allow to transparantly switch between instant apply and “OK/Apply/Cancel” buttons, depending on what fits the usecase. Marco is on this.

Martin has been pushing the removal of the direct X dependency further through porting to XCB. He’s also recently started on a Qt5 port. One problem with KWin is that Martin needs a bunch of changes to have QtQuick and KWin run in the same process, that means making sure that KWin and Plasma (or QtQuick2 really) properly share and interact in the same OpenGL context. There’s a chicken-and-egg situation for kwin, since it needs to load for example window decorations and task switchers (both from QML) to be useful, but it can’t right now. The X11-based windecos won’t make it into Plasma2, so we’d rather avoid porting them just for the time being. Martin is on that though, and he earns our gratitude for going through this painful period in the porting procedure.