File indexing completed on 2024-11-10 04:57:32

0001 /*
0002     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "server_decoration.h"
0007 #include "display.h"
0008 #include "surface.h"
0009 #include "utils/common.h"
0010 
0011 #include <QList>
0012 
0013 #include <optional>
0014 
0015 #include <qwayland-server-server-decoration.h>
0016 
0017 namespace KWin
0018 {
0019 static const quint32 s_version = 1;
0020 
0021 class ServerSideDecorationManagerInterfacePrivate : public QtWaylandServer::org_kde_kwin_server_decoration_manager
0022 {
0023 public:
0024     ServerSideDecorationManagerInterfacePrivate(ServerSideDecorationManagerInterface *_q, Display *display);
0025     void setDefaultMode(ServerSideDecorationManagerInterface::Mode mode);
0026 
0027     ServerSideDecorationManagerInterface::Mode defaultMode = ServerSideDecorationManagerInterface::Mode::None;
0028     ServerSideDecorationManagerInterface *q;
0029 
0030 protected:
0031     void org_kde_kwin_server_decoration_manager_bind_resource(Resource *resource) override;
0032     void org_kde_kwin_server_decoration_manager_create(Resource *resource, uint32_t id, wl_resource *surface) override;
0033 };
0034 
0035 static uint32_t modeWayland(ServerSideDecorationManagerInterface::Mode mode)
0036 {
0037     switch (mode) {
0038     case ServerSideDecorationManagerInterface::Mode::None:
0039         return ServerSideDecorationManagerInterfacePrivate::mode_None;
0040     case ServerSideDecorationManagerInterface::Mode::Client:
0041         return ServerSideDecorationManagerInterfacePrivate::mode_Client;
0042     case ServerSideDecorationManagerInterface::Mode::Server:
0043         return ServerSideDecorationManagerInterfacePrivate::mode_Server;
0044     default:
0045         Q_UNREACHABLE();
0046     }
0047 }
0048 
0049 void ServerSideDecorationManagerInterfacePrivate::org_kde_kwin_server_decoration_manager_create(Resource *resource, uint32_t id, wl_resource *surface)
0050 {
0051     SurfaceInterface *s = SurfaceInterface::get(surface);
0052     if (!s) {
0053         wl_resource_post_error(resource->handle, 0, "Invalid  surface");
0054         return;
0055     }
0056 
0057     wl_resource *decorationResource = wl_resource_create(resource->client(), &org_kde_kwin_server_decoration_interface, resource->version(), id);
0058     if (!decorationResource) {
0059         wl_client_post_no_memory(resource->client());
0060         return;
0061     }
0062     auto decoration = new ServerSideDecorationInterface(q, s, decorationResource);
0063     decoration->setMode(defaultMode);
0064     Q_EMIT q->decorationCreated(decoration);
0065 }
0066 
0067 void ServerSideDecorationManagerInterfacePrivate::setDefaultMode(ServerSideDecorationManagerInterface::Mode mode)
0068 {
0069     defaultMode = mode;
0070     const uint32_t wlMode = modeWayland(mode);
0071 
0072     const auto clientResources = resourceMap();
0073     for (Resource *resource : clientResources) {
0074         send_default_mode(resource->handle, wlMode);
0075     }
0076 }
0077 
0078 ServerSideDecorationManagerInterfacePrivate::ServerSideDecorationManagerInterfacePrivate(ServerSideDecorationManagerInterface *_q, Display *display)
0079     : QtWaylandServer::org_kde_kwin_server_decoration_manager(*display, s_version)
0080     , q(_q)
0081 {
0082 }
0083 
0084 void ServerSideDecorationManagerInterfacePrivate::org_kde_kwin_server_decoration_manager_bind_resource(Resource *resource)
0085 {
0086     send_default_mode(resource->handle, modeWayland(defaultMode));
0087 }
0088 
0089 ServerSideDecorationManagerInterface::ServerSideDecorationManagerInterface(Display *display, QObject *parent)
0090     : QObject(parent)
0091     , d(new ServerSideDecorationManagerInterfacePrivate(this, display))
0092 {
0093 }
0094 
0095 ServerSideDecorationManagerInterface::~ServerSideDecorationManagerInterface() = default;
0096 
0097 void ServerSideDecorationManagerInterface::setDefaultMode(Mode mode)
0098 {
0099     d->setDefaultMode(mode);
0100 }
0101 
0102 ServerSideDecorationManagerInterface::Mode ServerSideDecorationManagerInterface::defaultMode() const
0103 {
0104     return d->defaultMode;
0105 }
0106 
0107 class ServerSideDecorationInterfacePrivate : public QtWaylandServer::org_kde_kwin_server_decoration
0108 {
0109 public:
0110     ServerSideDecorationInterfacePrivate(ServerSideDecorationManagerInterface *manager,
0111                                          ServerSideDecorationInterface *_q,
0112                                          SurfaceInterface *surface,
0113                                          wl_resource *resource);
0114     ~ServerSideDecorationInterfacePrivate();
0115 
0116     static ServerSideDecorationInterface *get(SurfaceInterface *surface);
0117     void setMode(ServerSideDecorationManagerInterface::Mode mode);
0118 
0119     ServerSideDecorationManagerInterface *manager;
0120     ServerSideDecorationManagerInterface::Mode mode = ServerSideDecorationManagerInterface::Mode::None;
0121     std::optional<ServerSideDecorationManagerInterface::Mode> preferredMode;
0122     SurfaceInterface *surface;
0123 
0124 private:
0125     ServerSideDecorationInterface *q;
0126     static QList<ServerSideDecorationInterfacePrivate *> s_all;
0127 
0128 protected:
0129     void org_kde_kwin_server_decoration_destroy_resource(Resource *resource) override;
0130     void org_kde_kwin_server_decoration_release(Resource *resource) override;
0131     void org_kde_kwin_server_decoration_request_mode(Resource *resource, uint32_t mode) override;
0132 };
0133 
0134 QList<ServerSideDecorationInterfacePrivate *> ServerSideDecorationInterfacePrivate::s_all;
0135 
0136 void ServerSideDecorationInterfacePrivate::org_kde_kwin_server_decoration_request_mode(Resource *resource, uint32_t mode)
0137 {
0138     ServerSideDecorationManagerInterface::Mode m = ServerSideDecorationManagerInterface::Mode::None;
0139     switch (mode) {
0140     case ServerSideDecorationManagerInterfacePrivate::mode_None:
0141         m = ServerSideDecorationManagerInterface::Mode::None;
0142         break;
0143     case ServerSideDecorationManagerInterfacePrivate::mode_Client:
0144         m = ServerSideDecorationManagerInterface::Mode::Client;
0145         break;
0146     case ServerSideDecorationManagerInterfacePrivate::mode_Server:
0147         m = ServerSideDecorationManagerInterface::Mode::Server;
0148         break;
0149     default:
0150         // invalid mode
0151         qCWarning(KWIN_CORE) << "Invalid mode:" << mode;
0152         return;
0153     }
0154     preferredMode = m;
0155     Q_EMIT q->preferredModeChanged();
0156 }
0157 
0158 void ServerSideDecorationInterfacePrivate::org_kde_kwin_server_decoration_release(Resource *resource)
0159 {
0160     wl_resource_destroy(resource->handle);
0161 }
0162 
0163 void ServerSideDecorationInterfacePrivate::org_kde_kwin_server_decoration_destroy_resource(Resource *resource)
0164 {
0165     delete q;
0166 }
0167 
0168 ServerSideDecorationInterface *ServerSideDecorationInterfacePrivate::get(SurfaceInterface *surface)
0169 {
0170     for (ServerSideDecorationInterfacePrivate *decoration : std::as_const(s_all)) {
0171         if (decoration->surface == surface) {
0172             return decoration->q;
0173         }
0174     }
0175     return nullptr;
0176 }
0177 
0178 ServerSideDecorationInterfacePrivate::ServerSideDecorationInterfacePrivate(ServerSideDecorationManagerInterface *manager,
0179                                                                            ServerSideDecorationInterface *_q,
0180                                                                            SurfaceInterface *surface,
0181                                                                            wl_resource *resource)
0182     : QtWaylandServer::org_kde_kwin_server_decoration(resource)
0183     , manager(manager)
0184     , surface(surface)
0185     , q(_q)
0186 {
0187     s_all << this;
0188 }
0189 
0190 ServerSideDecorationInterfacePrivate::~ServerSideDecorationInterfacePrivate()
0191 {
0192     s_all.removeAll(this);
0193 }
0194 
0195 void ServerSideDecorationInterfacePrivate::setMode(ServerSideDecorationManagerInterface::Mode mode)
0196 {
0197     this->mode = mode;
0198     send_mode(modeWayland(mode));
0199 }
0200 
0201 ServerSideDecorationInterface::ServerSideDecorationInterface(ServerSideDecorationManagerInterface *manager, SurfaceInterface *surface, wl_resource *resource)
0202     : QObject()
0203     , d(new ServerSideDecorationInterfacePrivate(manager, this, surface, resource))
0204 {
0205 }
0206 
0207 ServerSideDecorationInterface::~ServerSideDecorationInterface() = default;
0208 
0209 void ServerSideDecorationInterface::setMode(ServerSideDecorationManagerInterface::Mode mode)
0210 {
0211     d->setMode(mode);
0212 }
0213 
0214 ServerSideDecorationManagerInterface::Mode ServerSideDecorationInterface::mode() const
0215 {
0216     return d->mode;
0217 }
0218 
0219 ServerSideDecorationManagerInterface::Mode ServerSideDecorationInterface::preferredMode() const
0220 {
0221     return d->preferredMode.value_or(d->manager->defaultMode());
0222 }
0223 
0224 SurfaceInterface *ServerSideDecorationInterface::surface() const
0225 {
0226     return d->surface;
0227 }
0228 
0229 ServerSideDecorationInterface *ServerSideDecorationInterface::get(SurfaceInterface *surface)
0230 {
0231     return ServerSideDecorationInterfacePrivate::get(surface);
0232 }
0233 
0234 }
0235 
0236 #include "moc_server_decoration.cpp"