diff --git a/autotests/client/test_plasma_virtual_desktop.cpp b/autotests/client/test_plasma_virtual_desktop.cpp index e31cd9a..cf0eca3 100644 --- a/autotests/client/test_plasma_virtual_desktop.cpp +++ b/autotests/client/test_plasma_virtual_desktop.cpp @@ -1,404 +1,407 @@ /******************************************************************** 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 . *********************************************************************/ // Qt #include // KWin #include "../../src/client/compositor.h" #include "../../src/client/connection_thread.h" #include "../../src/client/event_queue.h" #include "../../src/client/region.h" #include "../../src/client/registry.h" #include "../../src/client/surface.h" #include "../../src/client/plasmavirtualdesktop.h" #include "../../src/server/display.h" #include "../../src/server/compositor_interface.h" #include "../../src/server/region_interface.h" #include "../../src/server/plasmavirtualdesktop_interface.h" #include "../../src/server/plasmawindowmanagement_interface.h" #include "../../src/client/plasmawindowmanagement.h" using namespace KWayland::Client; class TestVirtualDesktop : public QObject { Q_OBJECT public: explicit TestVirtualDesktop(QObject *parent = nullptr); private Q_SLOTS: void init(); void cleanup(); void testCreate(); void testDestroy(); void testActivate(); void testEnterLeaveDesktop(); private: KWayland::Server::Display *m_display; KWayland::Server::CompositorInterface *m_compositorInterface; KWayland::Server::PlasmaVirtualDesktopManagementInterface *m_plasmaVirtualDesktopManagementInterface; KWayland::Server::PlasmaWindowManagementInterface *m_windowManagementInterface; KWayland::Server::PlasmaWindowInterface *m_windowInterface; KWayland::Client::ConnectionThread *m_connection; KWayland::Client::Compositor *m_compositor; KWayland::Client::PlasmaVirtualDesktopManagement *m_plasmaVirtualDesktopManagement; KWayland::Client::EventQueue *m_queue; KWayland::Client::PlasmaWindowManagement *m_windowManagement; KWayland::Client::PlasmaWindow *m_window; QThread *m_thread; }; static const QString s_socketName = QStringLiteral("kwayland-test-wayland-virtual-desktop-0"); TestVirtualDesktop::TestVirtualDesktop(QObject *parent) : QObject(parent) , m_display(nullptr) , m_compositorInterface(nullptr) , m_connection(nullptr) , m_compositor(nullptr) , m_queue(nullptr) , m_thread(nullptr) { } void TestVirtualDesktop::init() { using namespace KWayland::Server; delete m_display; m_display = new Display(this); m_display->setSocketName(s_socketName); m_display->start(); QVERIFY(m_display->isRunning()); // setup connection m_connection = new KWayland::Client::ConnectionThread; QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected); QVERIFY(connectedSpy.isValid()); m_connection->setSocketName(s_socketName); m_thread = new QThread(this); m_connection->moveToThread(m_thread); m_thread->start(); m_connection->initConnection(); QVERIFY(connectedSpy.wait()); m_queue = new KWayland::Client::EventQueue(this); QVERIFY(!m_queue->isValid()); m_queue->setup(m_connection); QVERIFY(m_queue->isValid()); Registry registry; QSignalSpy compositorSpy(®istry, &Registry::compositorAnnounced); QVERIFY(compositorSpy.isValid()); QSignalSpy plasmaVirtualDesktopManagementSpy(®istry, &Registry::plasmaVirtualDesktopManagementAnnounced); QVERIFY(plasmaVirtualDesktopManagementSpy.isValid()); QSignalSpy windowManagementSpy(®istry, SIGNAL(plasmaWindowManagementAnnounced(quint32,quint32))); QVERIFY(windowManagementSpy.isValid()); QVERIFY(!registry.eventQueue()); registry.setEventQueue(m_queue); QCOMPARE(registry.eventQueue(), m_queue); registry.create(m_connection->display()); QVERIFY(registry.isValid()); registry.setup(); m_compositorInterface = m_display->createCompositor(m_display); m_compositorInterface->create(); QVERIFY(m_compositorInterface->isValid()); QVERIFY(compositorSpy.wait()); m_compositor = registry.createCompositor(compositorSpy.first().first().value(), compositorSpy.first().last().value(), this); m_plasmaVirtualDesktopManagementInterface = m_display->createPlasmaVirtualDesktopManagement(m_display); m_plasmaVirtualDesktopManagementInterface->create(); QVERIFY(m_plasmaVirtualDesktopManagementInterface->isValid()); QVERIFY(plasmaVirtualDesktopManagementSpy.wait()); m_plasmaVirtualDesktopManagement = registry.createPlasmaVirtualDesktopManagement(plasmaVirtualDesktopManagementSpy.first().first().value(), plasmaVirtualDesktopManagementSpy.first().last().value(), this); m_windowManagementInterface = m_display->createPlasmaWindowManagement(m_display); m_windowManagementInterface->create(); QVERIFY(m_windowManagementInterface->isValid()); m_windowManagementInterface->setPlasmaVirtualDesktopManagementInterface(m_plasmaVirtualDesktopManagementInterface); QVERIFY(windowManagementSpy.wait()); m_windowManagement = registry.createPlasmaWindowManagement(windowManagementSpy.first().first().value(), windowManagementSpy.first().last().value(), this); QSignalSpy windowSpy(m_windowManagement, SIGNAL(windowCreated(KWayland::Client::PlasmaWindow *))); QVERIFY(windowSpy.isValid()); m_windowInterface = m_windowManagementInterface->createWindow(this); m_windowInterface->setPid(1337); QVERIFY(windowSpy.wait()); m_window = windowSpy.first().first().value(); } void TestVirtualDesktop::cleanup() { #define CLEANUP(variable) \ if (variable) { \ delete variable; \ variable = nullptr; \ } CLEANUP(m_compositor) CLEANUP(m_plasmaVirtualDesktopManagement) CLEANUP(m_windowManagement) CLEANUP(m_queue) if (m_connection) { m_connection->deleteLater(); m_connection = nullptr; } if (m_thread) { m_thread->quit(); m_thread->wait(); delete m_thread; m_thread = nullptr; } CLEANUP(m_compositorInterface) CLEANUP(m_plasmaVirtualDesktopManagementInterface) CLEANUP(m_windowManagementInterface) CLEANUP(m_display) #undef CLEANUP } void TestVirtualDesktop::testCreate() { QSignalSpy desktopAddedSpy(m_plasmaVirtualDesktopManagement, &PlasmaVirtualDesktopManagement::desktopAdded); QSignalSpy managementDoneSpy(m_plasmaVirtualDesktopManagement, &PlasmaVirtualDesktopManagement::done); //on this createDesktop bind() isn't called already, the desktopadded signals will be sent after bind happened KWayland::Server::PlasmaVirtualDesktopInterface *desktop1Int = m_plasmaVirtualDesktopManagementInterface->createDesktop(QStringLiteral("0-1")); desktop1Int->setName("Desktop 1"); - desktop1Int->setRightNeighbour("0-2"); - desktop1Int->setBottomNeighbour("0-3"); desktopAddedSpy.wait(); - QCOMPARE(desktopAddedSpy.takeFirst().at(0).toString(), QStringLiteral("0-1")); + QList arguments = desktopAddedSpy.takeFirst(); + QCOMPARE(arguments.at(0).toString(), QStringLiteral("0-1")); + QCOMPARE(arguments.at(1).toUInt(), 0); m_plasmaVirtualDesktopManagementInterface->sendDone(); managementDoneSpy.wait(); QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 1); KWayland::Client::PlasmaVirtualDesktop *desktop1 = m_plasmaVirtualDesktopManagement->desktops().first(); QSignalSpy desktop1DoneSpy(desktop1, &PlasmaVirtualDesktop::done); desktop1Int->sendDone(); desktop1DoneSpy.wait(); QCOMPARE(desktop1->id(), QStringLiteral("0-1")); QCOMPARE(desktop1->name(), QStringLiteral("Desktop 1")); - QCOMPARE(desktop1->rightNeighbour(), "0-2"); - QCOMPARE(desktop1->bottomNeighbour(), "0-3"); //on those createDesktop the bind will already be done KWayland::Server::PlasmaVirtualDesktopInterface *desktop2Int = m_plasmaVirtualDesktopManagementInterface->createDesktop(QStringLiteral("0-2")); desktop2Int->setName("Desktop 2"); - desktop2Int->setLeftNeighbour("0-1"); desktopAddedSpy.wait(); - QCOMPARE(desktopAddedSpy.takeFirst().at(0).toString(), QStringLiteral("0-2")); + arguments = desktopAddedSpy.takeFirst(); + QCOMPARE(arguments.at(0).toString(), QStringLiteral("0-2")); + QCOMPARE(arguments.at(1).toUInt(), 1); QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 2); KWayland::Server::PlasmaVirtualDesktopInterface *desktop3Int = m_plasmaVirtualDesktopManagementInterface->createDesktop(QStringLiteral("0-3")); desktop3Int->setName("Desktop 3"); - desktop3Int->setTopNeighbour("0-1"); desktopAddedSpy.wait(); - QCOMPARE(desktopAddedSpy.takeFirst().at(0).toString(), QStringLiteral("0-3")); + arguments = desktopAddedSpy.takeFirst(); + QCOMPARE(arguments.at(0).toString(), QStringLiteral("0-3")); QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 3); m_plasmaVirtualDesktopManagementInterface->sendDone(); managementDoneSpy.wait(); //get the clients KWayland::Client::PlasmaVirtualDesktop *desktop2 = m_plasmaVirtualDesktopManagement->desktops()[1]; QSignalSpy desktop2DoneSpy(desktop2, &PlasmaVirtualDesktop::done); desktop2Int->sendDone(); desktop2DoneSpy.wait(); KWayland::Client::PlasmaVirtualDesktop *desktop3 = m_plasmaVirtualDesktopManagement->desktops()[2]; QSignalSpy desktop3DoneSpy(desktop3, &PlasmaVirtualDesktop::done); desktop3Int->sendDone(); desktop3DoneSpy.wait(); QCOMPARE(desktop1->id(), QStringLiteral("0-1")); QCOMPARE(desktop1->name(), QStringLiteral("Desktop 1")); - QCOMPARE(desktop1->leftNeighbour(), QString()); - QCOMPARE(desktop1->topNeighbour(), QString()); - QCOMPARE(desktop1->rightNeighbour(), "0-2"); - QCOMPARE(desktop1->bottomNeighbour(), "0-3"); QCOMPARE(desktop2->id(), QStringLiteral("0-2")); QCOMPARE(desktop2->name(), QStringLiteral("Desktop 2")); - QCOMPARE(desktop2->leftNeighbour(), "0-1"); - QCOMPARE(desktop2->topNeighbour(), QString()); - QCOMPARE(desktop2->rightNeighbour(), QString()); - QCOMPARE(desktop2->bottomNeighbour(), QString()); QCOMPARE(desktop3->id(), QStringLiteral("0-3")); QCOMPARE(desktop3->name(), QStringLiteral("Desktop 3")); - QCOMPARE(desktop3->leftNeighbour(), QString()); - QCOMPARE(desktop3->topNeighbour(), "0-1"); - QCOMPARE(desktop3->rightNeighbour(), QString()); - QCOMPARE(desktop3->bottomNeighbour(), QString()); + + //coherence of order between client and server + QCOMPARE(m_plasmaVirtualDesktopManagementInterface->desktops().length(), 3); + QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 3); + + for (int i = 0; i < m_plasmaVirtualDesktopManagement->desktops().length(); ++i) { + QCOMPARE(m_plasmaVirtualDesktopManagementInterface->desktops().at(i)->id(), m_plasmaVirtualDesktopManagement->desktops().at(i)->id()); + } } void TestVirtualDesktop::testDestroy() { //rebuild some desktops testCreate(); KWayland::Server::PlasmaVirtualDesktopInterface *desktop1Int = m_plasmaVirtualDesktopManagementInterface->desktops().first(); KWayland::Client::PlasmaVirtualDesktop *desktop1 = m_plasmaVirtualDesktopManagement->desktops().first(); QSignalSpy desktop1IntDestroyedSpy(desktop1Int, &QObject::destroyed); QSignalSpy desktop1DestroyedSpy(desktop1, &QObject::destroyed); QSignalSpy desktop1RemovedSpy(desktop1, &KWayland::Client::PlasmaVirtualDesktop::removed); m_plasmaVirtualDesktopManagementInterface->removeDesktop(QStringLiteral("0-1")); //test that both server and client desktoip interfaces go away desktop1IntDestroyedSpy.wait(); desktop1RemovedSpy.wait(); desktop1DestroyedSpy.wait(); + //coherence of order between client and server + QCOMPARE(m_plasmaVirtualDesktopManagementInterface->desktops().length(), 2); + QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 2); + + for (int i = 0; i < m_plasmaVirtualDesktopManagement->desktops().length(); ++i) { + QCOMPARE(m_plasmaVirtualDesktopManagementInterface->desktops().at(i)->id(), m_plasmaVirtualDesktopManagement->desktops().at(i)->id()); + } + //Test the desktopRemoved signal of the manager, remove another desktop as the signals can't be tested at the same time QSignalSpy desktopManagerRemovedSpy(m_plasmaVirtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopRemoved); m_plasmaVirtualDesktopManagementInterface->removeDesktop(QStringLiteral("0-2")); desktopManagerRemovedSpy.wait(); QCOMPARE(desktopManagerRemovedSpy.takeFirst().at(0).toString(), QStringLiteral("0-2")); QCOMPARE(m_plasmaVirtualDesktopManagementInterface->desktops().length(), 1); QCOMPARE(m_plasmaVirtualDesktopManagement->desktops().length(), 1); } void TestVirtualDesktop::testActivate() { //rebuild some desktops testCreate(); KWayland::Server::PlasmaVirtualDesktopInterface *desktop1Int = m_plasmaVirtualDesktopManagementInterface->desktops().first(); KWayland::Client::PlasmaVirtualDesktop *desktop1 = m_plasmaVirtualDesktopManagement->desktops().first(); QVERIFY(desktop1->active()); QVERIFY(desktop1Int->active()); KWayland::Server::PlasmaVirtualDesktopInterface *desktop2Int = m_plasmaVirtualDesktopManagementInterface->desktops()[1]; KWayland::Client::PlasmaVirtualDesktop *desktop2 = m_plasmaVirtualDesktopManagement->desktops()[1]; QVERIFY(!desktop2Int->active()); QSignalSpy requestActivateSpy(desktop2Int, &KWayland::Server::PlasmaVirtualDesktopInterface::activateRequested); QSignalSpy activatedSpy(desktop2, &KWayland::Client::PlasmaVirtualDesktop::activated); desktop2->requestActivate(); requestActivateSpy.wait(); //activate the desktop that was requested active m_plasmaVirtualDesktopManagementInterface->setActiveDesktop(desktop2->id()); activatedSpy.wait(); //correct state in the server QVERIFY(desktop2Int->active()); QVERIFY(!desktop1Int->active()); //correct state in the client QVERIFY(desktop2Int->active()); QVERIFY(!desktop1Int->active()); //Test the deactivated signal QSignalSpy deactivatedSpy(desktop2, &KWayland::Client::PlasmaVirtualDesktop::deactivated); m_plasmaVirtualDesktopManagementInterface->setActiveDesktop(desktop1->id()); deactivatedSpy.wait(); } void TestVirtualDesktop::testEnterLeaveDesktop() { testCreate(); QSignalSpy enterRequestedSpy(m_windowInterface, &KWayland::Server::PlasmaWindowInterface::enterPlasmaVirtualDesktopRequested); m_window->requestEnterVirtualDesktop(QStringLiteral("0-1")); enterRequestedSpy.wait(); QCOMPARE(enterRequestedSpy.takeFirst().at(0).toString(), QStringLiteral("0-1")); QSignalSpy virtualDesktopEnteredSpy(m_window, &KWayland::Client::PlasmaWindow::plasmaVirtualDesktopEntered); //agree to the request m_windowInterface->addPlasmaVirtualDesktop(QStringLiteral("0-1")); QCOMPARE(m_windowInterface->plasmaVirtualDesktops().length(), 1); QCOMPARE(m_windowInterface->plasmaVirtualDesktops().first(), QStringLiteral("0-1")); //check if the client received the enter virtualDesktopEnteredSpy.wait(); QCOMPARE(virtualDesktopEnteredSpy.takeFirst().at(0).toString(), QStringLiteral("0-1")); QCOMPARE(m_window->plasmaVirtualDesktops().length(), 1); QCOMPARE(m_window->plasmaVirtualDesktops().first(), QStringLiteral("0-1")); //add another desktop, server side m_windowInterface->addPlasmaVirtualDesktop(QStringLiteral("0-3")); virtualDesktopEnteredSpy.wait(); QCOMPARE(virtualDesktopEnteredSpy.takeFirst().at(0).toString(), QStringLiteral("0-3")); QCOMPARE(m_windowInterface->plasmaVirtualDesktops().length(), 2); QCOMPARE(m_window->plasmaVirtualDesktops().length(), 2); QCOMPARE(m_window->plasmaVirtualDesktops()[1], QStringLiteral("0-3")); //try to add an invalid desktop m_windowInterface->addPlasmaVirtualDesktop(QStringLiteral("invalid")); QCOMPARE(m_window->plasmaVirtualDesktops().length(), 2); //remove a desktop QSignalSpy leaveRequestedSpy(m_windowInterface, &KWayland::Server::PlasmaWindowInterface::leavePlasmaVirtualDesktopRequested); m_window->requestLeaveVirtualDesktop(QStringLiteral("0-1")); leaveRequestedSpy.wait(); QCOMPARE(leaveRequestedSpy.takeFirst().at(0).toString(), QStringLiteral("0-1")); QSignalSpy virtualDesktopLeftSpy(m_window, &KWayland::Client::PlasmaWindow::plasmaVirtualDesktopLeft); //agree to the request m_windowInterface->removePlasmaVirtualDesktop(QStringLiteral("0-1")); QCOMPARE(m_windowInterface->plasmaVirtualDesktops().length(), 1); QCOMPARE(m_windowInterface->plasmaVirtualDesktops().first(), QStringLiteral("0-3")); //check if the client received the leave virtualDesktopLeftSpy.wait(); QCOMPARE(virtualDesktopLeftSpy.takeFirst().at(0).toString(), QStringLiteral("0-1")); QCOMPARE(m_window->plasmaVirtualDesktops().length(), 1); QCOMPARE(m_window->plasmaVirtualDesktops().first(), QStringLiteral("0-3")); //Destroy desktop 1 m_plasmaVirtualDesktopManagementInterface->removeDesktop(QStringLiteral("0-3")); //the window should receive a left signal from the destroyed desktop virtualDesktopLeftSpy.wait(); QCOMPARE(m_window->plasmaVirtualDesktops().length(), 0); } QTEST_GUILESS_MAIN(TestVirtualDesktop) #include "test_plasma_virtual_desktop.moc" diff --git a/src/client/plasmavirtualdesktop.cpp b/src/client/plasmavirtualdesktop.cpp index 591cce1..816b143 100644 --- a/src/client/plasmavirtualdesktop.cpp +++ b/src/client/plasmavirtualdesktop.cpp @@ -1,422 +1,352 @@ /**************************************************************************** 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.h" #include "event_queue.h" #include "wayland_pointer_p.h" #include #include #include namespace KWayland { namespace Client { class Q_DECL_HIDDEN PlasmaVirtualDesktopManagement::Private { public: Private(PlasmaVirtualDesktopManagement *q); void setup(org_kde_plasma_virtual_desktop_management *arg); WaylandPointer plasmavirtualdesktopmanagement; EventQueue *queue = nullptr; //is a map to have desktops() return a list always with the same order QMap desktops; + QList desktopsOrder; private: - static void addedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id); + static void addedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id, uint32_t position); static void removedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id); static void doneCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management); PlasmaVirtualDesktopManagement *q; static const org_kde_plasma_virtual_desktop_management_listener s_listener; }; const org_kde_plasma_virtual_desktop_management_listener PlasmaVirtualDesktopManagement::Private::s_listener = { addedCallback, removedCallback, doneCallback }; -void PlasmaVirtualDesktopManagement::Private::addedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id) +void PlasmaVirtualDesktopManagement::Private::addedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id, uint32_t position) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktopmanagement == org_kde_plasma_virtual_desktop_management); const QString stringId = QString::fromUtf8(id); PlasmaVirtualDesktop *vd = p->q->getVirtualDesktop(stringId); Q_ASSERT(vd); - emit p->q->desktopAdded(stringId); + p->desktopsOrder.insert(position, vd); + //TODO: emit a lot of desktopMoved? + + emit p->q->desktopAdded(stringId, position); } void PlasmaVirtualDesktopManagement::Private::removedCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management, const char *id) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktopmanagement == org_kde_plasma_virtual_desktop_management); const QString stringId = QString::fromUtf8(id); PlasmaVirtualDesktop *vd = p->q->getVirtualDesktop(stringId); p->desktops.remove(stringId); + p->desktopsOrder.removeAll(vd); + //TODO: emit a lot of desktopMoved? Q_ASSERT(vd); vd->release(); vd->destroy(); vd->deleteLater(); emit p->q->desktopRemoved(stringId); } void PlasmaVirtualDesktopManagement::Private::doneCallback(void *data, org_kde_plasma_virtual_desktop_management *org_kde_plasma_virtual_desktop_management) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktopmanagement == org_kde_plasma_virtual_desktop_management); emit p->q->done(); } PlasmaVirtualDesktopManagement::PlasmaVirtualDesktopManagement(QObject *parent) : QObject(parent) , d(new Private(this)) { } PlasmaVirtualDesktopManagement::Private::Private(PlasmaVirtualDesktopManagement *q) : q(q) {} void PlasmaVirtualDesktopManagement::Private::setup(org_kde_plasma_virtual_desktop_management *arg) { Q_ASSERT(arg); Q_ASSERT(!plasmavirtualdesktopmanagement); plasmavirtualdesktopmanagement.setup(arg); org_kde_plasma_virtual_desktop_management_add_listener(plasmavirtualdesktopmanagement, &s_listener, this); } PlasmaVirtualDesktopManagement::~PlasmaVirtualDesktopManagement() { release(); } void PlasmaVirtualDesktopManagement::setup(org_kde_plasma_virtual_desktop_management *plasmavirtualdesktopmanagement) { d->setup(plasmavirtualdesktopmanagement); } void PlasmaVirtualDesktopManagement::release() { d->plasmavirtualdesktopmanagement.release(); } void PlasmaVirtualDesktopManagement::destroy() { d->plasmavirtualdesktopmanagement.destroy(); } PlasmaVirtualDesktopManagement::operator org_kde_plasma_virtual_desktop_management*() { return d->plasmavirtualdesktopmanagement; } PlasmaVirtualDesktopManagement::operator org_kde_plasma_virtual_desktop_management*() const { return d->plasmavirtualdesktopmanagement; } bool PlasmaVirtualDesktopManagement::isValid() const { return d->plasmavirtualdesktopmanagement.isValid(); } void PlasmaVirtualDesktopManagement::setEventQueue(EventQueue *queue) { d->queue = queue; } EventQueue *PlasmaVirtualDesktopManagement::eventQueue() { return d->queue; } PlasmaVirtualDesktop *PlasmaVirtualDesktopManagement::getVirtualDesktop(const QString &id) { Q_ASSERT(isValid()); auto i = d->desktops.constFind(id); if (i != d->desktops.constEnd()) { return *i; } auto w = org_kde_plasma_virtual_desktop_management_get_virtual_desktop(d->plasmavirtualdesktopmanagement, id.toUtf8()); if (!w) { return nullptr; } if (d->queue) { d->queue->addProxy(w); } auto desktop = new PlasmaVirtualDesktop(this); desktop->setup(w); d->desktops[id] = desktop; connect(desktop, &QObject::destroyed, this, [this, id] { d->desktops.remove(id); } ); return desktop; } QList PlasmaVirtualDesktopManagement::desktops() const { - return d->desktops.values(); + return d->desktopsOrder; } class Q_DECL_HIDDEN PlasmaVirtualDesktop::Private { public: Private(PlasmaVirtualDesktop *q); void setup(org_kde_plasma_virtual_desktop *arg); WaylandPointer plasmavirtualdesktop; QString id; QString name; - QString topNeighbour; - QString leftNeighbour; - QString rightNeighbour; - QString bottomNeighbour; bool active = false; private: PlasmaVirtualDesktop *q; private: static void idCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char * id); static void nameCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char * name); - static void topNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id); - static void leftNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id); - static void rightNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id); - static void bottomNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id); static void activatedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop); static void deactivatedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop); static void doneCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop); static void removedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop); static const org_kde_plasma_virtual_desktop_listener s_listener; }; const org_kde_plasma_virtual_desktop_listener PlasmaVirtualDesktop::Private::s_listener = { idCallback, nameCallback, - topNeighbourCallback, - leftNeighbourCallback, - rightNeighbourCallback, - bottomNeighbourCallback, activatedCallback, deactivatedCallback, doneCallback, removedCallback }; void PlasmaVirtualDesktop::Private::idCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char * id) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); p->id = QString::fromUtf8(id); } void PlasmaVirtualDesktop::Private::nameCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char * name) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); p->name = QString::fromUtf8(name); } -void PlasmaVirtualDesktop::Private::topNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id) -{ - auto p = reinterpret_cast(data); - Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); - const QString stringId = QString::fromUtf8(id); - if (stringId != p->topNeighbour) { - p->topNeighbour = stringId; - emit p->q->topNeighbourChanged(stringId); - } -} - -void PlasmaVirtualDesktop::Private::leftNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id) -{ - auto p = reinterpret_cast(data); - Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); - const QString stringId = QString::fromUtf8(id); - if (stringId != p->leftNeighbour) { - p->leftNeighbour = stringId; - emit p->q->leftNeighbourChanged(stringId); - } -} - -void PlasmaVirtualDesktop::Private::rightNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id) -{ - auto p = reinterpret_cast(data); - Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); - const QString stringId = QString::fromUtf8(id); - if (stringId != p->rightNeighbour) { - p->rightNeighbour = stringId; - emit p->q->rightNeighbourChanged(stringId); - } -} - -void PlasmaVirtualDesktop::Private::bottomNeighbourCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop, const char *id) -{ - auto p = reinterpret_cast(data); - Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); - const QString stringId = QString::fromUtf8(id); - if (stringId != p->bottomNeighbour) { - p->bottomNeighbour = stringId; - emit p->q->bottomNeighbourChanged(stringId); - } -} - void PlasmaVirtualDesktop::Private::activatedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); p->active = true; emit p->q->activated(); } void PlasmaVirtualDesktop::Private::deactivatedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); p->active = false; emit p->q->deactivated(); } void PlasmaVirtualDesktop::Private::doneCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); emit p->q->done(); } void PlasmaVirtualDesktop::Private::removedCallback(void *data, org_kde_plasma_virtual_desktop *org_kde_plasma_virtual_desktop) { auto p = reinterpret_cast(data); Q_ASSERT(p->plasmavirtualdesktop == org_kde_plasma_virtual_desktop); emit p->q->removed(); } PlasmaVirtualDesktop::Private::Private(PlasmaVirtualDesktop *q) : q(q) { } PlasmaVirtualDesktop::PlasmaVirtualDesktop(QObject *parent) : QObject(parent) , d(new Private(this)) { } void PlasmaVirtualDesktop::Private::setup(org_kde_plasma_virtual_desktop *arg) { Q_ASSERT(arg); Q_ASSERT(!plasmavirtualdesktop); plasmavirtualdesktop.setup(arg); org_kde_plasma_virtual_desktop_add_listener(plasmavirtualdesktop, &s_listener, this); } PlasmaVirtualDesktop::~PlasmaVirtualDesktop() { release(); } void PlasmaVirtualDesktop::setup(org_kde_plasma_virtual_desktop *plasmavirtualdesktop) { d->setup(plasmavirtualdesktop); } void PlasmaVirtualDesktop::release() { d->plasmavirtualdesktop.release(); } void PlasmaVirtualDesktop::destroy() { d->plasmavirtualdesktop.destroy(); } PlasmaVirtualDesktop::operator org_kde_plasma_virtual_desktop*() { return d->plasmavirtualdesktop; } PlasmaVirtualDesktop::operator org_kde_plasma_virtual_desktop*() const { return d->plasmavirtualdesktop; } bool PlasmaVirtualDesktop::isValid() const { return d->plasmavirtualdesktop.isValid(); } void PlasmaVirtualDesktop::requestActivate() { Q_ASSERT(isValid()); org_kde_plasma_virtual_desktop_request_activate(d->plasmavirtualdesktop); } QString PlasmaVirtualDesktop::id() const { return d->id; } QString PlasmaVirtualDesktop::name() const { return d->name; } -QString PlasmaVirtualDesktop::topNeighbour() const -{ - return d->topNeighbour; -} - -QString PlasmaVirtualDesktop::leftNeighbour() const -{ - return d->leftNeighbour; -} - -QString PlasmaVirtualDesktop::rightNeighbour() const -{ - return d->rightNeighbour; -} - -QString PlasmaVirtualDesktop::bottomNeighbour() const -{ - return d->bottomNeighbour; -} - bool PlasmaVirtualDesktop::active() const { return d->active; } } } diff --git a/src/client/plasmavirtualdesktop.h b/src/client/plasmavirtualdesktop.h index a74602c..3c57c4c 100644 --- a/src/client/plasmavirtualdesktop.h +++ b/src/client/plasmavirtualdesktop.h @@ -1,277 +1,267 @@ /**************************************************************************** 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 . ****************************************************************************/ #ifndef KWAYLAND_CLIENT_PLASMAVIRTUALDESKTOP_H #define KWAYLAND_CLIENT_PLASMAVIRTUALDESKTOP_H #include #include struct org_kde_plasma_virtual_desktop_management; struct org_kde_plasma_virtual_desktop; namespace KWayland { namespace Client { class EventQueue; class PlasmaVirtualDesktop; /** * @short Wrapper for the org_kde_plasma_virtual_desktop_management interface. * * This class provides a convenient wrapper for the org_kde_plasma_virtual_desktop_management interface. * * To use this class one needs to interact with the Registry. There are two * possible ways to create the PlasmaVirtualDesktopManagement interface: * @code * PlasmaVirtualDesktopManagement *c = registry->createPlasmaVirtualDesktopManagement(name, version); * @endcode * * This creates the PlasmaVirtualDesktopManagement and sets it up directly. As an alternative this * can also be done in a more low level way: * @code * PlasmaVirtualDesktopManagement *c = new PlasmaVirtualDesktopManagement; * c->setup(registry->bindPlasmaVirtualDesktopManagement(name, version)); * @endcode * * The PlasmaVirtualDesktopManagement can be used as a drop-in replacement for any org_kde_plasma_virtual_desktop_management * pointer as it provides matching cast operators. * @since 5.46 * * @see Registry **/ class KWAYLANDCLIENT_EXPORT PlasmaVirtualDesktopManagement : public QObject { Q_OBJECT public: /** * Creates a new PlasmaVirtualDesktopManagement. * Note: after constructing the PlasmaVirtualDesktopManagement it is not yet valid and one needs * to call setup. In order to get a ready to use PlasmaVirtualDesktopManagement prefer using * Registry::createPlasmaVirtualDesktopManagement. **/ explicit PlasmaVirtualDesktopManagement(QObject *parent = nullptr); virtual ~PlasmaVirtualDesktopManagement(); /** * Setup this PlasmaVirtualDesktopManagement to manage the @p plasmavirtualdesktopmanagement. * When using Registry::createPlasmaVirtualDesktopManagement there is no need to call this * method. **/ void setup(org_kde_plasma_virtual_desktop_management *plasmavirtualdesktopmanagement); /** * @returns @c true if managing a org_kde_plasma_virtual_desktop_management. **/ bool isValid() const; /** * Releases the org_kde_plasma_virtual_desktop_management interface. * After the interface has been released the PlasmaVirtualDesktopManagement instance is no * longer valid and can be setup with another org_kde_plasma_virtual_desktop_management interface. **/ void release(); /** * Destroys the data held by this PlasmaVirtualDesktopManagement. * This method is supposed to be used when the connection to the Wayland * server goes away. If the connection is not valid anymore, it's not * possible to call release anymore as that calls into the Wayland * connection and the call would fail. This method cleans up the data, so * that the instance can be deleted or set up to a new org_kde_plasma_virtual_desktop_management interface * once there is a new connection available. * * It is suggested to connect this method to ConnectionThread::connectionDied: * @code * connect(connection, &ConnectionThread::connectionDied, plasmavirtualdesktopmanagement, &PlasmaVirtualDesktopManagement::destroy); * @endcode * * @see release **/ void destroy(); /** * Sets the @p queue to use for creating objects with this PlasmaVirtualDesktopManagement. **/ void setEventQueue(EventQueue *queue); /** * @returns The event queue to use for creating objects with this PlasmaVirtualDesktopManagement. * The object is owned by the manager and the caller should not delete it. **/ EventQueue *eventQueue(); PlasmaVirtualDesktop *getVirtualDesktop(const QString &id); /** * @returns All the existent virtual desktops */ QList desktops() const; operator org_kde_plasma_virtual_desktop_management*(); operator org_kde_plasma_virtual_desktop_management*() const; Q_SIGNALS: void removed(); /** * Emitted when a new desktop has been added */ - void desktopAdded(const QString &id); + void desktopAdded(const QString &id, quint32 position); /** * Emitted when a desktop has been removed */ void desktopRemoved(const QString &id); /** * This event is sent after all other properties has been * sent after binding to the desktop manager object and after any * other property changes done after that. This allows * changes to the org_kde_plasma_virtual_desktop_management properties * to be seen as atomic, even if they happen via multiple events. */ void done(); private: class Private; QScopedPointer d; }; class KWAYLANDCLIENT_EXPORT PlasmaVirtualDesktop : public QObject { Q_OBJECT public: virtual ~PlasmaVirtualDesktop(); /** * Setup this PlasmaVirtualDesktop to manage the @p plasmavirtualdesktop. * When using PlasmaVirtualDesktopManagement::createPlasmaVirtualDesktop there is no need to call this * method. **/ void setup(org_kde_plasma_virtual_desktop *plasmavirtualdesktop); /** * @returns @c true if managing a org_kde_plasma_virtual_desktop. **/ bool isValid() const; /** * Releases the org_kde_plasma_virtual_desktop interface. * After the interface has been released the PlasmaVirtualDesktop instance is no * longer valid and can be setup with another org_kde_plasma_virtual_desktop interface. **/ void release(); /** * Destroys the data held by this PlasmaVirtualDesktop. * This method is supposed to be used when the connection to the Wayland * server goes away. If the connection is not valid anymore, it's not * possible to call release anymore as that calls into the Wayland * connection and the call would fail. This method cleans up the data, so * that the instance can be deleted or set up to a new org_kde_plasma_virtual_desktop interface * once there is a new connection available. * * It is suggested to connect this method to ConnectionThread::connectionDied: * @code * connect(connection, &ConnectionThread::connectionDied, plasmavirtualdesktop, &PlasmaVirtualDesktop::destroy); * @endcode * * @see release **/ void destroy(); /** * Requests this desktop to be activated. * The server may or may not decide to consent to the request. */ void requestActivate(); /** * @returns The unique id of this desktop. The format of the id is decided by the compositor */ QString id() const; /** * @returns User readable name for the desktop. */ QString name() const; - QString topNeighbour() const; - QString leftNeighbour() const; - QString rightNeighbour() const; - QString bottomNeighbour() const; - /** * @returns True if the desktop is the active one. * when this property changes, activated or deactivated will be emitted. * @see activated * @see deactivated */ bool active() const; operator org_kde_plasma_virtual_desktop*(); operator org_kde_plasma_virtual_desktop*() const; Q_SIGNALS: /** * TODO: activeChanged(bool)? * Emitted when this desktop has been activated by the server */ void activated(); /** * Emitted when this desktop has been activated by the server */ void deactivated(); /** * This event is sent after all other properties has been * sent after binding to the desktop manager object and after any * other property changes done after that. This allows * changes to the org_kde_plasma_virtual_desktop properties * to be seen as atomic, even if they happen via multiple events. */ void done(); /** * This virtual desktop has just been removed by the server: * This object itself is about to be deleted. All windows will * lose the association to this desktop. */ void removed(); - void topNeighbourChanged(const QString &id); - void leftNeighbourChanged(const QString &id); - void rightNeighbourChanged(const QString &id); - void bottomNeighbourChanged(const QString &id); - private: friend class PlasmaVirtualDesktopManagement; explicit PlasmaVirtualDesktop(QObject *parent = nullptr); class Private; QScopedPointer d; }; } } #endif diff --git a/src/client/protocols/plasma-virtual-desktop.xml b/src/client/protocols/plasma-virtual-desktop.xml index da08469..e54b8f0 100644 --- a/src/client/protocols/plasma-virtual-desktop.xml +++ b/src/client/protocols/plasma-virtual-desktop.xml @@ -1,113 +1,98 @@ . ]]> Given the id of a particular virtual desktop, get the corresponding org_kde_plasma_virtual_desktop which represents only the desktop with that id; + + This event is sent after all other properties has been sent after binding to the desktop manager object and after any other property changes done after that. This allows changes to the org_kde_plasma_virtual_desktop_management properties to be seen as atomic, even if they happen via multiple events. The format of the id is decided by the compositor implementation. - - - - - - - - - - - - - - - - - This event is sent after all other properties has been sent after binding to the desktop object and after any other property changes done after that. This allows changes to the org_kde_plasma_virtual_desktop properties to be seen as atomic, even if they happen via multiple events. This virtual desktop has just been removed by the server: All windows will lose the association to this desktop. diff --git a/src/server/plasmavirtualdesktop_interface.cpp b/src/server/plasmavirtualdesktop_interface.cpp index 8be587b..3354d15 100644 --- a/src/server/plasmavirtualdesktop_interface.cpp +++ b/src/server/plasmavirtualdesktop_interface.cpp @@ -1,453 +1,379 @@ /**************************************************************************** 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; - QString topNeighbour; - QString leftNeighbour; - QString rightNeighbour; - QString bottomNeighbour; 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; QMap desktops; + QList desktopsOrder; quint32 rows = 0; quint32 columns = 0; 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 releaseCallback(wl_client *client, wl_resource *resource); 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 = 1; #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct org_kde_plasma_virtual_desktop_management_interface PlasmaVirtualDesktopManagementInterface::Private::s_interface = { getVirtualDesktopCallback, releaseCallback }; #endif 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->desktops.constFind(QString::fromUtf8(id)); if (i == s->desktops.constEnd()) { return; } (*i)->d->createResource(resource, serial); } void PlasmaVirtualDesktopManagementInterface::Private::releaseCallback(wl_client *client, wl_resource *resource) { Q_UNUSED(client) wl_resource_destroy(resource); } 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_added(resource, (*it)->id().toUtf8().constData()); + org_kde_plasma_virtual_desktop_management_send_desktop_added(resource, (*it)->id().toUtf8().constData(), i++); } } 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() {} PlasmaVirtualDesktopManagementInterface::Private *PlasmaVirtualDesktopManagementInterface::d_func() const { return reinterpret_cast(d.data()); } PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::desktop(const QString &id) { Q_D(); auto i = d->desktops.constFind(id); if (i != d->desktops.constEnd()) { return *i; } return nullptr; } PlasmaVirtualDesktopInterface *PlasmaVirtualDesktopManagementInterface::createDesktop(const QString &id) { Q_D(); auto i = d->desktops.constFind(id); if (i != d->desktops.constEnd()) { return *i; } 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_id(*it, id.toUtf8().constData()); } //activate the first desktop TODO: to be done here? if (d->desktops.isEmpty()) { desktop->d->active = true; } d->desktops[id] = desktop; + d->desktopsOrder << desktop; connect(desktop, &QObject::destroyed, this, [this, id] { Q_D(); d->desktops.remove(id); //TODO: activate another desktop? } ); for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { - org_kde_plasma_virtual_desktop_management_send_desktop_added(*it, id.toUtf8().constData()); + org_kde_plasma_virtual_desktop_management_send_desktop_added(*it, id.toUtf8().constData(), d->desktopsOrder.length()-1); } return desktop; } void PlasmaVirtualDesktopManagementInterface::removeDesktop(const QString &id) { Q_D(); auto deskIt = d->desktops.constFind(id); if (deskIt == d->desktops.constEnd()) { 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()); } + d->desktopsOrder.removeAll(*deskIt); (*deskIt)->deleteLater(); } QList PlasmaVirtualDesktopManagementInterface::desktops() const { Q_D(); - return d->desktops.values(); + return d->desktopsOrder; } 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); } } void PlasmaVirtualDesktopManagementInterface::setActiveDesktop(const QString &id) { Q_D(); for (auto it = d->desktops.constBegin(); it != d->desktops.constEnd(); ++it) { auto desktop = *it; if (desktop->id() == id) { desktop->d->active = true; for (auto it = desktop->d->resources.constBegin(); it != desktop->d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_activated(*it); } } else { if (desktop->d->active) { desktop->d->active = false; for (auto it = desktop->d->resources.constBegin(); it != desktop->d->resources.constEnd(); ++it) { org_kde_plasma_virtual_desktop_send_deactivated(*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); if (p->resources.isEmpty()) { p->q->deleteLater(); } } 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_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); } - org_kde_plasma_virtual_desktop_send_left_neighbour(resource, leftNeighbour.toUtf8().constData()); - org_kde_plasma_virtual_desktop_send_top_neighbour(resource, topNeighbour.toUtf8().constData()); - org_kde_plasma_virtual_desktop_send_right_neighbour(resource, rightNeighbour.toUtf8().constData()); - org_kde_plasma_virtual_desktop_send_bottom_neighbour(resource, bottomNeighbour.toUtf8().constData()); - c->flush(); } PlasmaVirtualDesktopInterface::PlasmaVirtualDesktopInterface(PlasmaVirtualDesktopManagementInterface *parent) : QObject(parent), d(new Private(this, parent)) { } PlasmaVirtualDesktopInterface::~PlasmaVirtualDesktopInterface() {} 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::setTopNeighbour(const QString &id) -{ - if (d->topNeighbour == id) { - return; - } - - d->topNeighbour = id; - for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { - org_kde_plasma_virtual_desktop_send_top_neighbour(*it, id.toUtf8().constData()); - } -} - -QString PlasmaVirtualDesktopInterface::topNeighbour() const -{ - return d->topNeighbour; -} - - -void PlasmaVirtualDesktopInterface::setLeftNeighbour(const QString &id) -{ - if (d->leftNeighbour == id) { - return; - } - - d->leftNeighbour = id; - for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { - org_kde_plasma_virtual_desktop_send_left_neighbour(*it, id.toUtf8().constData()); - } -} - -QString PlasmaVirtualDesktopInterface::leftNeighbour() const -{ - return d->leftNeighbour; -} - -void PlasmaVirtualDesktopInterface::setRightNeighbour(const QString &id) -{ - if (d->rightNeighbour == id) { - return; - } - - d->rightNeighbour = id; - for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { - org_kde_plasma_virtual_desktop_send_right_neighbour(*it, id.toUtf8().constData()); - } -} - -QString PlasmaVirtualDesktopInterface::rightNeighbour() const -{ - return d->rightNeighbour; -} - -void PlasmaVirtualDesktopInterface::setBottomNeighbour(const QString &id) -{ - if (d->bottomNeighbour == id) { - return; - } - - d->bottomNeighbour = id; - for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) { - org_kde_plasma_virtual_desktop_send_bottom_neighbour(*it, id.toUtf8().constData()); - } -} - -QString PlasmaVirtualDesktopInterface::bottomNeighbour() const -{ - return d->bottomNeighbour; -} - bool PlasmaVirtualDesktopInterface::active() 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); } } } } diff --git a/src/server/plasmavirtualdesktop_interface.h b/src/server/plasmavirtualdesktop_interface.h index 1574bd6..32d0dfd 100644 --- a/src/server/plasmavirtualdesktop_interface.h +++ b/src/server/plasmavirtualdesktop_interface.h @@ -1,159 +1,147 @@ /**************************************************************************** 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 . ****************************************************************************/ #ifndef KWAYLAND_SERVER_PLASMAVIRTUALDESKTOP_H #define KWAYLAND_SERVER_PLASMAVIRTUALDESKTOP_H #include "global.h" #include "resource.h" #include namespace KWayland { namespace Server { class Display; class PlasmaVirtualDesktopInterface; /** * @short Wrapper for the org_kde_plasma_virtual_desktop_management interface. * * This class provides a convenient wrapper for the org_kde_plasma_virtual_desktop_management interface. * @since 5.46 */ class KWAYLANDSERVER_EXPORT PlasmaVirtualDesktopManagementInterface : public Global { Q_OBJECT public: virtual ~PlasmaVirtualDesktopManagementInterface(); /** * Sets a new layout for this desktop grid. */ void setLayout(quint32 rows, quint32 columns); /** * @returns A desktop identified uniquely by this id. * If not found, nullptr will be returned. * @see createDesktop */ PlasmaVirtualDesktopInterface *desktop(const QString &id); /** * @returns A desktop identified uniquely by this id, if not found * a new desktop will be created for this id. */ PlasmaVirtualDesktopInterface *createDesktop(const QString &id); /** * Removed and destroys the desktop identified by id, if present */ void removeDesktop(const QString &id); /** * @returns All tghe desktops present. */ QList desktops() const; /** * Inform the clients that all the properties have been sent, and * their client-side representation is complete. */ void sendDone(); /** * Sets the desktop identified by id to be the active one. * active desktops are mutually exclusive */ void setActiveDesktop(const QString &id); private: explicit PlasmaVirtualDesktopManagementInterface(Display *display, QObject *parent = nullptr); friend class Display; class Private; Private *d_func() const; }; class KWAYLANDSERVER_EXPORT PlasmaVirtualDesktopInterface : public QObject { Q_OBJECT public: virtual ~PlasmaVirtualDesktopInterface(); /** * @returns the unique id for this desktop. * ids are set at creation time by PlasmaVirtualDesktopManagementInterface::createDesktop * and can't be changed at runtime. */ QString id() const; /** * Sets a new name for this desktop */ void setName(const QString &name); /** * @returns the name for this desktop */ QString name() const; - void setTopNeighbour(const QString &id); - QString topNeighbour() const; - - void setLeftNeighbour(const QString &id); - QString leftNeighbour() const; - - void setRightNeighbour(const QString &id); - QString rightNeighbour() const; - - void setBottomNeighbour(const QString &id); - QString bottomNeighbour() const; - /** * @returns true if this desktop is active. Only one at a time will be. */ bool active() const; /** * Inform the clients that all the properties have been sent, and * their client-side representation is complete. */ void sendDone(); Q_SIGNALS: /** * Emitted when the client asked to activate this desktop: * it's the decision of the server whether to perform the activation or not. */ void activateRequested(); private: explicit PlasmaVirtualDesktopInterface(PlasmaVirtualDesktopManagementInterface *parent); friend class PlasmaVirtualDesktopManagementInterface; class Private; const QScopedPointer d; }; } } #endif