From e8e360862fb7907959ecdfc3c717a545b7f4f16f Mon Sep 17 00:00:00 2001 From: Tranter Madi Date: Mon, 30 Dec 2019 23:01:10 +0700 Subject: [PATCH] Allow to set the available screen rect/region from outside through dbus Summary: I'm trying to implement the idea of @davidedmundson from this https://phabricator.kde.org/T10172 with my limited knowledge of C++/Qt/KDE/programming. This is the start of a new class so it could lack many things but it's usable. - It allows clients to set the available screen rect/region from outside through dbus. - The final available screen rect/region would be the intersection of all set values. - When a client dies, its values would be removed automatically. Test Plan: + qdbus-qt5 org.kde.plasmashell /StrutManager test org.kde.lattedock LVDS-1 0 24 1366 768 + After killing latte-dock, the values are got only from plasmashellCorona. {F7820969} Reviewers: #plasma, mvourlakos, davidedmundson, mart, apol Reviewed By: #plasma, davidedmundson Subscribers: davidre, plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D25807 --- shell/CMakeLists.txt | 1 + shell/shellcorona.cpp | 14 ++++++- shell/shellcorona.h | 7 ++++ shell/strutmanager.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++ shell/strutmanager.h | 35 ++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 shell/strutmanager.cpp create mode 100644 shell/strutmanager.h diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index 3523cfbc5..7efa9f20d 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -36,6 +36,7 @@ set (plasma_shell_SRCS standaloneappcorona osd.cpp coronatesthelper.cpp + strutmanager.cpp debug.cpp screenpool.cpp softwarerendernotifier.cpp diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp index 127f5f6b6..035043563 100644 --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -21,6 +21,7 @@ */ #include "shellcorona.h" +#include "strutmanager.h" #include @@ -107,7 +108,8 @@ ShellCorona::ShellCorona(QObject *parent) m_addPanelsMenu(nullptr), m_interactiveConsole(nullptr), m_waylandPlasmaShell(nullptr), - m_closingDown(false) + m_closingDown(false), + m_strutManager(new StrutManager(this)) { setupWaylandIntegration(); qmlRegisterUncreatableType("org.kde.plasma.shell", 2, 0, "Desktop", QStringLiteral("It is not possible to create objects of type Desktop")); @@ -1042,6 +1044,11 @@ QRect ShellCorona::screenGeometry(int id) const } QRegion ShellCorona::availableScreenRegion(int id) const +{ + return m_strutManager->availableScreenRegion(id); +} + +QRegion ShellCorona::_availableScreenRegion(int id) const { DesktopView* view = m_desktopViewforId.value(id); if (!view) { @@ -1062,6 +1069,11 @@ QRegion ShellCorona::availableScreenRegion(int id) const } QRect ShellCorona::availableScreenRect(int id) const +{ + return m_strutManager->availableScreenRect(id); +} + +QRect ShellCorona::_availableScreenRect(int id) const { DesktopView *view = m_desktopViewforId.value(id); if (!view) { diff --git a/shell/shellcorona.h b/shell/shellcorona.h index e7aed4291..9ed062d5b 100644 --- a/shell/shellcorona.h +++ b/shell/shellcorona.h @@ -38,6 +38,7 @@ class PanelView; class QMenu; class QScreen; class ScreenPool; +class StrutManager; namespace KActivities { @@ -89,6 +90,10 @@ public: Q_INVOKABLE QRegion availableScreenRegion(int id) const override; Q_INVOKABLE QRect availableScreenRect(int id) const override; + // plasmashellCorona's value + QRegion _availableScreenRegion(int id) const; + QRect _availableScreenRect(int id) const; + Q_INVOKABLE QStringList availableActivities() const; PanelView *panelView(Plasma::Containment *containment) const; @@ -256,6 +261,8 @@ private: KWayland::Client::PlasmaShell *m_waylandPlasmaShell; bool m_closingDown : 1; QString m_testModeLayout; + + StrutManager *m_strutManager; }; #endif // SHELLCORONA_H diff --git a/shell/strutmanager.cpp b/shell/strutmanager.cpp new file mode 100644 index 000000000..a86c39e97 --- /dev/null +++ b/shell/strutmanager.cpp @@ -0,0 +1,84 @@ +#include "strutmanager.h" +#include "shellcorona.h" +#include "screenpool.h" + +#include +#include +#include +#include + +StrutManager::StrutManager(ShellCorona *plasmashellCorona) : QObject(plasmashellCorona), + m_plasmashellCorona(plasmashellCorona), + m_serviceWatcher(new QDBusServiceWatcher(this)) +{ + qDBusRegisterMetaType>(); + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/StrutManager", this, QDBusConnection::ExportAllSlots); + m_serviceWatcher->setConnection(dbus); + + connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, [=](const QString &service) { + m_availableScreenRects.remove(service); + m_availableScreenRegions.remove(service); + m_serviceWatcher->removeWatchedService(service); + + emit m_plasmashellCorona->availableScreenRectChanged(); + }); +} + +QRect StrutManager::availableScreenRect(int id) const +{ + QRect r = m_plasmashellCorona->_availableScreenRect(id); + QHash service; + foreach (service, m_availableScreenRects) { + if (!service.value(id).isNull()) { + r &= service[id]; + } + } + return r; +} + +QRegion StrutManager::availableScreenRegion(int id) const +{ + QRegion r = m_plasmashellCorona->_availableScreenRegion(id); + QHash service; + foreach (service, m_availableScreenRegions) { + if (!service.value(id).isNull()) { + r &= service[id]; + } + } + return r; +} + +void StrutManager::setAvailableScreenRect(const QString &service, const QString &screenName, const QRect &rect) { + int id = m_plasmashellCorona->screenPool()->id(screenName); + if (id == -1 || m_availableScreenRects.value(service).value(id) == rect || !addWatchedService(service)) { + return; + } + m_availableScreenRects[service][id] = rect; + emit m_plasmashellCorona->availableScreenRectChanged(); +} + +void StrutManager::setAvailableScreenRegion(const QString &service, const QString &screenName, const QList &rects) { + int id = m_plasmashellCorona->screenPool()->id(screenName); + QRegion region; + foreach(QRect rect, rects) { + region += rect; + } + + if (id == -1 || m_availableScreenRegions.value(service).value(id) == region || !addWatchedService(service)) { + return; + } + m_availableScreenRegions[service][id] = region; + emit m_plasmashellCorona->availableScreenRegionChanged(); +} + +bool StrutManager::addWatchedService(const QString &service) { + if (!m_serviceWatcher->watchedServices().contains(service)) { + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(service)) { + return false; + } + m_serviceWatcher->addWatchedService(service); + } + return true; +} diff --git a/shell/strutmanager.h b/shell/strutmanager.h new file mode 100644 index 000000000..1318ab3ad --- /dev/null +++ b/shell/strutmanager.h @@ -0,0 +1,35 @@ +#ifndef STRUTMANAGER_H +#define STRUTMANAGER_H + +#include +#include + +class QDBusServiceWatcher; +class ShellCorona; + +class StrutManager : public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface","org.kde.PlasmaShell.StrutManager") + + public: + explicit StrutManager(ShellCorona *plasmashellCorona); + + QRect availableScreenRect(int id) const; + QRegion availableScreenRegion(int id) const; + + public Q_SLOTS: + void setAvailableScreenRect(const QString &service, const QString &screenName, const QRect &rect); + void setAvailableScreenRegion(const QString &service, const QString &screenName, const QList &rects); + + private: + ShellCorona *m_plasmashellCorona; + + QDBusServiceWatcher *m_serviceWatcher; + bool addWatchedService(const QString &service); + + QHash > m_availableScreenRects; + QHash > m_availableScreenRegions; +}; + +#endif