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