File indexing completed on 2024-04-21 16:17:20
0001 /* 0002 * Copyright 2016 Smith AR <audoban@openmailbox.org> 0003 * Michail Vourlakos <mvourlakos@gmail.com> 0004 * 0005 * This file is part of Latte-Dock 0006 * 0007 * Latte-Dock is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU General Public License as 0009 * published by the Free Software Foundation; either version 2 of 0010 * the License, or (at your option) any later version. 0011 * 0012 * Latte-Dock is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License 0018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include "abstractwindowinterface.h" 0022 0023 // local 0024 #include "tracker/schemes.h" 0025 #include "tracker/windowstracker.h" 0026 #include "../lattecorona.h" 0027 0028 // Qt 0029 #include <QDebug> 0030 0031 // KDE 0032 #include <KActivities/Controller> 0033 0034 namespace Latte { 0035 namespace WindowSystem { 0036 0037 #define MAXPLASMAPANELTHICKNESS 96 0038 0039 AbstractWindowInterface::AbstractWindowInterface(QObject *parent) 0040 : QObject(parent) 0041 { 0042 m_activities = new KActivities::Consumer(this); 0043 m_currentActivity = m_activities->currentActivity(); 0044 0045 m_corona = qobject_cast<Latte::Corona *>(parent); 0046 m_windowsTracker = new Tracker::Windows(this); 0047 m_schemesTracker = new Tracker::Schemes(this); 0048 0049 rulesConfig = KSharedConfig::openConfig(QStringLiteral("taskmanagerrulesrc")); 0050 0051 m_windowWaitingTimer.setInterval(150); 0052 m_windowWaitingTimer.setSingleShot(true); 0053 0054 connect(&m_windowWaitingTimer, &QTimer::timeout, this, [&]() { 0055 WindowId wid = m_windowChangedWaiting; 0056 m_windowChangedWaiting = QVariant(); 0057 emit windowChanged(wid); 0058 }); 0059 0060 connect(this, &AbstractWindowInterface::windowRemoved, this, &AbstractWindowInterface::windowRemovedSlot); 0061 0062 // connect(this, &AbstractWindowInterface::windowChanged, this, [&](WindowId wid) { 0063 // qDebug() << "WINDOW CHANGED ::: " << wid; 0064 // }); 0065 0066 connect(m_activities.data(), &KActivities::Consumer::currentActivityChanged, this, [&](const QString &id) { 0067 m_currentActivity = id; 0068 emit currentActivityChanged(); 0069 }); 0070 0071 } 0072 0073 AbstractWindowInterface::~AbstractWindowInterface() 0074 { 0075 m_windowWaitingTimer.stop(); 0076 0077 m_schemesTracker->deleteLater(); 0078 m_windowsTracker->deleteLater(); 0079 } 0080 0081 QString AbstractWindowInterface::currentDesktop() const 0082 { 0083 return m_currentDesktop; 0084 } 0085 0086 QString AbstractWindowInterface::currentActivity() const 0087 { 0088 return m_currentActivity; 0089 } 0090 0091 Latte::Corona *AbstractWindowInterface::corona() 0092 { 0093 return m_corona; 0094 } 0095 0096 Tracker::Schemes *AbstractWindowInterface::schemesTracker() 0097 { 0098 return m_schemesTracker; 0099 } 0100 0101 Tracker::Windows *AbstractWindowInterface::windowsTracker() const 0102 { 0103 return m_windowsTracker; 0104 } 0105 0106 bool AbstractWindowInterface::isIgnored(const WindowId &wid) 0107 { 0108 return m_ignoredWindows.contains(wid); 0109 } 0110 0111 bool AbstractWindowInterface::isPlasmaDesktop(const QRect &wGeometry) const 0112 { 0113 if (wGeometry.isEmpty()) { 0114 return false; 0115 } 0116 0117 for (const auto scr : qGuiApp->screens()) { 0118 if (wGeometry == scr->geometry()) { 0119 return true; 0120 } 0121 } 0122 0123 return false; 0124 } 0125 0126 bool AbstractWindowInterface::isPlasmaPanel(const QRect &wGeometry) const 0127 { 0128 if (wGeometry.isEmpty()) { 0129 return false; 0130 } 0131 0132 bool isTouchingHorizontalEdge{false}; 0133 bool isTouchingVerticalEdge{false}; 0134 0135 for (const auto scr : qGuiApp->screens()) { 0136 if (scr->geometry().contains(wGeometry.center())) { 0137 if (wGeometry.y() == scr->geometry().y() || wGeometry.bottom() == scr->geometry().bottom()) { 0138 isTouchingHorizontalEdge = true; 0139 } 0140 0141 if (wGeometry.left() == scr->geometry().left() || wGeometry.right() == scr->geometry().right()) { 0142 isTouchingVerticalEdge = true; 0143 } 0144 0145 if (isTouchingVerticalEdge && isTouchingHorizontalEdge) { 0146 break; 0147 } 0148 } 0149 } 0150 0151 if ((isTouchingHorizontalEdge && wGeometry.height() < MAXPLASMAPANELTHICKNESS) 0152 || (isTouchingVerticalEdge && wGeometry.width() < MAXPLASMAPANELTHICKNESS)) { 0153 return true; 0154 } 0155 0156 return false; 0157 } 0158 0159 bool AbstractWindowInterface::isRegisteredPlasmaPanel(const WindowId &wid) 0160 { 0161 return m_plasmaPanels.contains(wid); 0162 } 0163 0164 bool AbstractWindowInterface::inCurrentDesktopActivity(const WindowInfoWrap &winfo) const 0165 { 0166 return (winfo.isValid() && winfo.isOnDesktop(currentDesktop()) && winfo.isOnActivity(currentActivity())); 0167 } 0168 0169 //! Register Latte Ignored Windows in order to NOT be tracked 0170 void AbstractWindowInterface::registerIgnoredWindow(WindowId wid) 0171 { 0172 if (!wid.isNull() && !m_ignoredWindows.contains(wid)) { 0173 m_ignoredWindows.append(wid); 0174 emit windowChanged(wid); 0175 } 0176 } 0177 0178 void AbstractWindowInterface::unregisterIgnoredWindow(WindowId wid) 0179 { 0180 if (m_ignoredWindows.contains(wid)) { 0181 m_ignoredWindows.removeAll(wid); 0182 emit windowRemoved(wid); 0183 } 0184 } 0185 0186 void AbstractWindowInterface::registerPlasmaPanel(WindowId wid) 0187 { 0188 if (!wid.isNull() && !m_plasmaPanels.contains(wid)) { 0189 m_plasmaPanels.append(wid); 0190 emit windowChanged(wid); 0191 } 0192 } 0193 0194 void AbstractWindowInterface::unregisterPlasmaPanel(WindowId wid) 0195 { 0196 if (m_plasmaPanels.contains(wid)) { 0197 m_plasmaPanels.removeAll(wid); 0198 } 0199 } 0200 0201 void AbstractWindowInterface::windowRemovedSlot(WindowId wid) 0202 { 0203 if (m_plasmaPanels.contains(wid)) { 0204 unregisterPlasmaPanel(wid); 0205 } 0206 } 0207 0208 //! Activities switching 0209 void AbstractWindowInterface::switchToNextActivity() 0210 { 0211 QStringList runningActivities = m_activities->activities(KActivities::Info::State::Running); 0212 if (runningActivities.count() <= 1) { 0213 return; 0214 } 0215 0216 int curPos = runningActivities.indexOf(m_currentActivity); 0217 int nextPos = curPos + 1; 0218 0219 if (curPos == runningActivities.count() -1) { 0220 nextPos = 0; 0221 } 0222 0223 KActivities::Controller activitiesController; 0224 activitiesController.setCurrentActivity(runningActivities.at(nextPos)); 0225 } 0226 0227 void AbstractWindowInterface::switchToPreviousActivity() 0228 { 0229 QStringList runningActivities = m_activities->activities(KActivities::Info::State::Running); 0230 if (runningActivities.count() <= 1) { 0231 return; 0232 } 0233 0234 int curPos = runningActivities.indexOf(m_currentActivity); 0235 int nextPos = curPos - 1; 0236 0237 if (curPos == 0) { 0238 nextPos = runningActivities.count() - 1; 0239 } 0240 0241 KActivities::Controller activitiesController; 0242 activitiesController.setCurrentActivity(runningActivities.at(nextPos)); 0243 } 0244 0245 //! Delay window changed trigerring 0246 void AbstractWindowInterface::considerWindowChanged(WindowId wid) 0247 { 0248 //! Consider if the windowChanged signal should be sent DIRECTLY or WAIT 0249 0250 if (m_windowChangedWaiting == wid && m_windowWaitingTimer.isActive()) { 0251 //! window should be sent later 0252 m_windowWaitingTimer.start(); 0253 return; 0254 } 0255 0256 if (m_windowChangedWaiting != wid && !m_windowWaitingTimer.isActive()) { 0257 //! window should be sent later 0258 m_windowChangedWaiting = wid; 0259 m_windowWaitingTimer.start(); 0260 } 0261 0262 if (m_windowChangedWaiting != wid && m_windowWaitingTimer.isActive()) { 0263 m_windowWaitingTimer.stop(); 0264 //! sent previous waiting window 0265 emit windowChanged(m_windowChangedWaiting); 0266 0267 //! retrigger waiting for the upcoming window 0268 m_windowChangedWaiting = wid; 0269 m_windowWaitingTimer.start(); 0270 } 0271 } 0272 0273 } 0274 } 0275