Chill your Champagne bottles – it’s official: the KDE Plasma 6.0 + KDE Frameworks 6.0 + KDE Gear 24.02 Mega Release™ that will take KDE software to the next level is going to happen on 28th February 2024! Let’s have a look at what I’ve been up to in the past two months, again working mostly on either Qt itself or dealing with its behavior changes on the application side.
A major annoyance I have been chasing for a while has been the Kate/KWrite double-close bug: when you quit the editor with unsaved changes it would naturally prompt whether you’d want to save the changes. If you said no, it asked you again‽ I am not very familiar with the code bases of Kate and KTextEditor (which by the way is actually a fantastic Framework you can use in your own apps if you need a text editor with syntax highlighting, code folding, multi-cursor, and much more!) so I just couldn’t figure out why the exit code ran twice.
One night I was casually browsing Qt documentation looking for “What’s New In Qt 6” and found that QCoreApplication::quit() behaves differently in Qt 6. While in Qt 5, calling quit() was the same as calling QCoreApplication::exit(0), i.e. just exiting the main event loop, in Qt 6 calling quit() closes all top-level windows first. Kate was calling quit(), which would now ask the editor window to close, causing a “Save?” prompt. Once the dialog was rejected, shutdown commenced but the changes were still “unsaved” and Kate would ask again. Since Kate has its own shutdown code anyway, we can just skip all of that and call QCoreApplication::exit(0), fixing the bug. That’s why it’s important to read Release Notes.
One API change in QFont even affected Chromium, which incidentally gained a Qt 6 back end: In Qt 5 QFont::Weight was a number from 0 to 100, with “Normal” being 50. Qt 6 on the other hand together with CSS and many others follows the OpenType specification where font-weight ranges from 0 to 1000, with “Normal” being 400. Chrome used the same conversion logic on both platforms and in a Plasma 6 session encountered the default font being set to 400 and thus assumed it was meant to be ultra-black, leading to bold text throughout its UI. Once I reported this, the issues was resolved by one of their Linux platform maintainers faster than I would have been able to build Chromium and submit a fix myself.
Another one that might bite you is an assert that was added in Qt 6.3 about calling slots on objects being torn down. While this has always been dangerous, Qt will now yell at you. If, for example, you have a child object and connect its destroyed signal to a slot in your object, when the child is destroyed on normal parent-child teardown (which happens in the QObject destructor, i.e. after your class destructor) it will call into your slot when the object is already half-dead, and Qt rightfully complains.
This uncovered an issue in Dolphin when closing it while its terminal panel was open, since it is an embedded Konsole KPart which is monitored for destruction (if the shell unexpectedly quit, for instance) to then close the panel. Of course, the KPart is also destroyed during normal application teardown and triggered this assertion. The solution was to disconnect the signal in the destructor. A similar thing occurred in KWin where a thumbnail item monitored its window changing, which can also happen during cleanup when the window goes away and is announced to now be null. This was resolved by instead calling the relevant handler from QQuickItem::itemChange, which is also ever so slightly more efficient than creating a signal-slot connection.
I also finally figured out those “Unregistered input type in parameter list” errors coming from Qt DBus, which, among other things, broke Bluetooth device discovery. It failed to connect to the relevant DBus ObjectManager signals for when a device appeared. Normally this is a sign that you forgot to call qDBusRegisterMetaType which makes a custom type, such as a struct, or even a simple typedef, known to the DBus type system. However, the code in question on the KDE side hasn’t changed in years and has been working just fine under Qt 5. Turns out QMetaType is a lot smarter in Qt 6: whereas in Qt 5 it saw a typedef only by its declared name, e.g. VariantMapMap, in Qt 6, it would know it as the compiler saw it and register it under e.g. QMap<QString, QMap<QString, QVariant>>. When it then during DBus type marshalling encountered the name “VariantMapMap” it didn’t know what to do and failed.
Additionally, I did a few more Qt changes:
- QModelIndex::data() is invokable by QML starting in Qt 6.7, so when passed a QModelIndex, instead of calling index.model.data(index, role), you can directly call index.data(role) as expected.
- The text property on QQuickText is no longer FINAL in Qt 6.6.0, since during the effort to mark everything as final, it was missed that even Qt’s own QQuickMnemonicLabel, which handles the underlined letters in QtQuick Controls 2, overrode it.
- QtMultimedia’s PulseAudio backend sets a proper application ID, name, and icon, so apps don’t show up in the Volume applet as generic “QtPulseAudio:<pid>” anymore.
On the KDE side, I fixed rendering images in Gwenview when using fractional scaling on Wayland in a similar way as I did last time for Dolphin – both use QGraphicsView after all. A funky repaint issue in the System Monitor has also been fixed which was caused by someone calling winId() on something that is not a window. When you do that on Wayland, Qt will split the widget into its own subsurface window causing all sorts of hard to debug input and rendering issues. Furthermore, the new QML-based PolicyKit prompt can now be dismissed by pressing Escape, just like any other dialog.
Kirigami’s Mnemonic handler which auto-generates shortcuts from the underlined letters for controls in QML applications has been optimized by installing one global event filter instead of one per label which typically are many. The event filter is used to show the underlined letter only while the Alt key is pressed. The new Kirigami InlineViewHeader control used at the top of many list views nowadays can be used in conjunction with a GridView. While ListView supports sticky header positioning, GridView’s headers always scroll with its contents. The layouting code in QtQuick’s item views is quite complex, so I just added a workaround in Kirigami translating the vertical header position in the opposite direction of the scroll position, effectively sticking it to the top of the view.
Finally, Font Management works in a Plasma Wayland session but only as a stopgap since it basically just opens its own X connection rather than relying on Qt here which obviously won’t do that when run under Wayland. The whole thing is twenty years old and completely written around Xft, the X Font library, so I think the only way to make it run natively on Wayland is to rewrite it from scratch.
Plasma 6.0 Alpha is just around the corner and you can help make it a reality by donating to our Plasma 6 Fundraiser! I can only encourage you to give Plasma 6 a try and help iron out any bugs. If you want to learn more about what to expect in the future, there’s two lovely two-hour interviews on Tech Over Tea with David Edmundson and Nate Graham about Plasma, Wayland, and KDE in general. And don’t forget about the Wallpaper Contest that closes on 14th November!
Discuss this post on KDE Discuss.
Such great work! I love how you explain the details of all the fixes in a comprehensible way.
I really appreciate your work on fixing fractional scaling issues under Wayland.
The Gwenview change (https://invent.kde.org/graphics/gwenview/-/merge_requests/227/diffs) looks really simple, and I thought I’d try my hand at applying something similar to KRDC (host screens are currently rendered at the wrong size), but it turns out I have no idea what I’m doing :) There are quite a few devicePixelRatio references: https://invent.kde.org/search?search=devicePixelRatio&nav_source=navbar&project_id=2147&group_id=1551&search_code=true&repository_ref=master – if there’s an easy fix and you have time, I’d value your input.