File indexing completed on 2024-04-21 16:17:21
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 "waylandinterface.h" 0022 0023 // local 0024 #include "view/screenedgeghostwindow.h" 0025 #include "view/view.h" 0026 #include "../lattecorona.h" 0027 #include "../liblatte2/extras.h" 0028 0029 // Qt 0030 #include <QDebug> 0031 #include <QTimer> 0032 #include <QApplication> 0033 #include <QtX11Extras/QX11Info> 0034 #include <QRasterWindow> 0035 0036 // KDE 0037 #include <KWindowSystem> 0038 #include <KWindowInfo> 0039 #include <KWayland/Client/surface.h> 0040 0041 #if KF5_VERSION_MINOR >= 52 0042 #include <KWayland/Client/plasmavirtualdesktop.h> 0043 #endif 0044 0045 // X11 0046 #include <NETWM> 0047 0048 using namespace KWayland::Client; 0049 0050 namespace Latte { 0051 0052 class Private::GhostWindow : public QRasterWindow 0053 { 0054 Q_OBJECT 0055 0056 public: 0057 WindowSystem::WindowId m_winId; 0058 0059 GhostWindow(WindowSystem::WaylandInterface *waylandInterface) 0060 : m_waylandInterface(waylandInterface) { 0061 setFlags(Qt::FramelessWindowHint 0062 | Qt::WindowStaysOnTopHint 0063 | Qt::NoDropShadowWindowHint 0064 | Qt::WindowDoesNotAcceptFocus); 0065 0066 connect(m_waylandInterface, &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, &GhostWindow::identifyWinId); 0067 0068 setupWaylandIntegration(); 0069 show(); 0070 } 0071 0072 ~GhostWindow() { 0073 m_waylandInterface->unregisterIgnoredWindow(m_winId); 0074 delete m_shellSurface; 0075 } 0076 0077 void setGeometry(const QRect &rect) { 0078 if (geometry() == rect) { 0079 return; 0080 } 0081 0082 m_validGeometry = rect; 0083 0084 setMinimumSize(rect.size()); 0085 setMaximumSize(rect.size()); 0086 resize(rect.size()); 0087 0088 m_shellSurface->setPosition(rect.topLeft()); 0089 } 0090 0091 void setupWaylandIntegration() { 0092 using namespace KWayland::Client; 0093 0094 if (m_shellSurface) 0095 return; 0096 0097 Surface *s{Surface::fromWindow(this)}; 0098 0099 if (!s) 0100 return; 0101 0102 m_shellSurface = m_waylandInterface->waylandCoronaInterface()->createSurface(s, this); 0103 qDebug() << "wayland ghost window surface was created..."; 0104 0105 m_shellSurface->setSkipTaskbar(true); 0106 m_shellSurface->setPanelTakesFocus(false); 0107 m_shellSurface->setRole(PlasmaShellSurface::Role::Panel); 0108 m_shellSurface->setPanelBehavior(PlasmaShellSurface::PanelBehavior::AlwaysVisible); 0109 } 0110 0111 KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; 0112 WindowSystem::WaylandInterface *m_waylandInterface{nullptr}; 0113 0114 //! geometry() function under wayland does not return nice results 0115 QRect m_validGeometry; 0116 0117 public slots: 0118 void identifyWinId() { 0119 if (m_winId.isNull()) { 0120 m_winId = m_waylandInterface->winIdFor("latte-dock", m_validGeometry); 0121 m_waylandInterface->registerIgnoredWindow(m_winId); 0122 } 0123 } 0124 }; 0125 0126 namespace WindowSystem { 0127 0128 WaylandInterface::WaylandInterface(QObject *parent) 0129 : AbstractWindowInterface(parent) 0130 { 0131 m_corona = qobject_cast<Latte::Corona *>(parent); 0132 } 0133 0134 WaylandInterface::~WaylandInterface() 0135 { 0136 } 0137 0138 void WaylandInterface::init() 0139 { 0140 } 0141 0142 void WaylandInterface::initWindowManagement(KWayland::Client::PlasmaWindowManagement *windowManagement) 0143 { 0144 if (m_windowManagement == windowManagement) { 0145 return; 0146 } 0147 0148 m_windowManagement = windowManagement; 0149 0150 connect(m_windowManagement, &PlasmaWindowManagement::windowCreated, this, &WaylandInterface::windowCreatedProxy); 0151 connect(m_windowManagement, &PlasmaWindowManagement::activeWindowChanged, this, [&]() noexcept { 0152 auto w = m_windowManagement->activeWindow(); 0153 if (!w || (w && (!m_ignoredWindows.contains(w->internalId() && !isPlasmaDesktop(w)))) ) { 0154 emit activeWindowChanged(w ? w->internalId() : 0); 0155 } 0156 0157 }, Qt::QueuedConnection); 0158 } 0159 0160 #if KF5_VERSION_MINOR >= 52 0161 void WaylandInterface::initVirtualDesktopManagement(KWayland::Client::PlasmaVirtualDesktopManagement *virtualDesktopManagement) 0162 { 0163 if (m_virtualDesktopManagement == virtualDesktopManagement) { 0164 return; 0165 } 0166 0167 m_virtualDesktopManagement = virtualDesktopManagement; 0168 0169 connect(m_virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopCreated, this, 0170 [this](const QString &id, quint32 position) { 0171 addDesktop(id, position); 0172 }); 0173 0174 connect(m_virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopRemoved, this, 0175 [this](const QString &id) { 0176 m_desktops.removeAll(id); 0177 0178 if (m_currentDesktop == id) { 0179 setCurrentDesktop(QString()); 0180 } 0181 }); 0182 } 0183 0184 void WaylandInterface::addDesktop(const QString &id, quint32 position) 0185 { 0186 if (m_desktops.contains(id)) { 0187 return; 0188 } 0189 0190 m_desktops.append(id); 0191 0192 const KWayland::Client::PlasmaVirtualDesktop *desktop = m_virtualDesktopManagement->getVirtualDesktop(id); 0193 0194 QObject::connect(desktop, &KWayland::Client::PlasmaVirtualDesktop::activated, this, 0195 [desktop, this]() { 0196 setCurrentDesktop(desktop->id()); 0197 } 0198 ); 0199 0200 if (desktop->isActive()) { 0201 setCurrentDesktop(id); 0202 } 0203 } 0204 0205 void WaylandInterface::setCurrentDesktop(QString desktop) 0206 { 0207 if (m_currentDesktop == desktop) { 0208 return; 0209 } 0210 0211 m_currentDesktop = desktop; 0212 emit currentDesktopChanged(); 0213 } 0214 #endif 0215 0216 KWayland::Client::PlasmaShell *WaylandInterface::waylandCoronaInterface() const 0217 { 0218 return m_corona->waylandCoronaInterface(); 0219 } 0220 0221 //! Register Latte Ignored Windows in order to NOT be tracked 0222 void WaylandInterface::registerIgnoredWindow(WindowId wid) 0223 { 0224 if (!wid.isNull() && !m_ignoredWindows.contains(wid)) { 0225 m_ignoredWindows.append(wid); 0226 0227 KWayland::Client::PlasmaWindow *w = windowFor(wid); 0228 0229 if (w) { 0230 untrackWindow(w); 0231 } 0232 0233 emit windowChanged(wid); 0234 } 0235 } 0236 0237 void WaylandInterface::unregisterIgnoredWindow(WindowId wid) 0238 { 0239 if (m_ignoredWindows.contains(wid)) { 0240 m_ignoredWindows.removeAll(wid); 0241 emit windowRemoved(wid); 0242 } 0243 } 0244 0245 void WaylandInterface::setViewExtraFlags(QWindow &view) 0246 { 0247 Q_UNUSED(view) 0248 } 0249 0250 void WaylandInterface::setViewStruts(QWindow &view, const QRect &rect, Plasma::Types::Location location) 0251 { 0252 if (!m_ghostWindows.contains(view.winId())) { 0253 m_ghostWindows[view.winId()] = new Private::GhostWindow(this); 0254 } 0255 0256 auto w = m_ghostWindows[view.winId()]; 0257 0258 switch (location) { 0259 case Plasma::Types::TopEdge: 0260 case Plasma::Types::BottomEdge: 0261 w->setGeometry({rect.x() + rect.width() / 2, rect.y(), 1, rect.height()}); 0262 break; 0263 0264 case Plasma::Types::LeftEdge: 0265 case Plasma::Types::RightEdge: 0266 w->setGeometry({rect.x(), rect.y() + rect.height() / 2, rect.width(), 1}); 0267 break; 0268 0269 default: 0270 break; 0271 } 0272 } 0273 0274 void WaylandInterface::switchToNextVirtualDesktop() const 0275 { 0276 #if KF5_VERSION_MINOR >= 52 0277 if (!m_virtualDesktopManagement || m_desktops.count() <= 1) { 0278 return; 0279 } 0280 0281 int curPos = m_desktops.indexOf(m_currentDesktop); 0282 int nextPos = curPos + 1; 0283 0284 if (curPos == m_desktops.count()-1) { 0285 nextPos = 0; 0286 } 0287 0288 KWayland::Client::PlasmaVirtualDesktop *desktopObj = m_virtualDesktopManagement->getVirtualDesktop(m_desktops[nextPos]); 0289 0290 if (desktopObj) { 0291 desktopObj->requestActivate(); 0292 } 0293 #endif 0294 } 0295 0296 void WaylandInterface::switchToPreviousVirtualDesktop() const 0297 { 0298 #if KF5_VERSION_MINOR >= 52 0299 if (!m_virtualDesktopManagement || m_desktops.count() <= 1) { 0300 return; 0301 } 0302 0303 int curPos = m_desktops.indexOf(m_currentDesktop); 0304 int nextPos = curPos - 1; 0305 0306 if (curPos == 0) { 0307 nextPos = m_desktops.count()-1; 0308 } 0309 0310 KWayland::Client::PlasmaVirtualDesktop *desktopObj = m_virtualDesktopManagement->getVirtualDesktop(m_desktops[nextPos]); 0311 0312 if (desktopObj) { 0313 desktopObj->requestActivate(); 0314 } 0315 #endif 0316 } 0317 0318 void WaylandInterface::setWindowOnActivities(QWindow &window, const QStringList &activities) 0319 { 0320 //! needs to updated to wayland case 0321 // KWindowSystem::setOnActivities(view.winId(), activities); 0322 } 0323 0324 void WaylandInterface::removeViewStruts(QWindow &view) const 0325 { 0326 delete m_ghostWindows.take(view.winId()); 0327 } 0328 0329 WindowId WaylandInterface::activeWindow() const 0330 { 0331 if (!m_windowManagement) { 0332 return 0; 0333 } 0334 0335 auto wid = m_windowManagement->activeWindow(); 0336 0337 return wid ? wid->internalId() : 0; 0338 } 0339 0340 void WaylandInterface::setKeepAbove(const QDialog &dialog, bool above) const 0341 { 0342 if (above) { 0343 KWindowSystem::setState(dialog.winId(), NET::KeepAbove); 0344 } else { 0345 KWindowSystem::clearState(dialog.winId(), NET::KeepAbove); 0346 } 0347 } 0348 0349 void WaylandInterface::skipTaskBar(const QDialog &dialog) const 0350 { 0351 KWindowSystem::setState(dialog.winId(), NET::SkipTaskbar); 0352 } 0353 0354 void WaylandInterface::slideWindow(QWindow &view, AbstractWindowInterface::Slide location) const 0355 { 0356 auto slideLocation = KWindowEffects::NoEdge; 0357 0358 switch (location) { 0359 case Slide::Top: 0360 slideLocation = KWindowEffects::TopEdge; 0361 break; 0362 0363 case Slide::Bottom: 0364 slideLocation = KWindowEffects::BottomEdge; 0365 break; 0366 0367 case Slide::Left: 0368 slideLocation = KWindowEffects::LeftEdge; 0369 break; 0370 0371 case Slide::Right: 0372 slideLocation = KWindowEffects::RightEdge; 0373 break; 0374 0375 default: 0376 break; 0377 } 0378 0379 KWindowEffects::slideWindow(view.winId(), slideLocation, -1); 0380 } 0381 0382 void WaylandInterface::enableBlurBehind(QWindow &view) const 0383 { 0384 KWindowEffects::enableBlurBehind(view.winId()); 0385 } 0386 0387 void WaylandInterface::setActiveEdge(QWindow *view, bool active) const 0388 { 0389 ViewPart::ScreenEdgeGhostWindow *window = qobject_cast<ViewPart::ScreenEdgeGhostWindow *>(view); 0390 0391 if (!window) { 0392 return; 0393 } 0394 0395 if (window->parentView()->surface() && window->parentView()->visibility() 0396 && (window->parentView()->visibility()->mode() == Types::DodgeActive 0397 || window->parentView()->visibility()->mode() == Types::DodgeMaximized 0398 || window->parentView()->visibility()->mode() == Types::DodgeAllWindows 0399 || window->parentView()->visibility()->mode() == Types::AutoHide)) { 0400 if (active) { 0401 window->showWithMask(); 0402 window->surface()->requestHideAutoHidingPanel(); 0403 } else { 0404 window->hideWithMask(); 0405 window->surface()->requestShowAutoHidingPanel(); 0406 } 0407 } 0408 } 0409 0410 WindowInfoWrap WaylandInterface::requestInfoActive() const 0411 { 0412 if (!m_windowManagement) { 0413 return {}; 0414 } 0415 0416 auto w = m_windowManagement->activeWindow(); 0417 0418 if (!w) return {}; 0419 0420 return requestInfo(w->internalId()); 0421 } 0422 0423 WindowInfoWrap WaylandInterface::requestInfo(WindowId wid) const 0424 { 0425 WindowInfoWrap winfoWrap; 0426 0427 auto w = windowFor(wid); 0428 0429 if (w) { 0430 if (isPlasmaDesktop(w)) { 0431 winfoWrap.setIsValid(true); 0432 winfoWrap.setIsPlasmaDesktop(true); 0433 winfoWrap.setWid(wid); 0434 0435 //! Window Abilities 0436 winfoWrap.setIsClosable(false); 0437 winfoWrap.setIsFullScreenable(false); 0438 winfoWrap.setIsGroupable(false); 0439 winfoWrap.setIsMaximizable(false); 0440 winfoWrap.setIsMinimizable(false); 0441 winfoWrap.setIsMovable(false); 0442 winfoWrap.setIsResizable(false); 0443 winfoWrap.setIsShadeable(false); 0444 winfoWrap.setIsVirtualDesktopsChangeable(false); 0445 //! Window Abilities 0446 0447 } else if (isValidWindow(w)) { 0448 winfoWrap.setIsValid(true); 0449 winfoWrap.setWid(wid); 0450 winfoWrap.setParentId(w->parentWindow() ? w->parentWindow()->internalId() : 0); 0451 winfoWrap.setIsActive(w->isActive()); 0452 winfoWrap.setIsMinimized(w->isMinimized()); 0453 winfoWrap.setIsMaxVert(w->isMaximized()); 0454 winfoWrap.setIsMaxHoriz(w->isMaximized()); 0455 winfoWrap.setIsFullscreen(w->isFullscreen()); 0456 winfoWrap.setIsShaded(w->isShaded()); 0457 winfoWrap.setIsOnAllDesktops(w->isOnAllDesktops()); 0458 winfoWrap.setIsOnAllActivities(true); 0459 winfoWrap.setGeometry(w->geometry()); 0460 winfoWrap.setHasSkipTaskbar(w->skipTaskbar()); 0461 0462 //! Window Abilities 0463 winfoWrap.setIsClosable(w->isCloseable()); 0464 winfoWrap.setIsFullScreenable(w->isFullscreenable()); 0465 winfoWrap.setIsMaximizable(w->isMaximizeable()); 0466 winfoWrap.setIsMinimizable(w->isMinimizeable()); 0467 winfoWrap.setIsMovable(w->isMovable()); 0468 winfoWrap.setIsResizable(w->isResizable()); 0469 winfoWrap.setIsShadeable(w->isShadeable()); 0470 winfoWrap.setIsVirtualDesktopsChangeable(w->isVirtualDesktopChangeable()); 0471 //! Window Abilities 0472 0473 winfoWrap.setDisplay(w->title()); 0474 #if KF5_VERSION_MINOR >= 52 0475 winfoWrap.setDesktops(w->plasmaVirtualDesktops()); 0476 #endif 0477 winfoWrap.setActivities(QStringList()); 0478 } 0479 } else { 0480 winfoWrap.setIsValid(false); 0481 } 0482 0483 return winfoWrap; 0484 } 0485 0486 AppData WaylandInterface::appDataFor(WindowId wid) const 0487 { 0488 auto window = windowFor(wid); 0489 0490 if (window) { 0491 const AppData &data = appDataFromUrl(windowUrlFromMetadata(window->appId(), 0492 window->pid(), rulesConfig)); 0493 0494 return data; 0495 } 0496 0497 AppData empty; 0498 0499 return empty; 0500 } 0501 0502 KWayland::Client::PlasmaWindow *WaylandInterface::windowFor(WindowId wid) const 0503 { 0504 auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { 0505 return w->isValid() && w->internalId() == wid; 0506 }); 0507 0508 if (it == m_windowManagement->windows().constEnd()) { 0509 return nullptr; 0510 } 0511 0512 return *it; 0513 } 0514 0515 QIcon WaylandInterface::iconFor(WindowId wid) const 0516 { 0517 auto window = windowFor(wid); 0518 0519 if (window) { 0520 return window->icon(); 0521 } 0522 0523 0524 return QIcon(); 0525 } 0526 0527 WindowId WaylandInterface::winIdFor(QString appId, QRect geometry) const 0528 { 0529 auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&appId, &geometry](PlasmaWindow * w) noexcept { 0530 return w->isValid() && w->appId() == appId && w->geometry() == geometry; 0531 }); 0532 0533 if (it == m_windowManagement->windows().constEnd()) { 0534 return QVariant(); 0535 } 0536 0537 return (*it)->internalId(); 0538 } 0539 0540 0541 bool WaylandInterface::windowCanBeDragged(WindowId wid) const 0542 { 0543 auto w = windowFor(wid); 0544 0545 if (w && isValidWindow(w)) { 0546 WindowInfoWrap winfo = requestInfo(wid); 0547 return (winfo.isValid() 0548 && w->isMovable() 0549 && !winfo.isMinimized() 0550 && inCurrentDesktopActivity(winfo) 0551 && !winfo.isPlasmaDesktop()); 0552 } 0553 0554 return false; 0555 } 0556 0557 bool WaylandInterface::windowCanBeMaximized(WindowId wid) const 0558 { 0559 auto w = windowFor(wid); 0560 0561 if (w && isValidWindow(w)) { 0562 WindowInfoWrap winfo = requestInfo(wid); 0563 return (winfo.isValid() 0564 && w->isMaximizeable() 0565 && !winfo.isMinimized() 0566 && inCurrentDesktopActivity(winfo) 0567 && !winfo.isPlasmaDesktop()); 0568 } 0569 0570 return false; 0571 } 0572 0573 void WaylandInterface::requestActivate(WindowId wid) const 0574 { 0575 auto w = windowFor(wid); 0576 0577 if (w) { 0578 w->requestActivate(); 0579 } 0580 } 0581 0582 void WaylandInterface::requestClose(WindowId wid) const 0583 { 0584 auto w = windowFor(wid); 0585 0586 if (w) { 0587 w->requestClose(); 0588 } 0589 } 0590 0591 0592 void WaylandInterface::requestMoveWindow(WindowId wid, QPoint from) const 0593 { 0594 WindowInfoWrap wInfo = requestInfo(wid); 0595 0596 if (windowCanBeDragged(wid) && inCurrentDesktopActivity(wInfo)) { 0597 auto w = windowFor(wid); 0598 0599 if (w && isValidWindow(w)) { 0600 w->requestMove(); 0601 } 0602 } 0603 } 0604 0605 void WaylandInterface::requestToggleIsOnAllDesktops(WindowId wid) const 0606 { 0607 #if KF5_VERSION_MINOR >= 52 0608 auto w = windowFor(wid); 0609 0610 if (w && isValidWindow(w) && m_desktops.count() > 1) { 0611 if (w->isOnAllDesktops()) { 0612 w->requestEnterVirtualDesktop(m_currentDesktop); 0613 } else { 0614 const QStringList &now = w->plasmaVirtualDesktops(); 0615 0616 foreach (const QString &desktop, now) { 0617 w->requestLeaveVirtualDesktop(desktop); 0618 } 0619 } 0620 } 0621 #endif 0622 } 0623 0624 void WaylandInterface::requestToggleKeepAbove(WindowId wid) const 0625 { 0626 auto w = windowFor(wid); 0627 0628 if (w) { 0629 w->requestToggleKeepAbove(); 0630 } 0631 } 0632 0633 void WaylandInterface::requestToggleMinimized(WindowId wid) const 0634 { 0635 auto w = windowFor(wid); 0636 WindowInfoWrap wInfo = requestInfo(wid); 0637 0638 if (w && isValidWindow(w) && inCurrentDesktopActivity(wInfo)) { 0639 #if KF5_VERSION_MINOR >= 52 0640 if (!m_currentDesktop.isEmpty()) { 0641 w->requestEnterVirtualDesktop(m_currentDesktop); 0642 } 0643 #endif 0644 w->requestToggleMinimized(); 0645 } 0646 } 0647 0648 void WaylandInterface::requestToggleMaximized(WindowId wid) const 0649 { 0650 auto w = windowFor(wid); 0651 WindowInfoWrap wInfo = requestInfo(wid); 0652 0653 if (w && isValidWindow(w) && windowCanBeMaximized(wid) && inCurrentDesktopActivity(wInfo)) { 0654 #if KF5_VERSION_MINOR >= 52 0655 if (!m_currentDesktop.isEmpty()) { 0656 w->requestEnterVirtualDesktop(m_currentDesktop); 0657 } 0658 #endif 0659 w->requestToggleMaximized(); 0660 } 0661 } 0662 0663 bool WaylandInterface::isPlasmaDesktop(const KWayland::Client::PlasmaWindow *w) const 0664 { 0665 if (!w || (w->appId() != QLatin1String("org.kde.plasmashell"))) { 0666 return false; 0667 } 0668 0669 return AbstractWindowInterface::isPlasmaDesktop(w->geometry()); 0670 } 0671 0672 bool WaylandInterface::isPlasmaPanel(const KWayland::Client::PlasmaWindow *w) const 0673 { 0674 if (!w || (w->appId() != QLatin1String("org.kde.plasmashell"))) { 0675 return false; 0676 } 0677 0678 return AbstractWindowInterface::isPlasmaPanel(w->geometry()); 0679 } 0680 0681 bool WaylandInterface::isValidWindow(const KWayland::Client::PlasmaWindow *w) const 0682 { 0683 //! DEPRECATED comment is case we must reenable this 0684 //! because wayland does not have any way yet to identify the window type 0685 //! a trick is to just consider windows as valid when they can be shown in the 0686 //! taskbar. Of course that creates issues with plasma native dialogs 0687 //! e.g. widgets explorer, Activities etc. that are not used to hide 0688 //! the dodge views appropriately 0689 0690 bool hasSkipTaskbar = w->skipTaskbar(); 0691 bool isSkipped = hasSkipTaskbar; 0692 0693 #if KF5_VERSION_MINOR >= 47 0694 bool hasSkipSwitcher = w->skipSwitcher(); 0695 isSkipped = hasSkipTaskbar && hasSkipSwitcher; 0696 #endif 0697 0698 return w->isValid() && !isPlasmaDesktop(w) && !isSkipped && !m_plasmaPanels.contains(w->internalId()) && !m_ignoredWindows.contains(w->internalId()); 0699 } 0700 0701 void WaylandInterface::updateWindow() 0702 { 0703 PlasmaWindow *pW = qobject_cast<PlasmaWindow*>(QObject::sender()); 0704 0705 if (pW && !m_ignoredWindows.contains(pW->internalId() && !isPlasmaDesktop(pW) )) { 0706 if (pW->appId() == QLatin1String("org.kde.plasmashell")) { 0707 if (isPlasmaDesktop(pW)) { 0708 return; 0709 } else if (isPlasmaPanel(pW)) { 0710 registerIgnoredWindow(pW->internalId()); 0711 } 0712 } 0713 0714 considerWindowChanged(pW->internalId()); 0715 } 0716 } 0717 0718 void WaylandInterface::windowUnmapped() 0719 { 0720 PlasmaWindow *pW = qobject_cast<PlasmaWindow*>(QObject::sender()); 0721 0722 if (pW) { 0723 untrackWindow(pW); 0724 emit windowRemoved(pW->internalId()); 0725 } 0726 } 0727 0728 void WaylandInterface::trackWindow(KWayland::Client::PlasmaWindow *w) 0729 { 0730 if (!w) { 0731 return; 0732 } 0733 0734 connect(w, &PlasmaWindow::activeChanged, this, &WaylandInterface::updateWindow); 0735 connect(w, &PlasmaWindow::titleChanged, this, &WaylandInterface::updateWindow); 0736 connect(w, &PlasmaWindow::fullscreenChanged, this, &WaylandInterface::updateWindow); 0737 connect(w, &PlasmaWindow::geometryChanged, this, &WaylandInterface::updateWindow); 0738 connect(w, &PlasmaWindow::maximizedChanged, this, &WaylandInterface::updateWindow); 0739 connect(w, &PlasmaWindow::minimizedChanged, this, &WaylandInterface::updateWindow); 0740 connect(w, &PlasmaWindow::shadedChanged, this, &WaylandInterface::updateWindow); 0741 connect(w, &PlasmaWindow::skipTaskbarChanged, this, &WaylandInterface::updateWindow); 0742 connect(w, &PlasmaWindow::onAllDesktopsChanged, this, &WaylandInterface::updateWindow); 0743 connect(w, &PlasmaWindow::parentWindowChanged, this, &WaylandInterface::updateWindow); 0744 0745 #if KF5_VERSION_MINOR >= 52 0746 connect(w, &PlasmaWindow::plasmaVirtualDesktopEntered, this, &WaylandInterface::updateWindow); 0747 connect(w, &PlasmaWindow::plasmaVirtualDesktopLeft, this, &WaylandInterface::updateWindow); 0748 #else 0749 connect(w, &PlasmaWindow::virtualDesktopChanged, this, &WaylandInterface::updateWindow); 0750 #endif 0751 0752 connect(w, &PlasmaWindow::unmapped, this, &WaylandInterface::windowUnmapped); 0753 } 0754 0755 void WaylandInterface::untrackWindow(KWayland::Client::PlasmaWindow *w) 0756 { 0757 if (!w) { 0758 return; 0759 } 0760 0761 disconnect(w, &PlasmaWindow::activeChanged, this, &WaylandInterface::updateWindow); 0762 disconnect(w, &PlasmaWindow::titleChanged, this, &WaylandInterface::updateWindow); 0763 disconnect(w, &PlasmaWindow::fullscreenChanged, this, &WaylandInterface::updateWindow); 0764 disconnect(w, &PlasmaWindow::geometryChanged, this, &WaylandInterface::updateWindow); 0765 disconnect(w, &PlasmaWindow::maximizedChanged, this, &WaylandInterface::updateWindow); 0766 disconnect(w, &PlasmaWindow::minimizedChanged, this, &WaylandInterface::updateWindow); 0767 disconnect(w, &PlasmaWindow::shadedChanged, this, &WaylandInterface::updateWindow); 0768 disconnect(w, &PlasmaWindow::skipTaskbarChanged, this, &WaylandInterface::updateWindow); 0769 disconnect(w, &PlasmaWindow::onAllDesktopsChanged, this, &WaylandInterface::updateWindow); 0770 disconnect(w, &PlasmaWindow::parentWindowChanged, this, &WaylandInterface::updateWindow); 0771 0772 #if KF5_VERSION_MINOR >= 52 0773 disconnect(w, &PlasmaWindow::plasmaVirtualDesktopEntered, this, &WaylandInterface::updateWindow); 0774 disconnect(w, &PlasmaWindow::plasmaVirtualDesktopLeft, this, &WaylandInterface::updateWindow); 0775 #else 0776 disconnect(w, &PlasmaWindow::virtualDesktopChanged, this, &WaylandInterface::updateWindow); 0777 #endif 0778 0779 disconnect(w, &PlasmaWindow::unmapped, this, &WaylandInterface::windowUnmapped); 0780 } 0781 0782 0783 void WaylandInterface::windowCreatedProxy(KWayland::Client::PlasmaWindow *w) 0784 { 0785 if (!isValidWindow(w)) { 0786 return; 0787 } 0788 0789 if ((w->appId() == QLatin1String("org.kde.plasmashell")) && isPlasmaPanel(w)) { 0790 registerPlasmaPanel(w->internalId()); 0791 } else { 0792 trackWindow(w); 0793 emit windowAdded(w->internalId()); 0794 } 0795 0796 if (w->appId() == "latte-dock") { 0797 emit latteWindowAdded(); 0798 } 0799 } 0800 0801 } 0802 } 0803 0804 #include "waylandinterface.moc"