Wayland native interface in Qt 6.5
Qt 6 introduced a new way to access platform specific objects and functionality in the
QNativeInterface
namespace. Starting with Qt 6.5
it will be possible to obtain handles to wayland object handles this way. Let’s look at what’s new
and how it improves on the past method.
In Qt 5 there were to two options to access platform-specific API and native handles of the current platform.
If you were lucky, your platform had an ‘Extras’ module like Qt Max Extras, Qt X11 Extras or Qt Android Extras.
However these were removed for Qt 6 and
if you ever needed something that was not exposed this way or the platform had no ‘Extras’ module (like Wayland), it
was also possible to access functionality via QPlatformNativeInterface
.
An example usage of would look like this:
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
if (!nativeInterface) {
return;
}
auto seat = static_cast<wl_seat*>(nativeInterface->nativeResourceForIntegration("wl_seat"));
auto surface = static_cast<wl_surface*>(nativeInterface->nativeResourceForWindow("surface", window));
if (!seat || !surface) {
return;
}
// do something with seat and surface
The snippet shows multiple problems of this API. One is that it is not type safe, the
nativeResourceFor...
functions return void*
. I could easily have forgotten to change the type in the second
cast with further implications down the line. The second problem is that it is not obvious at all what is available,
no header file will tell you. One has to either already know or read the implementation. Additionally any typo in the
string will break the functionality.
Qt 6 solves this with the interfaces in the QNativeInterface
namespace. They provide type safe access to the platform
specific parts. Using the new interfaces for Wayland in Qt 6.5 we can rewrite the above:
auto waylandApp = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
auto waylandWindow = window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
if (!waylandApp || !waylandWindow) {
return;
}
auto seat = waylandApp->seat();
auto surface = waylandWindow->surface();
if (!seat || !surface) {
return;
}
// do something with seat and surface
Much nicer. The nativeInterface
functions check that the interface is available on the object and from there on usage is straightforward.
It’s obvious what’s available by looking at the header or the documentation. For example through QWaylandApplication
it’s possible to access the wayland objects that Qt is using internally as well as the input
serial of the last user action which is sometimes required to pass in other wayland protocols.
The astute reader might have noticed that in the snippet QWaylandWindow
is in the nested QNativeInterface::Private
namespace for now. The interface chosen here is being evaluated and a bit experimental (due to the need of signalling surface creation and destruction, it’s the first native interface inheriting from QObject
!) and as I wanted to get this into Qt 6.5 I followed the precedent of QWindow
native interfaces of the other platforms
also being private for now. QWaylandOutput
also resides next to its cousins in QNativeInterface::Private
.
Still I hope they don’t need to stay too long there and can be made public soon.