# 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:

```cpp
class KisWaylandAPIColorManager
    : 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`:

```cpp
KisWaylandAPIColorManager::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);
            }
        }
    });
}
```

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

```bash
# 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:

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

## How to test client-side-decorations rendering code

Gnome/Mutter refuse to implement server-side window decorations
(https://gitlab.gnome.org/GNOME/mutter/-/issues/217), so on Gnome
Krita uses the decorations provided by Qt. To test this codepath
on a normal compositor with SSD, one needs to disable the
corresponding protocol support in Qt and choose the CSD plugin
name:

```bash
QT_QPA_PLATFORM=wayland QT_WAYLAND_DISABLED_INTERFACES=zxdg_decoration_manager_v1 QT_WAYLAND_DECORATION=adwaita krita

# or

QT_QPA_PLATFORM=wayland QT_WAYLAND_DISABLED_INTERFACES=zxdg_decoration_manager_v1 QT_WAYLAND_DECORATION=bradient krita
```

## How to test an extension, unsupported in your compositor

If you want to test code related to an extension that your compositor doesn't support,
you can bypass Krita's checks for the extension by passing the following environment variable:

```bash
KRITA_FORCE_WAYLAND_INTERFACES=*list of extension names*
```

For example to force Krita to do wayland color management on an unsupported compositor, you can pass:

```bash
KRITA_FORCE_WAYLAND_INTERFACES=wp_color_manager_v1
```

Note: The extension will **NOT** function properly if you do this.
