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();
}