File indexing completed on 2025-04-27 14:21:36
0001 /* 0002 * Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com> 0003 * 0004 * This file is part of Latte-Dock 0005 * 0006 * Latte-Dock is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * Latte-Dock is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "lastactivewindow.h" 0021 0022 // local 0023 #include "schemes.h" 0024 #include "trackedgeneralinfo.h" 0025 #include "windowstracker.h" 0026 #include "../abstractwindowinterface.h" 0027 #include "../tasktools.h" 0028 #include "../../view/view.h" 0029 0030 // Qt 0031 #include <QDebug> 0032 #include <QHoverEvent> 0033 #include <QPoint> 0034 #include <QTimer> 0035 0036 0037 namespace Latte { 0038 namespace WindowSystem { 0039 namespace Tracker { 0040 0041 const int INVALIDWID = -1; 0042 const int PREFHISTORY = 8; 0043 const int MAXHISTORY = 15; 0044 0045 LastActiveWindow::LastActiveWindow(TrackedGeneralInfo *trackedInfo) 0046 : QObject(trackedInfo), 0047 m_trackedInfo(trackedInfo), 0048 m_windowsTracker(trackedInfo->wm()->windowsTracker()), 0049 m_wm(trackedInfo->wm()) 0050 { 0051 connect(m_wm->schemesTracker(), &Schemes::colorSchemeChanged, this, [&](WindowId wid) { 0052 if (wid == m_winId) { 0053 updateColorScheme(); 0054 } 0055 }); 0056 0057 connect(m_windowsTracker, &Windows::applicationDataChanged, this, &LastActiveWindow::applicationDataChanged); 0058 connect(m_windowsTracker, &Windows::windowChanged, this, &LastActiveWindow::windowChanged); 0059 connect(m_windowsTracker, &Windows::windowRemoved, this, &LastActiveWindow::windowRemoved); 0060 } 0061 0062 LastActiveWindow::~LastActiveWindow() 0063 { 0064 } 0065 0066 bool LastActiveWindow::isActive() const 0067 { 0068 return m_isActive; 0069 } 0070 0071 void LastActiveWindow::setActive(bool active) 0072 { 0073 if (m_isActive == active) { 0074 return; 0075 } 0076 0077 m_isActive = active; 0078 emit isActiveChanged(); 0079 } 0080 0081 bool LastActiveWindow::isMinimized() const 0082 { 0083 return m_isMinimized; 0084 } 0085 0086 void LastActiveWindow::setIsMinimized(bool minimized) 0087 { 0088 if (m_isMinimized == minimized) { 0089 return; 0090 } 0091 0092 m_isMinimized = minimized; 0093 emit isMinimizedChanged(); 0094 } 0095 0096 bool LastActiveWindow::isMaximized() const 0097 { 0098 return m_isMaximized; 0099 } 0100 0101 void LastActiveWindow::setIsMaximized(bool maximized) 0102 { 0103 if (m_isMaximized == maximized) { 0104 return; 0105 } 0106 0107 m_isMaximized = maximized; 0108 emit isMaximizedChanged(); 0109 } 0110 0111 bool LastActiveWindow::isFullScreen() const 0112 { 0113 return m_isFullScreen; 0114 } 0115 0116 void LastActiveWindow::setIsFullScreen(bool fullscreen) 0117 { 0118 if (m_isFullScreen == fullscreen) { 0119 return; 0120 } 0121 0122 m_isFullScreen = fullscreen; 0123 emit isFullScreenChanged(); 0124 } 0125 0126 bool LastActiveWindow::isKeepAbove() const 0127 { 0128 return m_isKeepAbove; 0129 } 0130 0131 void LastActiveWindow::setIsKeepAbove(bool above) 0132 { 0133 if (m_isKeepAbove == above) { 0134 return; 0135 } 0136 0137 m_isKeepAbove = above; 0138 emit isKeepAboveChanged(); 0139 } 0140 0141 bool LastActiveWindow::isOnAllDesktops() const 0142 { 0143 return m_isOnAllDesktops; 0144 } 0145 0146 void LastActiveWindow::setIsOnAllDesktops(bool all) 0147 { 0148 if (m_isOnAllDesktops == all) { 0149 return; 0150 } 0151 0152 m_isOnAllDesktops = all; 0153 emit isOnAllDesktopsChanged(); 0154 } 0155 0156 bool LastActiveWindow::isShaded() const 0157 { 0158 return m_isShaded; 0159 } 0160 0161 void LastActiveWindow::setIsShaded(bool shaded) 0162 { 0163 if (m_isShaded == shaded) { 0164 return; 0165 } 0166 0167 m_isShaded = shaded; 0168 emit isShadedChanged(); 0169 } 0170 0171 bool LastActiveWindow::isValid() const 0172 { 0173 return m_isValid; 0174 } 0175 0176 void LastActiveWindow::setIsValid(bool valid) 0177 { 0178 if (m_isValid == valid) { 0179 return; 0180 } 0181 0182 m_isValid = valid; 0183 emit isValidChanged(); 0184 } 0185 0186 bool LastActiveWindow::hasSkipTaskbar() const 0187 { 0188 return m_hasSkipTaskbar; 0189 } 0190 0191 void LastActiveWindow::setHasSkipTaskbar(bool skip) 0192 { 0193 if (m_hasSkipTaskbar == skip) { 0194 return; 0195 } 0196 0197 m_hasSkipTaskbar = skip; 0198 emit hasSkipTaskbarChanged(); 0199 } 0200 0201 //! BEGIN: Window Abitilities 0202 bool LastActiveWindow::isClosable() const 0203 { 0204 return m_isClosable; 0205 } 0206 0207 void LastActiveWindow::setIsClosable(bool closable) 0208 { 0209 if (m_isClosable == closable) { 0210 return; 0211 } 0212 0213 m_isClosable = closable; 0214 emit isClosableChanged(); 0215 } 0216 0217 bool LastActiveWindow::isFullScreenable() const 0218 { 0219 return m_isFullScreenable; 0220 } 0221 0222 void LastActiveWindow::setIsFullScreenable(bool fullscreenable) 0223 { 0224 if (m_isFullScreenable == fullscreenable) { 0225 return; 0226 } 0227 0228 m_isFullScreenable = fullscreenable; 0229 emit isFullScreenableChanged(); 0230 } 0231 0232 bool LastActiveWindow::isGroupable() const 0233 { 0234 return m_isGroupable; 0235 } 0236 0237 void LastActiveWindow::setIsGroupable(bool groupable) 0238 { 0239 if (m_isGroupable == groupable) { 0240 return; 0241 } 0242 0243 m_isGroupable = groupable; 0244 emit isGroupableChanged(); 0245 } 0246 0247 0248 bool LastActiveWindow::isMaximizable() const 0249 { 0250 return m_isMaximizable; 0251 } 0252 0253 void LastActiveWindow::setIsMaximizable(bool maximizable) 0254 { 0255 if (m_isMaximizable == maximizable) { 0256 return; 0257 } 0258 0259 m_isMaximizable = maximizable; 0260 emit isMaximizableChanged(); 0261 } 0262 0263 bool LastActiveWindow::isMinimizable() const 0264 { 0265 return m_isMinimizable; 0266 } 0267 0268 void LastActiveWindow::setIsMinimizable(bool minimizable) 0269 { 0270 if (m_isMinimizable == minimizable) { 0271 return; 0272 } 0273 0274 m_isMinimizable = minimizable; 0275 emit isMinimizableChanged(); 0276 } 0277 0278 bool LastActiveWindow::isMovable() const 0279 { 0280 return m_isMovable; 0281 } 0282 0283 void LastActiveWindow::setIsMovable(bool movable) 0284 { 0285 if (m_isMovable == movable) { 0286 return; 0287 } 0288 0289 m_isMovable = movable; 0290 emit isMovableChanged(); 0291 } 0292 0293 bool LastActiveWindow::isResizable() const 0294 { 0295 return m_isResizable; 0296 } 0297 0298 void LastActiveWindow::setIsResizable(bool resizable) 0299 { 0300 if (m_isResizable == resizable) { 0301 return; 0302 } 0303 0304 m_isResizable = resizable; 0305 emit isResizableChanged(); 0306 } 0307 0308 bool LastActiveWindow::isShadeable() const 0309 { 0310 return m_isShadeable; 0311 } 0312 0313 void LastActiveWindow::setIsShadeable(bool shadeable) 0314 { 0315 if (m_isShadeable == shadeable) { 0316 return; 0317 } 0318 0319 m_isShadeable = shadeable; 0320 emit isShadeableChanged(); 0321 } 0322 0323 bool LastActiveWindow::isVirtualDesktopChangeable() const 0324 { 0325 return m_isVirtualDesktopsChangeable; 0326 } 0327 0328 void LastActiveWindow::setIsVirtualDesktopsChangeable(bool virtualdestkopschangeable) 0329 { 0330 if (m_isVirtualDesktopsChangeable == virtualdestkopschangeable) { 0331 return; 0332 } 0333 0334 m_isVirtualDesktopsChangeable = virtualdestkopschangeable; 0335 emit isVirtualDesktopChangeableChanged(); 0336 } 0337 //! END: Window Abitilities 0338 0339 0340 QRect LastActiveWindow::geometry() const 0341 { 0342 return m_geometry; 0343 } 0344 0345 void LastActiveWindow::setGeometry(QRect geometry) 0346 { 0347 if (m_geometry == geometry) { 0348 return; 0349 } 0350 0351 m_geometry = geometry; 0352 emit geometryChanged(); 0353 } 0354 0355 QString LastActiveWindow::appName() const 0356 { 0357 return m_appName; 0358 } 0359 0360 void LastActiveWindow::setAppName(QString appName) 0361 { 0362 if (m_appName == appName) { 0363 return; 0364 } 0365 0366 m_appName = appName; 0367 emit appNameChanged(); 0368 } 0369 0370 QString LastActiveWindow::colorScheme() const 0371 { 0372 return m_colorScheme; 0373 } 0374 0375 void LastActiveWindow::setColorScheme(QString scheme) 0376 { 0377 if (m_colorScheme == scheme){ 0378 return; 0379 } 0380 0381 m_colorScheme = scheme; 0382 emit colorSchemeChanged(); 0383 } 0384 0385 QString LastActiveWindow::display() const 0386 { 0387 return m_display; 0388 } 0389 0390 void LastActiveWindow::setDisplay(QString display) 0391 { 0392 if (m_display == display) { 0393 return; 0394 } 0395 0396 m_display = display; 0397 emit displayChanged(); 0398 } 0399 0400 QIcon LastActiveWindow::icon() const 0401 { 0402 return m_icon; 0403 } 0404 0405 void LastActiveWindow::setIcon(QIcon icon) 0406 { 0407 m_icon = icon; 0408 emit iconChanged(); 0409 } 0410 0411 QVariant LastActiveWindow::winId() const 0412 { 0413 return m_winId; 0414 } 0415 0416 void LastActiveWindow::setWinId(QVariant winId) 0417 { 0418 if (m_winId == winId && isValid()) { 0419 return; 0420 } 0421 0422 if (!m_history.contains(winId)) { 0423 m_history.prepend(winId); 0424 cleanHistory(); 0425 } else { 0426 int p = m_history.indexOf(winId); 0427 //! move to start 0428 m_history.move(p, 0); 0429 } 0430 0431 m_winId = winId; 0432 emit winIdChanged(); 0433 } 0434 0435 void LastActiveWindow::setInformation(const WindowInfoWrap &info) 0436 { 0437 bool firstActiveness{false}; 0438 0439 if (m_winId != info.wid()) { 0440 firstActiveness = true; 0441 } 0442 0443 setWinId(info.wid()); 0444 0445 setIsValid(true); 0446 setActive(info.isActive()); 0447 setIsMinimized(info.isMinimized()); 0448 setIsMaximized(info.isMaximized()); 0449 setIsOnAllDesktops(info.isOnAllDesktops()); 0450 0451 //! Window Abilities 0452 setIsClosable(info.isCloseable()); 0453 setIsFullScreenable(info.isFullScreenable()); 0454 setIsGroupable(info.isGroupable()); 0455 setIsMaximizable(info.isMaximizable()); 0456 setIsMinimizable(info.isMinimizable()); 0457 setIsMovable(info.isMovable()); 0458 setIsResizable(info.isResizable()); 0459 setIsShadeable(info.isShadeable()); 0460 setIsVirtualDesktopsChangeable(info.isVirtualDesktopsChangeable()); 0461 //! Window Abilities 0462 0463 setAppName(info.appName()); 0464 setDisplay(info.display()); 0465 setGeometry(info.geometry()); 0466 setIsKeepAbove(info.isKeepAbove()); 0467 0468 if (firstActiveness) { 0469 updateColorScheme(); 0470 } 0471 0472 if (info.appName().isEmpty()) { 0473 setAppName(m_windowsTracker->appNameFor(info.wid())); 0474 } else { 0475 setAppName(info.appName()); 0476 } 0477 0478 if (info.icon().isNull()) { 0479 setIcon(m_windowsTracker->iconFor(info.wid())); 0480 } else { 0481 setIcon(info.icon()); 0482 } 0483 } 0484 0485 //! PRIVATE SLOTS 0486 void LastActiveWindow::applicationDataChanged(const WindowId &wid) 0487 { 0488 if (m_winId == wid) { 0489 setAppName(m_windowsTracker->appNameFor(wid)); 0490 setIcon(m_windowsTracker->iconFor(wid)); 0491 } 0492 } 0493 0494 0495 void LastActiveWindow::windowChanged(const WindowId &wid) 0496 { 0497 if (!m_trackedInfo->enabled()) { 0498 // qDebug() << " Last Active Window, Window Changed : TrackedInfo is disabled..."; 0499 return; 0500 } 0501 0502 if (m_history.contains(wid)) { 0503 //! remove from history minimized windows or windows that changed screen 0504 //! and update information accordingly with the first valid window found from 0505 //! history after the removal 0506 WindowInfoWrap winfo = m_windowsTracker->infoFor(wid); 0507 0508 bool firstItemRemoved{false}; 0509 0510 //! Remove minimized windows OR NOT-TRACKED windows from history 0511 if (winfo.isMinimized() || !m_trackedInfo->isTracking(winfo)) { 0512 if (m_history[0] == wid) { 0513 firstItemRemoved = true; 0514 } 0515 0516 m_history.removeAll(wid); 0517 cleanHistory(); 0518 } 0519 0520 if (m_history.count() > 0) { 0521 if (m_history[0] == wid || firstItemRemoved) { 0522 WindowInfoWrap history1 = m_windowsTracker->infoFor(m_history[0]); 0523 0524 //! Check if first found History window is still valid to show its information 0525 if (history1.isMinimized() || !m_trackedInfo->isTracking(history1)) { 0526 windowChanged(m_history[0]); 0527 } else { 0528 setInformation(history1); 0529 } 0530 } 0531 } else { 0532 //! History is empty so any demonstrated information are invalid 0533 setIsValid(false); 0534 } 0535 0536 //qDebug() << " HISTORY ::: " << m_history; 0537 } else { 0538 //qDebug() << " LastActiveWindow : window is not in history"; 0539 } 0540 } 0541 0542 void LastActiveWindow::windowRemoved(const WindowId &wid) 0543 { 0544 if (m_history.contains(wid)) { 0545 bool firstItemRemoved{false}; 0546 0547 if (m_history.count() > 0 && m_history[0] == wid) { 0548 firstItemRemoved = true; 0549 } 0550 0551 m_history.removeAll(wid); 0552 m_history.removeAll(wid); 0553 0554 if (m_history.count() > 0 && firstItemRemoved) { 0555 windowChanged(m_history[0]); 0556 } else { 0557 setIsValid(false); 0558 } 0559 } 0560 } 0561 0562 void LastActiveWindow::cleanHistory() 0563 { 0564 if (m_history.count() > MAXHISTORY) { 0565 int size = m_history.count(); 0566 for(int i=0; i<(size-PREFHISTORY); ++i) { 0567 if (!m_history.isEmpty()) { 0568 m_history.removeLast(); 0569 } 0570 } 0571 } 0572 } 0573 0574 void LastActiveWindow::updateColorScheme() 0575 { 0576 auto scheme = m_wm->schemesTracker()->schemeForWindow(m_winId); 0577 if (scheme) { 0578 setColorScheme(scheme->schemeFile()); 0579 } 0580 } 0581 0582 0583 //! FUNCTIONALITY 0584 void LastActiveWindow::requestActivate() 0585 { 0586 m_wm->requestActivate(m_winId); 0587 } 0588 0589 void LastActiveWindow::requestClose() 0590 { 0591 m_wm->requestClose(m_winId); 0592 } 0593 0594 void LastActiveWindow::requestMove(Latte::View *fromView, int localX, int localY) 0595 { 0596 if (!fromView || !canBeDragged()) { 0597 return; 0598 } 0599 0600 QPoint globalPoint{fromView->x() + localX, fromView->y() + localY}; 0601 m_wm->requestMoveWindow(m_winId, globalPoint); 0602 0603 fromView->unblockMouse(localX, localY); 0604 } 0605 0606 void LastActiveWindow::requestToggleIsOnAllDesktops() 0607 { 0608 m_wm->requestToggleIsOnAllDesktops(m_winId); 0609 } 0610 0611 void LastActiveWindow::requestToggleKeepAbove() 0612 { 0613 m_wm->requestToggleKeepAbove(m_winId); 0614 } 0615 0616 void LastActiveWindow::requestToggleMinimized() 0617 { 0618 m_wm->requestToggleMinimized(m_winId); 0619 } 0620 0621 void LastActiveWindow::requestToggleMaximized() 0622 { 0623 m_wm->requestToggleMaximized(m_winId); 0624 } 0625 0626 bool LastActiveWindow::canBeDragged() 0627 { 0628 return m_wm->windowCanBeDragged(m_winId); 0629 } 0630 0631 } 0632 } 0633 }