diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -36,6 +36,7 @@ standaloneappcorona osd.cpp coronatesthelper.cpp + strutmanager.cpp debug.cpp screenpool.cpp softwarerendernotifier.cpp diff --git a/shell/shellcorona.h b/shell/shellcorona.h --- a/shell/shellcorona.h +++ b/shell/shellcorona.h @@ -38,6 +38,7 @@ class QMenu; class QScreen; class ScreenPool; +class StrutManager; namespace KActivities { @@ -89,6 +90,10 @@ 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 @@ KWayland::Client::PlasmaShell *m_waylandPlasmaShell; bool m_closingDown : 1; QString m_testModeLayout; + + StrutManager *m_strutManager; }; #endif // SHELLCORONA_H diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -21,6 +21,7 @@ */ #include "shellcorona.h" +#include "strutmanager.h" #include @@ -107,7 +108,8 @@ 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 @@ } 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 @@ } 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/strutmanager.h b/shell/strutmanager.h new file mode 100644 --- /dev/null +++ b/shell/strutmanager.h @@ -0,0 +1,37 @@ +#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); + + void test(QString service, QString screenName, int x, int y, int width, int height); + + private: + ShellCorona *m_plasmashellCorona; + + QDBusServiceWatcher *m_serviceWatcher; + bool addWatchedService(const QString &service); + + QHash > m_availableScreenRects; + QHash > m_availableScreenRegions; +}; + +#endif diff --git a/shell/strutmanager.cpp b/shell/strutmanager.cpp new file mode 100644 --- /dev/null +++ b/shell/strutmanager.cpp @@ -0,0 +1,88 @@ +#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; +} + +void StrutManager::test(QString service, QString screenName, int x, int y, int width, int height) { + setAvailableScreenRect(service, screenName, QRect(x, y, width, height)); +}