File indexing completed on 2024-05-19 16:35:23

0001 /*
0002     SPDX-FileCopyrightText: 2018 Marco Martin <notmart@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "plasmavirtualdesktop_interface.h"
0007 #include "display.h"
0008 
0009 #include <QDebug>
0010 #include <QTimer>
0011 
0012 #include <qwayland-server-org-kde-plasma-virtual-desktop.h>
0013 #include <wayland-server.h>
0014 
0015 namespace KWaylandServer
0016 {
0017 static const quint32 s_version = 2;
0018 
0019 class PlasmaVirtualDesktopInterfacePrivate : public QtWaylandServer::org_kde_plasma_virtual_desktop
0020 {
0021 public:
0022     PlasmaVirtualDesktopInterfacePrivate(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c);
0023     ~PlasmaVirtualDesktopInterfacePrivate();
0024 
0025     PlasmaVirtualDesktopInterface *q;
0026     PlasmaVirtualDesktopManagementInterface *vdm;
0027 
0028     QString id;
0029     QString name;
0030     bool active = false;
0031 
0032 protected:
0033     void org_kde_plasma_virtual_desktop_bind_resource(Resource *resource) override;
0034     void org_kde_plasma_virtual_desktop_request_activate(Resource *resource) override;
0035 };
0036 
0037 class PlasmaVirtualDesktopManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_virtual_desktop_management
0038 {
0039 public:
0040     PlasmaVirtualDesktopManagementInterfacePrivate(PlasmaVirtualDesktopManagementInterface *_q, Display *display);
0041 
0042     QList<PlasmaVirtualDesktopInterface *> desktops;
0043     quint32 rows = 0;
0044     quint32 columns = 0;
0045     PlasmaVirtualDesktopManagementInterface *q;
0046 
0047     inline QList<PlasmaVirtualDesktopInterface *>::const_iterator constFindDesktop(const QString &id);
0048     inline QList<PlasmaVirtualDesktopInterface *>::iterator findDesktop(const QString &id);
0049 
0050 protected:
0051     void org_kde_plasma_virtual_desktop_management_get_virtual_desktop(Resource *resource, uint32_t id, const QString &desktop_id) override;
0052     void org_kde_plasma_virtual_desktop_management_request_create_virtual_desktop(Resource *resource, const QString &name, uint32_t position) override;
0053     void org_kde_plasma_virtual_desktop_management_request_remove_virtual_desktop(Resource *resource, const QString &desktop_id) override;
0054     void org_kde_plasma_virtual_desktop_management_bind_resource(Resource *resource) override;
0055 };
0056 
0057 inline QList<PlasmaVirtualDesktopInterface *>::const_iterator PlasmaVirtualDesktopManagementInterfacePrivate::constFindDesktop(const QString &id)
0058 {
0059     return std::find_if(desktops.constBegin(), desktops.constEnd(), [id](const PlasmaVirtualDesktopInterface *desk) {
0060         return desk->id() == id;
0061     });
0062 }
0063 
0064 inline QList<PlasmaVirtualDesktopInterface *>::iterator PlasmaVirtualDesktopManagementInterfacePrivate::findDesktop(const QString &id)
0065 {
0066     return std::find_if(desktops.begin(), desktops.end(), [id](const PlasmaVirtualDesktopInterface *desk) {
0067         return desk->id() == id;
0068     });
0069 }
0070 
0071 void PlasmaVirtualDesktopManagementInterfacePrivate::org_kde_plasma_virtual_desktop_management_get_virtual_desktop(Resource *resource,
0072                                                                                                                    uint32_t id,
0073                                                                                                                    const QString &desktop_id)
0074 {
0075     auto i = constFindDesktop(desktop_id);
0076     if (i == desktops.constEnd()) {
0077         return;
0078     }
0079 
0080     (*i)->d->add(resource->client(), id, resource->version());
0081 }
0082 
0083 void PlasmaVirtualDesktopManagementInterfacePrivate::org_kde_plasma_virtual_desktop_management_request_create_virtual_desktop(Resource *resource,
0084                                                                                                                               const QString &name,
0085                                                                                                                               uint32_t position)
0086 {
0087     Q_EMIT q->desktopCreateRequested(name, std::clamp<quint32>(position, 0, desktops.size()));
0088 }
0089 
0090 void PlasmaVirtualDesktopManagementInterfacePrivate::org_kde_plasma_virtual_desktop_management_request_remove_virtual_desktop(Resource *resource,
0091                                                                                                                               const QString &desktop_id)
0092 {
0093     Q_EMIT q->desktopRemoveRequested(desktop_id);
0094 }
0095 
0096 PlasmaVirtualDesktopManagementInterfacePrivate::PlasmaVirtualDesktopManagementInterfacePrivate(PlasmaVirtualDesktopManagementInterface *_q, Display *display)
0097     : QtWaylandServer::org_kde_plasma_virtual_desktop_management(*display, s_version)
0098     , q(_q)
0099 {
0100 }
0101 
0102 void PlasmaVirtualDesktopManagementInterfacePrivate::org_kde_plasma_virtual_desktop_management_bind_resource(Resource *resource)
0103 {
0104     quint32 i = 0;
0105     for (auto it = desktops.constBegin(); it != desktops.constEnd(); ++it) {
0106         send_desktop_created(resource->handle, (*it)->id(), i++);
0107     }
0108 
0109     if (resource->version() >= ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) {
0110         send_rows(resource->handle, rows);
0111     }
0112 
0113     send_done(resource->handle);
0114 }
0115 
0116 PlasmaVirtualDesktopManagementInterface::PlasmaVirtualDesktopManagementInterface(Display *display, QObject *parent)
0117     : QObject(parent)
0118     , d(new PlasmaVirtualDesktopManagementInterfacePrivate(this, display))
0119 {
0120 }
0121 
0122 PlasmaVirtualDesktopManagementInterface::~PlasmaVirtualDesktopManagementInterface()
0123 {
0124     qDeleteAll(d->desktops);
0125 }
0126 
0127 void PlasmaVirtualDesktopManagementInterface::setRows(quint32 rows)
0128 {
0129     if (rows == 0 || d->rows == rows) {
0130         return;
0131     }
0132 
0133     d->rows = rows;
0134 
0135     const auto clientResources = d->resourceMap();
0136     for (auto resource : clientResources) {
0137         if (resource->version() < ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) {
0138             continue;
0139         }
0140         d->send_rows(resource->handle, rows);
0141     }
0142 }
0143 
0144 PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::desktop(const QString &id)
0145 {
0146     auto i = d->constFindDesktop(id);
0147     if (i != d->desktops.constEnd()) {
0148         return *i;
0149     }
0150     return nullptr;
0151 }
0152 
0153 PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::createDesktop(const QString &id, quint32 position)
0154 {
0155     auto i = d->constFindDesktop(id);
0156     if (i != d->desktops.constEnd()) {
0157         return *i;
0158     }
0159 
0160     const quint32 actualPosition = std::min(position, (quint32)d->desktops.count());
0161 
0162     auto desktop = new PlasmaVirtualDesktopInterface(this);
0163     desktop->d->id = id;
0164 
0165     const auto desktopClientResources = desktop->d->resourceMap();
0166     for (auto resource : desktopClientResources) {
0167         desktop->d->send_desktop_id(resource->handle, id);
0168     }
0169 
0170     // activate the first desktop TODO: to be done here?
0171     if (d->desktops.isEmpty()) {
0172         desktop->d->active = true;
0173     }
0174 
0175     d->desktops.insert(actualPosition, desktop);
0176 
0177     const auto clientResources = d->resourceMap();
0178     for (auto resource : clientResources) {
0179         d->send_desktop_created(resource->handle, id, actualPosition);
0180     }
0181 
0182     return desktop;
0183 }
0184 
0185 void PlasmaVirtualDesktopManagementInterface::removeDesktop(const QString &id)
0186 {
0187     auto deskIt = d->findDesktop(id);
0188     if (deskIt == d->desktops.end()) {
0189         return;
0190     }
0191 
0192     const auto desktopClientResources = (*deskIt)->d->resourceMap();
0193     for (auto resource : desktopClientResources) {
0194         (*deskIt)->d->send_removed(resource->handle);
0195     }
0196 
0197     const auto clientResources = d->resourceMap();
0198     for (auto resource : clientResources) {
0199         d->send_desktop_removed(resource->handle, id);
0200     }
0201 
0202     (*deskIt)->deleteLater();
0203     d->desktops.erase(deskIt);
0204 }
0205 
0206 QList<PlasmaVirtualDesktopInterface *> PlasmaVirtualDesktopManagementInterface::desktops() const
0207 {
0208     return d->desktops;
0209 }
0210 
0211 void PlasmaVirtualDesktopManagementInterface::sendDone()
0212 {
0213     const auto clientResources = d->resourceMap();
0214     for (auto resource : clientResources) {
0215         d->send_done(resource->handle);
0216     }
0217 }
0218 
0219 //// PlasmaVirtualDesktopInterface
0220 
0221 void PlasmaVirtualDesktopInterfacePrivate::org_kde_plasma_virtual_desktop_request_activate(Resource *resource)
0222 {
0223     Q_EMIT q->activateRequested();
0224 }
0225 
0226 PlasmaVirtualDesktopInterfacePrivate::PlasmaVirtualDesktopInterfacePrivate(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c)
0227     : QtWaylandServer::org_kde_plasma_virtual_desktop()
0228     , q(q)
0229     , vdm(c)
0230 {
0231 }
0232 
0233 PlasmaVirtualDesktopInterfacePrivate::~PlasmaVirtualDesktopInterfacePrivate()
0234 {
0235     const auto clientResources = resourceMap();
0236     for (Resource *resource : clientResources) {
0237         send_removed(resource->handle);
0238         wl_resource_destroy(resource->handle);
0239     }
0240 }
0241 
0242 void PlasmaVirtualDesktopInterfacePrivate::org_kde_plasma_virtual_desktop_bind_resource(Resource *resource)
0243 {
0244     send_desktop_id(resource->handle, id);
0245 
0246     if (!name.isEmpty()) {
0247         send_name(resource->handle, name);
0248     }
0249 
0250     if (active) {
0251         send_activated(resource->handle);
0252     }
0253 }
0254 
0255 PlasmaVirtualDesktopInterface::PlasmaVirtualDesktopInterface(PlasmaVirtualDesktopManagementInterface *parent)
0256     : QObject()
0257     , d(new PlasmaVirtualDesktopInterfacePrivate(this, parent))
0258 {
0259 }
0260 
0261 PlasmaVirtualDesktopInterface::~PlasmaVirtualDesktopInterface()
0262 {
0263     d->vdm->removeDesktop(id());
0264 }
0265 
0266 QString PlasmaVirtualDesktopInterface::id() const
0267 {
0268     return d->id;
0269 }
0270 
0271 void PlasmaVirtualDesktopInterface::setName(const QString &name)
0272 {
0273     if (d->name == name) {
0274         return;
0275     }
0276 
0277     d->name = name;
0278 
0279     const auto clientResources = d->resourceMap();
0280     for (auto resource : clientResources) {
0281         d->send_name(resource->handle, name);
0282     }
0283 }
0284 
0285 QString PlasmaVirtualDesktopInterface::name() const
0286 {
0287     return d->name;
0288 }
0289 
0290 void PlasmaVirtualDesktopInterface::setActive(bool active)
0291 {
0292     if (d->active == active) {
0293         return;
0294     }
0295 
0296     d->active = active;
0297     const auto clientResources = d->resourceMap();
0298 
0299     if (active) {
0300         for (auto resource : clientResources) {
0301             d->send_activated(resource->handle);
0302         }
0303     } else {
0304         for (auto resource : clientResources) {
0305             d->send_deactivated(resource->handle);
0306         }
0307     }
0308 }
0309 
0310 bool PlasmaVirtualDesktopInterface::isActive() const
0311 {
0312     return d->active;
0313 }
0314 
0315 void PlasmaVirtualDesktopInterface::sendDone()
0316 {
0317     const auto clientResources = d->resourceMap();
0318     for (auto resource : clientResources) {
0319         d->send_done(resource->handle);
0320     }
0321 }
0322 
0323 }