diff --git a/libtaskmanager/virtualdesktopinfo.cpp b/libtaskmanager/virtualdesktopinfo.cpp --- a/libtaskmanager/virtualdesktopinfo.cpp +++ b/libtaskmanager/virtualdesktopinfo.cpp @@ -27,6 +27,10 @@ #include #include +#include +#include +#include +#include #include @@ -197,14 +201,23 @@ } #endif +static const QString s_serviceName(QStringLiteral("org.kde.KWin")); +static const QString s_virtualDesktopsInterface(QStringLiteral("org.kde.KWin.VirtualDesktopManager")); +static const QString s_virtDesktopsPath(QStringLiteral("/VirtualDesktopManager")); +static const QString s_fdoPropertiesInterface(QStringLiteral("org.freedesktop.DBus.Properties")); + class Q_DECL_HIDDEN VirtualDesktopInfo::WaylandPrivate : public VirtualDesktopInfo::Private { +Q_OBJECT + public: WaylandPrivate(VirtualDesktopInfo *q); QVariant currentVirtualDesktop; QStringList virtualDesktops; + uint cachedDesktopLayoutRows = 0; KWayland::Client::PlasmaVirtualDesktopManagement *virtualDesktopManagement = nullptr; + QDBusServiceWatcher *kwinServiceWatcher = nullptr; void init() override; void addDesktop(const QString &id, quint32 position); @@ -217,6 +230,9 @@ void requestActivate(const QVariant &desktop) override; void requestCreateDesktop(quint32 position) override; void requestRemoveDesktop(quint32 position) override; + +public Q_SLOTS: + void handleDesktopLayoutRowsChanged(uint rows); }; VirtualDesktopInfo::WaylandPrivate::WaylandPrivate(VirtualDesktopInfo *q) @@ -270,6 +286,61 @@ ); registry->setup(); + + kwinServiceWatcher = new QDBusServiceWatcher(s_serviceName, + QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange); + + QObject::connect(kwinServiceWatcher, &QDBusServiceWatcher::serviceRegistered, + this, [this]() { + QDBusConnection::sessionBus().connect( + s_serviceName, + s_virtDesktopsPath, + s_virtualDesktopsInterface, + QStringLiteral("rowsChanged"), + this, + SLOT(handleDesktopLayoutRowsChanged(uint))); + }); + + QObject::connect(kwinServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, + this, [this]() { + QDBusConnection::sessionBus().disconnect( + s_serviceName, + s_virtDesktopsPath, + s_virtualDesktopsInterface, + QStringLiteral("rowsChanged"), + this, + SLOT(handleDesktopLayoutRowsChanged(uint))); + } + ); + + QDBusConnection::sessionBus().connect( + s_serviceName, + s_virtDesktopsPath, + s_virtualDesktopsInterface, + QStringLiteral("rowsChanged"), + this, + SLOT(handleDesktopLayoutRowsChanged(uint))); + + auto callFinished = [this](QDBusPendingCallWatcher *call) { + QDBusPendingReply reply = *call; + + handleDesktopLayoutRowsChanged(reply.value().toUInt()); + + call->deleteLater(); + }; + + auto call = QDBusMessage::createMethodCall( + s_serviceName, + s_virtDesktopsPath, + s_fdoPropertiesInterface, + QStringLiteral("Get")); + + call.setArguments({s_virtualDesktopsInterface, QStringLiteral("rows")}); + + QDBusPendingCall pending = QDBusConnection::sessionBus().asyncCall(call); + + const QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, callFinished); } void VirtualDesktopInfo::WaylandPrivate::addDesktop(const QString &id, quint32 position) @@ -342,9 +413,7 @@ int VirtualDesktopInfo::WaylandPrivate::desktopLayoutRows() const { - // TODO FIXME: We don't have virtual desktop layout information in the Wayland - // protocol yet. - return 0; + return (int)cachedDesktopLayoutRows; } void VirtualDesktopInfo::WaylandPrivate::requestActivate(const QVariant &desktop) @@ -374,6 +443,15 @@ virtualDesktopManagement->requestRemoveVirtualDesktop(virtualDesktops.at(position)); } +void VirtualDesktopInfo::WaylandPrivate::handleDesktopLayoutRowsChanged(uint rows) +{ + if (cachedDesktopLayoutRows != rows) { + cachedDesktopLayoutRows = rows; + + emit desktopLayoutRowsChanged(); + } +} + VirtualDesktopInfo::Private* VirtualDesktopInfo::d = nullptr; VirtualDesktopInfo::VirtualDesktopInfo(QObject *parent) : QObject(parent)