diff --git a/src/server/plasmavirtualdesktop_interface.cpp b/src/server/plasmavirtualdesktop_interface.cpp index 9cb1e3a..db2ee59 100644 --- a/src/server/plasmavirtualdesktop_interface.cpp +++ b/src/server/plasmavirtualdesktop_interface.cpp @@ -1,408 +1,416 @@ /**************************************************************************** Copyright 2018 Marco Martin This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . ****************************************************************************/ #include "plasmavirtualdesktop_interface.h" #include "display.h" #include "global_p.h" #include "resource_p.h" #include #include #include #include namespace KWayland { namespace Server { class Q_DECL_HIDDEN PlasmaVirtualDesktopInterface::Private { public: Private(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c); ~Private(); void createResource(wl_resource *parent, quint32 serial); PlasmaVirtualDesktopInterface *q; PlasmaVirtualDesktopManagementInterface *vdm; QVector resources; QString id; QString name; bool active = false; private: static void unbind(wl_resource *resource); static void requestActivateCallback(wl_client *client, wl_resource *resource); static Private *cast(wl_resource *resource) { return reinterpret_cast(wl_resource_get_user_data(resource)); } wl_listener listener; static const struct org_kde_plasma_virtual_desktop_interface s_interface; }; class Q_DECL_HIDDEN PlasmaVirtualDesktopManagementInterface::Private : public Global::Private { public: Private(PlasmaVirtualDesktopManagementInterface *q, Display *d); QVector resources; QList desktops; quint32 rows = 0; quint32 columns = 0; inline QList::const_iterator constFindDesktop(const QString &id); inline QList::iterator findDesktop(const QString &id); private: void bind(wl_client *client, uint32_t version, uint32_t id) override; static void unbind(wl_resource *resource); static Private *cast(wl_resource *r) { return reinterpret_cast(wl_resource_get_user_data(r)); } static void getVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *id); static void requestCreateVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *name, uint32_t position); static void requestRemoveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id); PlasmaVirtualDesktopManagementInterface *q; static const struct org_kde_plasma_virtual_desktop_management_interface s_interface; static const quint32 s_version; }; const quint32 PlasmaVirtualDesktopManagementInterface::Private::s_version = 2; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_plasma_virtual_desktop_management_interface PlasmaVirtualDesktopManagementInterface::Private::s_interface = { getVirtualDesktopCallback, requestCreateVirtualDesktopCallback, requestRemoveVirtualDesktopCallback }; #endif inline QList::const_iterator PlasmaVirtualDesktopManagementInterface::Private::constFindDesktop(const QString &id) { return std::find_if( desktops.constBegin(), desktops.constEnd(), [id]( const PlasmaVirtualDesktopInterface *desk ){ return desk->id() == id; } ); } inline QList::iterator PlasmaVirtualDesktopManagementInterface::Private::findDesktop(const QString &id) { return std::find_if( desktops.begin(), desktops.end(), [id]( const PlasmaVirtualDesktopInterface *desk ){ return desk->id() == id; } ); } void PlasmaVirtualDesktopManagementInterface::Private::getVirtualDesktopCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *id) { Q_UNUSED(client) auto s = cast(resource); auto i = s->constFindDesktop(QString::fromUtf8(id)); if (i == s->desktops.constEnd()) { return; } (*i)->d->createResource(resource, serial); } void PlasmaVirtualDesktopManagementInterface::Private::requestCreateVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *name, uint32_t position) { Q_UNUSED(client) auto s = cast(resource); emit s->q->desktopCreateRequested(QString::fromUtf8(name), qBound(0, position, (quint32)s->desktops.count())); } void PlasmaVirtualDesktopManagementInterface::Private::requestRemoveVirtualDesktopCallback(wl_client *client, wl_resource *resource, const char *id) { Q_UNUSED(client) auto s = cast(resource); emit s->q->desktopRemoveRequested(QString::fromUtf8(id)); } PlasmaVirtualDesktopManagementInterface::Private::Private(PlasmaVirtualDesktopManagementInterface *q, Display *d) : Global::Private(d, &org_kde_plasma_virtual_desktop_management_interface, s_version) , q(q) { } void PlasmaVirtualDesktopManagementInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) { auto c = display->getConnection(client); wl_resource *resource = c->createResource(&org_kde_plasma_virtual_desktop_management_interface, qMin(version, s_version), id); if (!resource) { wl_client_post_no_memory(client); return; } resources << resource; wl_resource_set_implementation(resource, &s_interface, this, unbind); quint32 i = 0; for (auto it = desktops.constBegin(); it != desktops.constEnd(); ++it) { org_kde_plasma_virtual_desktop_management_send_desktop_created(resource, (*it)->id().toUtf8().constData(), i++); } + + if (wl_resource_get_version(resource) >= ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) { + org_kde_plasma_virtual_desktop_management_send_rows(resource, rows); + } + org_kde_plasma_virtual_desktop_management_send_done(resource); } void PlasmaVirtualDesktopManagementInterface::Private::unbind(wl_resource *resource) { auto dm = reinterpret_cast(wl_resource_get_user_data(resource)); dm->resources.removeAll(resource); } PlasmaVirtualDesktopManagementInterface::PlasmaVirtualDesktopManagementInterface(Display *display, QObject *parent) : Global(new Private(this, display), parent) { } PlasmaVirtualDesktopManagementInterface::~PlasmaVirtualDesktopManagementInterface() { Q_D(); qDeleteAll(d->desktops); } PlasmaVirtualDesktopManagementInterface::Private *PlasmaVirtualDesktopManagementInterface::d_func() const { return reinterpret_cast(d.data()); } void PlasmaVirtualDesktopManagementInterface::setRows(quint32 rows) { - if (rows == 0) { + Q_D(); + + if (rows == 0 || d->rows == rows) { return; } - Q_D(); + d->rows = rows; + for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { if (wl_resource_get_version(*it) < ORG_KDE_PLASMA_VIRTUAL_DESKTOP_MANAGEMENT_ROWS_SINCE_VERSION) { continue; } org_kde_plasma_virtual_desktop_management_send_rows(*it, rows); } } PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::desktop(const QString &id) { Q_D(); auto i = d->constFindDesktop(id); if (i != d->desktops.constEnd()) { return *i; } return nullptr; } PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::createDesktop(const QString &id, quint32 position) { Q_D(); auto i = d->constFindDesktop(id); if (i != d->desktops.constEnd()) { return *i; } const quint32 actualPosition = qMin(position, (quint32)d->desktops.count()); PlasmaVirtualDesktopInterface *desktop = new PlasmaVirtualDesktopInterface(this); desktop->d->id = id; for (auto it = desktop->d->resources.constBegin(); it != desktop->d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_desktop_id(*it, id.toUtf8().constData()); } //activate the first desktop TODO: to be done here? if (d->desktops.isEmpty()) { desktop->d->active = true; } d->desktops.insert(actualPosition, desktop); for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_management_send_desktop_created(*it, id.toUtf8().constData(), actualPosition); } return desktop; } void PlasmaVirtualDesktopManagementInterface::removeDesktop(const QString &id) { Q_D(); auto deskIt = d->findDesktop(id); if (deskIt == d->desktops.end()) { return; } for (auto it = (*deskIt)->d->resources.constBegin(); it != (*deskIt)->d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_removed(*it); } for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_management_send_desktop_removed(*it, id.toUtf8().constData()); } (*deskIt)->deleteLater(); d->desktops.erase(deskIt); } QList PlasmaVirtualDesktopManagementInterface::desktops() const { Q_D(); return d->desktops; } void PlasmaVirtualDesktopManagementInterface::sendDone() { Q_D(); for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_management_send_done(*it); } } //// PlasmaVirtualDesktopInterface #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_plasma_virtual_desktop_interface PlasmaVirtualDesktopInterface::Private::s_interface = { requestActivateCallback }; #endif void PlasmaVirtualDesktopInterface::Private::requestActivateCallback(wl_client *client, wl_resource *resource) { Q_UNUSED(client) auto s = cast(resource); emit s->q->activateRequested(); } PlasmaVirtualDesktopInterface::Private::Private(PlasmaVirtualDesktopInterface *q, PlasmaVirtualDesktopManagementInterface *c) : q(q), vdm(c) { } PlasmaVirtualDesktopInterface::Private::~Private() { // need to copy, as destroy goes through the destroy listener and modifies the list as we iterate const auto c = resources; for (const auto &r : c) { auto client = wl_resource_get_client(r); org_kde_plasma_virtual_desktop_send_removed(r); wl_resource_destroy(r); wl_client_flush(client); } } void PlasmaVirtualDesktopInterface::Private::unbind(wl_resource *resource) { Private *p = reinterpret_cast(wl_resource_get_user_data(resource)); p->resources.removeAll(resource); } void PlasmaVirtualDesktopInterface::Private::createResource(wl_resource *parent, quint32 serial) { ClientConnection *c = vdm->display()->getConnection(wl_resource_get_client(parent)); wl_resource *resource = c->createResource(&org_kde_plasma_virtual_desktop_interface, wl_resource_get_version(parent), serial); if (!resource) { return; } wl_resource_set_implementation(resource, &s_interface, this, unbind); resources << resource; org_kde_plasma_virtual_desktop_send_desktop_id(resource, id.toUtf8().constData()); if (!name.isEmpty()) { org_kde_plasma_virtual_desktop_send_name(resource, name.toUtf8().constData()); } if (active) { org_kde_plasma_virtual_desktop_send_activated(resource); } c->flush(); } PlasmaVirtualDesktopInterface::PlasmaVirtualDesktopInterface(PlasmaVirtualDesktopManagementInterface *parent) : QObject(parent), d(new Private(this, parent)) { } PlasmaVirtualDesktopInterface::~PlasmaVirtualDesktopInterface() { d->vdm->removeDesktop(id()); } QString PlasmaVirtualDesktopInterface::id() const { return d->id; } void PlasmaVirtualDesktopInterface::setName(const QString &name) { if (d->name == name) { return; } d->name = name; for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_name(*it, name.toUtf8().constData()); } } QString PlasmaVirtualDesktopInterface::name() const { return d->name; } void PlasmaVirtualDesktopInterface::setActive(bool active) { if (d->active == active) { return; } d->active = active; if (active) { for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_activated(*it); } } else { for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_deactivated(*it); } } } bool PlasmaVirtualDesktopInterface::isActive() const { return d->active; } void PlasmaVirtualDesktopInterface::sendDone() { for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_done(*it); } } } }