File indexing completed on 2025-03-16 11:22:41
0001 /* 0002 SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "screengeometries.h" 0007 0008 //!local 0009 #include "../../lattecorona.h" 0010 #include "../../screenpool.h" 0011 #include "../../view/view.h" 0012 #include "../../layout/genericlayout.h" 0013 #include "../../layouts/manager.h" 0014 #include "../../settings/universalsettings.h" 0015 0016 // Qt 0017 #include <QDebug> 0018 #include <QtDBus> 0019 0020 0021 #define LATTESERVICE "org.kde.lattedock" 0022 #define PLASMASERVICE "org.kde.plasmashell" 0023 #define PLASMASTRUTNAMESPACE "org.kde.PlasmaShell.StrutManager" 0024 0025 #define PUBLISHINTERVAL 1000 0026 0027 namespace Latte { 0028 namespace PlasmaExtended { 0029 0030 ScreenGeometries::ScreenGeometries(Latte::Corona *parent) 0031 : QObject(parent), 0032 m_corona(parent), 0033 m_plasmaServiceWatcher(new QDBusServiceWatcher(this)) 0034 { 0035 qDBusRegisterMetaType<QList<QRect>>(); 0036 0037 m_startupInitTimer.setInterval(2500); 0038 m_startupInitTimer.setSingleShot(true); 0039 connect(&m_startupInitTimer, &QTimer::timeout, this, &ScreenGeometries::init); 0040 0041 m_publishTimer.setInterval(PUBLISHINTERVAL); 0042 m_publishTimer.setSingleShot(true); 0043 connect(&m_publishTimer, &QTimer::timeout, this, &ScreenGeometries::updateGeometries); 0044 0045 m_startupInitTimer.start(); 0046 0047 m_plasmaServiceWatcher->setConnection(QDBusConnection::sessionBus()); 0048 m_plasmaServiceWatcher->setWatchedServices(QStringList({PLASMASERVICE})); 0049 connect(m_plasmaServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this](const QString & serviceName) { 0050 if (serviceName == PLASMASERVICE && !m_plasmaInterfaceAvailable) { 0051 init(); 0052 } 0053 }); 0054 } 0055 0056 ScreenGeometries::~ScreenGeometries() 0057 { 0058 qDebug() << "Plasma Extended Screen Geometries :: Deleted..."; 0059 } 0060 0061 void ScreenGeometries::init() 0062 { 0063 qDebug() << " PLASMA STRUTS MANAGER :: checking availability...."; 0064 bool serviceavailable{false}; 0065 0066 if (QDBusConnection::sessionBus().interface()) { 0067 serviceavailable = QDBusConnection::sessionBus().interface()->isServiceRegistered(PLASMASERVICE).value(); 0068 qDebug() << "PLASMA STRUTS MANAGER :: interface availability :: " << QDBusConnection::sessionBus().interface()->isServiceRegistered(PLASMASERVICE).value(); 0069 } 0070 0071 connect(m_corona->universalSettings(), &Latte::UniversalSettings::isAvailableGeometryBroadcastedToPlasmaChanged, this, &ScreenGeometries::onBroadcastToPlasmaChanged); 0072 0073 if (serviceavailable) { 0074 m_plasmaInterfaceAvailable = true; 0075 0076 qDebug() << " PLASMA STRUTS MANAGER :: is available..."; 0077 0078 connect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &ScreenGeometries::availableScreenGeometryChangedFrom); 0079 connect(m_corona, &Latte::Corona::availableScreenRegionChangedFrom, this, &ScreenGeometries::availableScreenGeometryChangedFrom); 0080 0081 connect(m_corona->layoutsManager()->synchronizer(), &Latte::Layouts::Synchronizer::centralLayoutsChanged, this, [&]() { 0082 m_publishTimer.start(); 0083 }); 0084 0085 connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, [&]() { 0086 if (m_corona->universalSettings()->isAvailableGeometryBroadcastedToPlasma()) { 0087 m_publishTimer.start(); 0088 } 0089 }); 0090 0091 if (m_corona->universalSettings()->isAvailableGeometryBroadcastedToPlasma()) { 0092 m_publishTimer.start(); 0093 } 0094 } 0095 } 0096 0097 bool ScreenGeometries::screenIsActive(const QString &screenName) const 0098 { 0099 for (QScreen *screen : qGuiApp->screens()) { 0100 if (screen->name() == screenName) { 0101 return true; 0102 } 0103 } 0104 0105 return false; 0106 } 0107 0108 void ScreenGeometries::onBroadcastToPlasmaChanged() 0109 { 0110 if (m_corona->universalSettings()->isAvailableGeometryBroadcastedToPlasma()) { 0111 m_publishTimer.start(); 0112 } else { 0113 clearGeometries(); 0114 } 0115 } 0116 0117 void ScreenGeometries::setPlasmaAvailableScreenRect(const QString &screenName, const QRect &rect) 0118 { 0119 QDBusMessage message = QDBusMessage::createMethodCall(PLASMASERVICE, 0120 "/StrutManager", 0121 PLASMASTRUTNAMESPACE, 0122 "setAvailableScreenRect"); 0123 QVariantList args; 0124 0125 args << LATTESERVICE 0126 << screenName 0127 << rect; 0128 0129 message.setArguments(args); 0130 QDBusConnection::sessionBus().call(message, QDBus::NoBlock); 0131 } 0132 0133 void ScreenGeometries::setPlasmaAvailableScreenRegion(const QString &screenName, const QRegion ®ion) 0134 { 0135 QDBusMessage message = QDBusMessage::createMethodCall(PLASMASERVICE, 0136 "/StrutManager", 0137 PLASMASTRUTNAMESPACE, 0138 "setAvailableScreenRegion"); 0139 0140 QVariant regionvariant; 0141 0142 QList<QRect> rects; 0143 if (!region.isNull()) { 0144 //! transorm QRegion to QList<QRect> in order to be sent through dbus 0145 foreach (const QRect &rect, region) { 0146 rects << rect; 0147 } 0148 } else { 0149 rects << QRect(); 0150 } 0151 regionvariant = QVariant::fromValue(rects); 0152 0153 QVariantList args; 0154 0155 args << LATTESERVICE 0156 << screenName 0157 << regionvariant; 0158 0159 message.setArguments(args); 0160 QDBusConnection::sessionBus().call(message, QDBus::NoBlock); 0161 } 0162 0163 void ScreenGeometries::clearGeometries() 0164 { 0165 if (!m_plasmaInterfaceAvailable) { 0166 return; 0167 } 0168 0169 for (QScreen *screen : qGuiApp->screens()) { 0170 QString scrName = screen->name(); 0171 int scrId = m_corona->screenPool()->id(screen->name()); 0172 0173 if (m_corona->screenPool()->hasScreenId(scrId)) { 0174 setPlasmaAvailableScreenRect(scrName, QRect()); 0175 setPlasmaAvailableScreenRegion(scrName, QRegion()); 0176 } 0177 } 0178 0179 m_lastAvailableRect.clear(); 0180 m_lastAvailableRegion.clear(); 0181 } 0182 0183 void ScreenGeometries::updateGeometries() 0184 { 0185 if (!m_plasmaInterfaceAvailable || !m_corona->universalSettings()->isAvailableGeometryBroadcastedToPlasma()) { 0186 return; 0187 } 0188 0189 QStringList availableScreenNames; 0190 0191 qDebug() << " PLASMA SCREEN GEOMETRIES, LAST AVAILABLE SCREEN RECTS :: " << m_lastAvailableRect; 0192 0193 QStringList clearedScreenNames; 0194 0195 //! check for available geometries changes 0196 for (QScreen *screen : qGuiApp->screens()) { 0197 QString scrName = screen->name(); 0198 int scrId = m_corona->screenPool()->id(screen->name()); 0199 0200 qDebug() << " PLASMA SCREEN GEOMETRIES, SCREEN :: " << scrId << " - " << scrName; 0201 0202 if (m_corona->screenPool()->hasScreenId(scrId)) { 0203 QRect availableRect = m_corona->availableScreenRectWithCriteria(scrId, 0204 QString(), 0205 m_ignoreModes, 0206 QList<Plasma::Types::Location>(), 0207 true, 0208 true); 0209 0210 QRegion availableRegion = m_corona->availableScreenRegionWithCriteria(scrId, 0211 QString(), 0212 m_ignoreModes, 0213 QList<Plasma::Types::Location>(), 0214 true, 0215 true); 0216 0217 bool clearedScreen = (availableRect == screen->geometry()); 0218 0219 if (!clearedScreen) { 0220 //! Disable checks because of the workaround concerning plasma desktop behavior 0221 if (!m_lastAvailableRect.contains(scrName) || m_lastAvailableRect[scrName] != availableRect) { 0222 m_lastAvailableRect[scrName] = availableRect; 0223 setPlasmaAvailableScreenRect(scrName, availableRect); 0224 qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE RECT :: " << screen->name() << " : " << availableRect; 0225 } 0226 0227 if (!m_lastAvailableRegion.contains(scrName) || m_lastAvailableRegion[scrName] != availableRegion) { 0228 m_lastAvailableRegion[scrName] = availableRegion; 0229 setPlasmaAvailableScreenRegion(scrName, availableRegion); 0230 qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE REGION :: " << screen->name() << " : " << availableRegion; 0231 } 0232 } else { 0233 clearedScreenNames << scrName; 0234 } 0235 } 0236 0237 availableScreenNames << scrName; 0238 } 0239 0240 //! check for inactive screens that were published previously 0241 for (QString &lastScrName : m_lastScreenNames) { 0242 bool scractive = screenIsActive(lastScrName); 0243 0244 if (!scractive || clearedScreenNames.contains(lastScrName)) { 0245 //! screen became inactive and its geometries could be unpublished 0246 setPlasmaAvailableScreenRect(lastScrName, QRect()); 0247 setPlasmaAvailableScreenRegion(lastScrName, QRegion()); 0248 0249 m_lastAvailableRect.remove(lastScrName); 0250 m_lastAvailableRegion.remove(lastScrName); 0251 } 0252 0253 if (!scractive) { 0254 qDebug() << " PLASMA SCREEN GEOMETRIES, INACTIVE SCREEN :: " << lastScrName; 0255 } else if (clearedScreenNames.contains(lastScrName)) { 0256 qDebug() << " PLASMA SCREEN GEOMETRIES, CLEARED SCREEN :: " << lastScrName; 0257 } 0258 } 0259 0260 m_lastScreenNames = availableScreenNames; 0261 } 0262 0263 void ScreenGeometries::availableScreenGeometryChangedFrom(Latte::View *origin) 0264 { 0265 if (m_corona->universalSettings()->isAvailableGeometryBroadcastedToPlasma() && origin && origin->layout() && origin->layout()->isCurrent()) { 0266 m_publishTimer.start(); 0267 } 0268 } 0269 0270 } 0271 }