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