Krita Source Code Documentation
Loading...
Searching...
No Matches
Rules of thumb when writing a Wayland plugin

Client extension object lifetime management

When constructing a client extension with QWaylandClientExtensionTemplate, use automated deletion routines provided by the generated code:

Pass the autogenerated destroy() method into the second argument of the template:

: public QWaylandClientExtensionTemplate<KisWaylandAPIColorManager,
// \|/ pass the destructor here!
&QtWayland::wp_color_manager_v1::destroy>
, public QtWayland::wp_color_manager_v1
{
};

This will generate a code that performs two things for you:

1) Destruction of the Wayland's C-style object in the destructor of the C++-object

2) Destruction of the Wayland's C-style object when the extension gets inactive, i.e. when the connection is lost.

Active and non-active states

Wayland protocol is a "connection" to the compositor, which means that this connection may be lost sometimes (e.g. when the compositor crashes). Theoretically, we should expose this state on the API level, but we don't do that. Instead we expose ready and non-ready states (see below).

Ready and non-ready states

The Wayland protocol is asynchronous. It means that when we request some information from the compositor we do not get the reply immediately. Instead we should wait untit the compositor sends us an event with the reply.

For this reason we added two states to the plugin API. The interface may be "ready" (i.e. all information is available right away) or "non-ready". The "non-ready" state also covers the case when the connection is lost and the API is in non-active state.

Handling of the disconnection signal

When the connection to the compositor is lost (i.e. it crashed and got restarted), we should handle that and recreate all the objects related to our extension.

Basically, you need to handle QWaylandClientExtensionTemplate::activeChanged signal, destroy all the object and turn the object into "non-ready" mode.

See an example in KisWaylandAPIColorManager:

: QWaylandClientExtensionTemplate(1)
{
connect(this, &QWaylandClientExtensionTemplate::activeChanged, this, [this] {
if (!isActive()) {
m_supportedFeatures.clear();
m_supportedIntents.clear();
m_supportedPrimariesNamed.clear();
m_supportedTransferFunctionsNamed.clear();
if (m_isReady) {
m_isReady = false;
Q_EMIT sigReadyChanged(m_isReady);
}
}
});
}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))

To test if your app handles the disconnection signal correctly just run:

# ensure Qt tries to reconnect on the server restart
export QT_WAYLAND_RECONNECT=1
# restart the compositor
kwin_wayland --replace

Your app should not die :)

WARNING: it will kill all your XWayland apps (and wayland-native apps that handle this case incorrectly).

How to debug Wayland protocol interactions

You can set WAYLAND_DEBUG environment variable:

WAYLAND_DEBUG=1 krita | grep -E 'image|color'