HighDPI in KDE Applications

Recently I was asked about the state of High DPI in KDE Applications, by someone with a fancy screen.

In Plasma we have our own solution for solving the HighDPI problem, as we were working with new code where we provide the styling, this is all fairly straightforward. However, this doesn't work for applications which have a lot of existing code we need to bring this feature to.

This upcoming release of Qt (5.4) brings us everything we need to support High DPI in our applications. It's not going to be useful for end users just now, but this is a time where we need each and every developer to start getting interested and making sure their applications are ready.

Support requires at least one line of change in every application.

High DPI in Qt

Normally my application, will look something like this. On my screen this is fine,if you see this on a high DPI screen everything will be tiny.



If we change the DPI used in the fonts we, naturally, get bigger fonts. More usable, but all of the other controls are still hilariously small as they haven't changed. This is our current state.



Device Independent Pixels

Qt borrowed a concept used in Android and iOS of separating the pixel sizes we use in the code, to the actual pixel density on the screen.

From a programming perspective we keep coding like everything is in 96dpi like a normal desktop display, but underneath all co-ordinates and graphics will be doubled or quadrupled to scale up to the device resolution.

This API at a Qt level works per screen; with every screen having it's own independent scaling factor. However, in the X backend for Qt 5.4 it's loaded from an environment variable that applies to all screens. Not ideal, but better than nothing.

This gives a result, that is now usable, but very blocky and pixelated.
(you may need to click the image to really see this)



This blockiness problem is also solved. Whenever we create a pixmap we can make sure we provide graphics that have a higher size in device pixels than their size in user space.

To quote the QPixmap documentation, "For example, painting on a 200x200 image if with a ratio of 2.0 will result in effective (device-independent) painting bounds of 100x100.".

With "pixel" now meaning one of two things can get confusing very quickly.

As you might imagine, all of this wizardry under the scenes means it's moderated likely to break at least some applications. As Qt follows the rule of never breaking existing application it requires each and every application to opt in.

I added a command line flag --highdpi to oxygen-demo, the application in the screenshots, to enable the scaling support and test both side-by-side which finally leaves us with:



There were no additional changes to oxygen demo to make this work yet we see we're using high resolution pixmaps on the icons and on the clear buttons in the text field.

How to make sure your app works with Qt's high DPI

1) Port to Qt5
If you're putting it off porting because you're scared of regressions. The reality is over time you will have more bugs from not porting. Without Qt5 we don't get /any/ scaling. Not even the blocky version.

2) Opt in to the high DPI pixmap support
Add:

app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);

to your main function

3) Port code
If you don't do any low level work with unusual QPainter painting, provide any of your own pixmaps or load textures in QQuickItems, everything will just work.

Most likely your app will have something broken. Useful links are here and here.

4) Test
I only have a poor person's screen, but it's still easy(ish) to test:

  • Change the DPI under system settings -> font -> force font DPI to 192
  • Set the environment variable QT_DEVICE_PIXEL_RATIO=2

On a normal screen everything will appear massive, but hopefully also super smooth.

My thoughts on the GNOME trademark dispute

Unless you've been living under a rock today you would have seen that Groupon™ have been trying to use a trademark that belongs to GNOME™. Today GNOME™ started raising money to fight a legal battle.

I know there have been ongoing private discussions for months, and even though I have no idea what was said I do have full faith that if it got to the point of GNOME threatening to take legal action, it's because they felt they needed to.

It seems to have worked.

Communities Unified

What I loved to see most about this was I opened my G+/Facebook/Twitter feeds to see all of my KDE colleagues resharing this piece and donating money. Even /r/linux on Reddit, normally a somewhat feisty community, was filled with comments like "I don't use Gnome, but I'm going to support them".

Working together, supporting each other is what us open source communities should be about.

We're Not Easily Pushed Over

I don't think there was any attempt or conspiracy to try and destroy Gnome, but I do think there must have been some decision maker thinking "it's only a small charity software project, they're not going to bother fighting back, we can walk over them".

We, collectively, showed them wrong and I like to think the next company won't think the same thing.

Money Well Spent?

To everyone in engineering, the idea of having to spend money on legal mumbo jumbo is, at best, thoroughly depressing.

However, I saw a number of people making the rather silly comment "this is money that they should spend on developing instead". This was a fundraiser, which means it's "new" money that GNOME™ wouldn't have had otherwise.

Case in point; KDE™ and GNOME™ both have constant drives for developer funds which don't recieve anywhere near the level of interest this got.

If you feel that's where money should be spent, please please donate there and put your money where your mouth is.

My new library: Qlogind

What is it?

A high level wrapper round logind.

We are starting to use logind in numerous places; I need it in SDDM to track sessions. we have code in ksmserver to track Lock/Unlock signals, as well as in the kworkspace library to list sessions. It's coming into KWin for device hardware access as well as being used in solid.

The need for a library

Often we can simply automatically generate bindings at compile time using qdbusxml2cpp that turns DBus interface annotation into working code.

Unfortunately that doesn't work here for a few reasons.

qdbusxml2cpp and QDBusAbstractInterface are both really outdated; and don't know how to handle org.freedesktop.DBus.Properties.PropertiesChanged. Logind uses this method as the only way to notify of any changes, and in fact even introduced their own new type of changed signal annotation without these change signals it becomes near impossible to use.

To solve this, and a few other minor issues this repository contains a fork of qdbusxml2xpp and QDBusAbstractInterface with property caching and no blocking methods anywhere.

Ideally I want to push my changes upstream, but I always like to prototype code before committing to new API especially with Qt. Also we're going to need these changes before Qt5.5.

There are some other usages for a library, there are some changes needed to make to the annotation to make it compile (logind has a property called "class", funnily enough the c++ compiler does not like this) as well as code to demarshall complex types.

From personal experience having a good wrapper library can make a lot of development easier as we can write a higher level API on top to ease fetching multiple queries asynchronously.

Example

I've tried to make the code as easy to use in an asynchronous way, without the user having to write chains of lambdas.

Example:

    PendingSession* ps = Session::sessionFromPid(QCoreApplication::applicationPid());
    QObject::connect(ps, &PendingSession::finished, [=](){
        SessionPtr session = ps->interface();
        if (session->active()) {
            qDebug() << "Session " << session->id(); << "is active";
        }
    });

This code internally both a call to Login1.Manager to find the session path for a PID then requesting Properties.GetAll on the Session object in one handy KJob like API.

Where is the code

Code is availabe at git://anongit.kde.org/scratch/davidedmundson/qlogind.git

Current State

It's not quite finished, I only started this 2 working days ago. It needs namespacing, d-pointers and unit tests.

I wanted to write a blog post to get the people who might need to use this to have a look and give some feedback if there's anything missing.

Display Managers In Plasma 5

The last blog posts about KDM/LightDM/SDDM/WhateverDM left things a bit on an exciting cliffhanger so I've been asked a few times what the current state is.

The short summary is we recommend SDDM as the display manager for Plasma 5.

Backstory

KDM was dropped from Plasma 5. KDM includes code from XDM dating back to 1988! It had served it's job well. However, we're now at a point where we need the backend to be Wayland ready and we want to use more modern QML in the front end. When you have to replace both the back and front ends, it's a sign to just start from scratch.

There was some work done 2 years ago into sharing code with LightDM. In the meantime a separate project was started, SDDM which is (yet another) display manager.

Although personally I was very happy with what we had with LightDM it definitely doesn't make sense to split resources, so we focussed everything on SDDM and I have been helping work on that transferring knowledge from my old project.

Plasma Integration

SDDM is itself in Github and usage is shared with other desktop enviroments, in particular Maui. This makes it harder to add Plasma integration in the code itself, but we've managed nonetheless.

The visual design group made some mockups of a new display manager, which became the basis for the implementation of our login screen.

This is shipped with plasma-workspace. It is up to distributions to update /etc/sddm.conf to update the default theme on installation as it's not something we can do from our code.

In addition we also provide a configuration module that fits into SystemSettings. This is now back in the KDE repositories and will be included in Plasma 5.2.

Naturally Plasma can still work with any display manager as half of the point of having a display manager is to allow choosing which session to launch.