diff --git a/src/client/protocols/server-decoration.xml b/src/client/protocols/server-decoration.xml --- a/src/client/protocols/server-decoration.xml +++ b/src/client/protocols/server-decoration.xml @@ -40,6 +40,23 @@ + + + + + + + + + This event is emitted directly after binding the interface. It contains + the default mode for the decoration. When a new server decoration object + is created this new object will be in the default mode till the first + request mode is emitted. + + The server may change the default mode at any time. + + + diff --git a/src/client/server_decoration.h b/src/client/server_decoration.h --- a/src/client/server_decoration.h +++ b/src/client/server_decoration.h @@ -222,6 +222,13 @@ **/ Mode mode() const; + /** + * @returns The default decoration mode the server uses + * + * @see mode + **/ + Mode defaultMode() const; + operator org_kde_kwin_server_decoration*(); operator org_kde_kwin_server_decoration*() const; diff --git a/src/client/server_decoration.cpp b/src/client/server_decoration.cpp --- a/src/client/server_decoration.cpp +++ b/src/client/server_decoration.cpp @@ -24,7 +24,8 @@ #include "wayland_pointer_p.h" #include -class ServerSideDe; + +#include namespace KWayland { @@ -36,10 +37,79 @@ public: Private() = default; + void setup(org_kde_kwin_server_decoration_manager *serversidedecorationmanager); + WaylandPointer serversidedecorationmanager; EventQueue *queue = nullptr; + ServerSideDecoration::Mode defaultMode = ServerSideDecoration::Mode::None; + QVector decorations; + +private: + static void defaultModeCallback(void *data, org_kde_kwin_server_decoration_manager *manager, uint32_t mode); + static const struct org_kde_kwin_server_decoration_manager_listener s_listener; }; +class ServerSideDecoration::Private +{ +public: + Private(ServerSideDecoration *q); + + void setup(org_kde_kwin_server_decoration *serversidedecoration); + + WaylandPointer serversidedecoration; + Mode mode = Mode::None; + Mode defaultMode = Mode::None; + +private: + static void modeCallback(void *data, org_kde_kwin_server_decoration *org_kde_kwin_server_decoration, uint32_t mode); + static const struct org_kde_kwin_server_decoration_listener s_listener; + + ServerSideDecoration *q; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const org_kde_kwin_server_decoration_manager_listener ServerSideDecorationManager::Private::s_listener = { + defaultModeCallback +}; +#endif + +void ServerSideDecorationManager::Private::defaultModeCallback(void *data, org_kde_kwin_server_decoration_manager *manager, uint32_t mode) +{ + auto p = reinterpret_cast(data); + Q_ASSERT(p->serversidedecorationmanager == manager); + + ServerSideDecoration::Mode m; + switch (mode) { + case ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE: + m = ServerSideDecoration::Mode::None; + break; + case ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT: + m = ServerSideDecoration::Mode::Client; + break; + case ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER: + m = ServerSideDecoration::Mode::Server; + break; + default: + // invalid mode cannot set + qCWarning(KWAYLAND_CLIENT) << "Invalid decoration mode pushed by Server:" << mode; + return; + } + p->defaultMode = m; + // update the default mode on all decorations + for (auto it = p->decorations.constBegin(); it != p->decorations.constEnd(); ++it) { + (*it)->d->defaultMode = m; + // TODO: do we need a signal? + } +} + +void ServerSideDecorationManager::Private::setup(org_kde_kwin_server_decoration_manager *manager) +{ + Q_ASSERT(manager); + Q_ASSERT(!serversidedecorationmanager); + serversidedecorationmanager.setup(manager); + org_kde_kwin_server_decoration_manager_add_listener(serversidedecorationmanager, &s_listener, this); +} + ServerSideDecorationManager::ServerSideDecorationManager(QObject *parent) : QObject(parent) , d(new Private) @@ -53,9 +123,7 @@ void ServerSideDecorationManager::setup(org_kde_kwin_server_decoration_manager *serversidedecorationmanager) { - Q_ASSERT(serversidedecorationmanager); - Q_ASSERT(!d->serversidedecorationmanager); - d->serversidedecorationmanager.setup(serversidedecorationmanager); + d->setup(serversidedecorationmanager); } void ServerSideDecorationManager::release() @@ -104,27 +172,12 @@ if (d->queue) { d->queue->addProxy(w); } + deco->d->defaultMode = d->defaultMode; + deco->d->mode = d->defaultMode; deco->setup(w); return deco; } -class ServerSideDecoration::Private -{ -public: - Private(ServerSideDecoration *q); - - void setup(org_kde_kwin_server_decoration *serversidedecoration); - - WaylandPointer serversidedecoration; - Mode mode = Mode::None; - -private: - static void modeCallback(void *data, org_kde_kwin_server_decoration *org_kde_kwin_server_decoration, uint32_t mode); - static const struct org_kde_kwin_server_decoration_listener s_listener; - - ServerSideDecoration *q; -}; - #ifndef DOXYGEN_SHOULD_SKIP_THIS const org_kde_kwin_server_decoration_listener ServerSideDecoration::Private::s_listener = { modeCallback @@ -232,5 +285,10 @@ return d->mode; } +ServerSideDecoration::Mode ServerSideDecoration::defaultMode() const +{ + return d->defaultMode; +} + } } diff --git a/src/server/server_decoration_interface.cpp b/src/server/server_decoration_interface.cpp --- a/src/server/server_decoration_interface.cpp +++ b/src/server/server_decoration_interface.cpp @@ -40,6 +40,8 @@ Mode defaultMode = Mode::None; + QVector resources; + private: void bind(wl_client *client, uint32_t version, uint32_t id) override; @@ -107,6 +109,25 @@ { } +namespace { +static uint32_t modeWayland(ServerSideDecorationManagerInterface::Mode mode) +{ + switch (mode) { + case ServerSideDecorationManagerInterface::Mode::None: + return ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE; + break; + case ServerSideDecorationManagerInterface::Mode::Client: + return ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT; + break; + case ServerSideDecorationManagerInterface::Mode::Server: + return ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER; + break; + default: + Q_UNREACHABLE(); + } +} +} + void ServerSideDecorationManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) { auto c = display->getConnection(client); @@ -116,13 +137,16 @@ return; } wl_resource_set_implementation(resource, &s_interface, this, unbind); - // TODO: should we track? + + resources << resource; + + org_kde_kwin_server_decoration_manager_send_default_mode(resource, modeWayland(defaultMode)); + c->flush(); } void ServerSideDecorationManagerInterface::Private::unbind(wl_resource *resource) { - Q_UNUSED(resource) - // TODO: implement? + cast(resource)->resources.removeAll(resource); } ServerSideDecorationManagerInterface::ServerSideDecorationManagerInterface(Display *display, QObject *parent) @@ -141,6 +165,10 @@ { Q_D(); d->defaultMode = mode; + const uint32_t wlMode = modeWayland(mode); + for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); it++) { + org_kde_kwin_server_decoration_manager_send_default_mode(*it, wlMode); + } } class ServerSideDecorationInterface::Private : public Resource::Private @@ -240,21 +268,7 @@ { Q_D(); d->mode = mode; - uint32_t wlMode; - switch (mode) { - case ServerSideDecorationManagerInterface::Mode::None: - wlMode = ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE; - break; - case ServerSideDecorationManagerInterface::Mode::Client: - wlMode = ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT; - break; - case ServerSideDecorationManagerInterface::Mode::Server: - wlMode = ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER; - break; - default: - Q_UNREACHABLE(); - } - org_kde_kwin_server_decoration_send_mode(resource(), wlMode); + org_kde_kwin_server_decoration_send_mode(resource(), modeWayland(mode)); client()->flush(); }