/* SPDX-FileCopyrightText: 2016 Smith AR SPDX-FileCopyrightText: 2016 Michail Vourlakos SPDX-License-Identifier: GPL-2.0-or-later */ #include "waylandinterface.h" // local #include #include "../view/positioner.h" #include "../view/view.h" #include "../view/settings/subconfigview.h" #include "../view/helpers/screenedgeghostwindow.h" #include "../lattecorona.h" // Qt #include #include #include #include #include #include // KDE #include #include #include #include #if KF5_VERSION_MINOR >= 52 #include #endif // X11 #include using namespace KWayland::Client; namespace Latte { namespace WindowSystem { WaylandInterface::WaylandInterface(QObject *parent) : AbstractWindowInterface(parent) { m_corona = qobject_cast(parent); } WaylandInterface::~WaylandInterface() { } void WaylandInterface::init() { } void WaylandInterface::initWindowManagement(KWayland::Client::PlasmaWindowManagement *windowManagement) { if (m_windowManagement == windowManagement) { return; } m_windowManagement = windowManagement; connect(m_windowManagement, &PlasmaWindowManagement::windowCreated, this, &WaylandInterface::windowCreatedProxy); connect(m_windowManagement, &PlasmaWindowManagement::activeWindowChanged, this, [&]() noexcept { auto w = m_windowManagement->activeWindow(); if (!w || (w && (!m_ignoredWindows.contains(w->internalId()))) ) { emit activeWindowChanged(w ? w->internalId() : 0); } }, Qt::QueuedConnection); } #if KF5_VERSION_MINOR >= 52 void WaylandInterface::initVirtualDesktopManagement(KWayland::Client::PlasmaVirtualDesktopManagement *virtualDesktopManagement) { if (m_virtualDesktopManagement == virtualDesktopManagement) { return; } m_virtualDesktopManagement = virtualDesktopManagement; connect(m_virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopCreated, this, [this](const QString &id, quint32 position) { addDesktop(id, position); }); connect(m_virtualDesktopManagement, &KWayland::Client::PlasmaVirtualDesktopManagement::desktopRemoved, this, [this](const QString &id) { m_desktops.removeAll(id); if (m_currentDesktop == id) { setCurrentDesktop(QString()); } }); } void WaylandInterface::addDesktop(const QString &id, quint32 position) { if (m_desktops.contains(id)) { return; } m_desktops.append(id); const KWayland::Client::PlasmaVirtualDesktop *desktop = m_virtualDesktopManagement->getVirtualDesktop(id); QObject::connect(desktop, &KWayland::Client::PlasmaVirtualDesktop::activated, this, [desktop, this]() { setCurrentDesktop(desktop->id()); } ); if (desktop->isActive()) { setCurrentDesktop(id); } } void WaylandInterface::setCurrentDesktop(QString desktop) { if (m_currentDesktop == desktop) { return; } m_currentDesktop = desktop; emit currentDesktopChanged(); } #endif //! Register Latte Ignored Windows in order to NOT be tracked void WaylandInterface::registerIgnoredWindow(WindowId wid) { if (!wid.isNull() && !m_ignoredWindows.contains(wid)) { m_ignoredWindows.append(wid); KWayland::Client::PlasmaWindow *w = windowFor(wid); if (w) { untrackWindow(w); } emit windowChanged(wid); } } void WaylandInterface::unregisterIgnoredWindow(WindowId wid) { if (m_ignoredWindows.contains(wid)) { m_ignoredWindows.removeAll(wid); emit windowRemoved(wid); } } void WaylandInterface::setViewExtraFlags(QWindow *view, bool isPanelWindow, Latte::Types::Visibility mode) { if (!view) { return; } auto layerWindow = LayerShellQt::Window::get(view); #if KF5_VERSION_MINOR >= 45 KWindowSystem::setState(view->winId(), NET::SkipTaskbar | NET::SkipPager | NET::SkipSwitcher); #else KWindowSystem::setState(view->winId(), NET::SkipTaskbar | NET::SkipPager); #endif KWindowSystem::setOnAllDesktops(view->winId(), true); bool atBottom{!isPanelWindow && (mode == Latte::Types::WindowsCanCover || mode == Latte::Types::WindowsAlwaysCover)}; if (!atBottom) { layerWindow->setLayer(LayerShellQt::Window::LayerTop); } else { layerWindow->setLayer(LayerShellQt::Window::LayerBottom); } if (view->flags().testFlag(Qt::WindowDoesNotAcceptFocus) && mode != Latte::Types::NormalWindow) { layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityNone); } else { layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand); } } void WaylandInterface::setViewStruts(QWindow *view, const QRect &rect, Plasma::Types::Location location) { if (!view) { return; } auto layerWindow = LayerShellQt::Window::get(view); int thickness = rect.height(); if (location == Plasma::Types::LeftEdge || location == Plasma::Types::RightEdge) { thickness = rect.width(); } LayerShellQt::Window::Anchors anchors = layerWindow->anchors(); if (location == Plasma::Types::TopEdge) { anchors = LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorLeft; anchors = anchors | LayerShellQt::Window::AnchorRight; } else if (location == Plasma::Types::LeftEdge) { anchors = LayerShellQt::Window::AnchorLeft; anchors = anchors | LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorBottom; } else if (location == Plasma::Types::BottomEdge) { anchors = LayerShellQt::Window::AnchorBottom; anchors = anchors | LayerShellQt::Window::AnchorLeft; anchors = anchors | LayerShellQt::Window::AnchorRight; } else if (location == Plasma::Types::RightEdge) { anchors = LayerShellQt::Window::AnchorRight; anchors = anchors | LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorBottom; } layerWindow->setAnchors(anchors); layerWindow->setExclusiveZone(thickness); } void WaylandInterface::removeViewStruts(QWindow *view) { if (!view) { return; } auto layerWindow = LayerShellQt::Window::get(view); layerWindow->setExclusiveZone(-1); } void WaylandInterface::switchToNextVirtualDesktop() { #if KF5_VERSION_MINOR >= 52 if (!m_virtualDesktopManagement || m_desktops.count() <= 1) { return; } int curPos = m_desktops.indexOf(m_currentDesktop); int nextPos = curPos + 1; if (curPos >= m_desktops.count()-1) { if (isVirtualDesktopNavigationWrappingAround()) { nextPos = 0; } else { return; } } KWayland::Client::PlasmaVirtualDesktop *desktopObj = m_virtualDesktopManagement->getVirtualDesktop(m_desktops[nextPos]); if (desktopObj) { desktopObj->requestActivate(); } #endif } void WaylandInterface::switchToPreviousVirtualDesktop() { #if KF5_VERSION_MINOR >= 52 if (!m_virtualDesktopManagement || m_desktops.count() <= 1) { return; } int curPos = m_desktops.indexOf(m_currentDesktop); int nextPos = curPos - 1; if (curPos <= 0) { if (isVirtualDesktopNavigationWrappingAround()) { nextPos = m_desktops.count()-1; } else { return; } } KWayland::Client::PlasmaVirtualDesktop *desktopObj = m_virtualDesktopManagement->getVirtualDesktop(m_desktops[nextPos]); if (desktopObj) { desktopObj->requestActivate(); } #endif } void WaylandInterface::setWindowOnActivities(const WindowId &wid, const QStringList &nextactivities) { #if KF5_VERSION_MINOR >= 81 auto winfo = requestInfo(wid); auto w = windowFor(wid); if (!w) { return; } QStringList curactivities = winfo.activities(); if (!winfo.isOnAllActivities() && nextactivities.isEmpty()) { //! window must be set to all activities for(int i=0; irequestLeaveActivity(curactivities[i]); } } else if (curactivities != nextactivities) { QStringList requestenter; QStringList requestleave; for (int i=0; irequestLeaveActivity(requestleave[i]); } //! first enter to new activities for (int i=0; irequestEnterActivity(requestenter[i]); } } #endif } WindowId WaylandInterface::activeWindow() { if (!m_windowManagement) { return 0; } auto wid = m_windowManagement->activeWindow(); return wid ? wid->internalId() : 0; } void WaylandInterface::skipTaskBar(const QDialog &dialog) { KWindowSystem::setState(dialog.winId(), NET::SkipTaskbar); } void WaylandInterface::slideWindow(QWindow &view, AbstractWindowInterface::Slide location) { auto slideLocation = KWindowEffects::NoEdge; switch (location) { case Slide::Top: slideLocation = KWindowEffects::TopEdge; break; case Slide::Bottom: slideLocation = KWindowEffects::BottomEdge; break; case Slide::Left: slideLocation = KWindowEffects::LeftEdge; break; case Slide::Right: slideLocation = KWindowEffects::RightEdge; break; default: break; } KWindowEffects::slideWindow(view.winId(), slideLocation, -1); } void WaylandInterface::enableBlurBehind(QWindow &view) { KWindowEffects::enableBlurBehind(view.winId()); } void WaylandInterface::setActiveEdge(QWindow *view, bool active) { //ViewPart::ScreenEdgeGhostWindow *window = qobject_cast(view); //if (!window) { // return; //} /*if (window->parentView()->surface() && window->parentView()->visibility() && (window->parentView()->visibility()->mode() == Types::DodgeActive || window->parentView()->visibility()->mode() == Types::DodgeMaximized || window->parentView()->visibility()->mode() == Types::DodgeAllWindows || window->parentView()->visibility()->mode() == Types::AutoHide)) { if (active) { window->showWithMask(); window->surface()->requestHideAutoHidingPanel(); } else { window->hideWithMask(); window->surface()->requestShowAutoHidingPanel(); } }*/ } void WaylandInterface::setWindowPosition(QWindow *window, const Plasma::Types::Location &location, const QRect &geometry) { if (!window || !window->screen()) { return; } auto layerWindow = LayerShellQt::Window::get(window); QMargins margins; LayerShellQt::Window::Anchors anchors = layerWindow->anchors(); if (layerWindow->exclusionZone() <= 0) { //! WorkAround: Because kwin_wayland layershell suppport is working nicely only for windows //! that are anchored on TopEdge. Anything related to Bottom and Right could fail regularly in //! its positioning anchors = LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorLeft; margins.setTop(geometry.top() - window->screen()->geometry().top()); margins.setLeft(geometry.left() - window->screen()->geometry().left()); layerWindow->setExclusiveZone(-1); } else { margins.setTop(geometry.top() - window->screen()->geometry().top()); margins.setLeft(geometry.left() - window->screen()->geometry().left()); margins.setBottom(window->screen()->geometry().bottom() - geometry.bottom()); margins.setRight(window->screen()->geometry().right() - geometry.right()); } /* if (location == Plasma::Types::TopEdge || location == Plasma::Types::LeftEdge) { anchors = LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorLeft; margins.setTop(geometry.top() - window->screen()->geometry().top()); margins.setLeft(geometry.left() - window->screen()->geometry().left()); } else if (location == Plasma::Types::RightEdge) { anchors = LayerShellQt::Window::AnchorTop; anchors = anchors | LayerShellQt::Window::AnchorRight; margins.setTop(geometry.top() - window->screen()->geometry().top()); margins.setRight(window->screen()->geometry().right() - geometry.right()); } else { // bottom case anchors = LayerShellQt::Window::AnchorBottom; anchors = anchors | LayerShellQt::Window::AnchorLeft; margins.setBottom(window->screen()->geometry().bottom() - geometry.bottom()); margins.setLeft(geometry.left() - window->screen()->geometry().left()); //! when window changes height the kwin wm is not taking into account the anchoring. //! Such an example is when PrimaryConfigView changes from normal to advanced mode and back }*/ layerWindow->setAnchors(anchors); layerWindow->setMargins(margins); window->setPosition(geometry.topLeft()); qDebug() << "org.kde.layer ::: " << layerWindow->anchors() << " __ " << layerWindow->layer() << " :: " << geometry << " :: " << margins << " :: " << layerWindow->exclusionZone(); } void WaylandInterface::setFrameExtents(QWindow *view, const QMargins &extents) { //! do nothing until there is a wayland way to provide this } void WaylandInterface::setInputMask(QWindow *window, const QRect &rect) { //! do nothins, QWindow::mask() is sufficient enough in order to define Window input mask } WindowInfoWrap WaylandInterface::requestInfoActive() { if (!m_windowManagement) { return {}; } auto w = m_windowManagement->activeWindow(); if (!w) return {}; return requestInfo(w->internalId()); } WindowInfoWrap WaylandInterface::requestInfo(WindowId wid) { WindowInfoWrap winfoWrap; auto w = windowFor(wid); //!used to track Plasma DesktopView windows because during startup can not be identified properly bool plasmaBlockedWindow = w && (w->appId() == QLatin1String("org.kde.plasmashell")) && !isAcceptableWindow(w); if (w) { winfoWrap.setIsValid(isValidWindow(w) && !plasmaBlockedWindow); winfoWrap.setWid(wid); winfoWrap.setParentId(w->parentWindow() ? w->parentWindow()->internalId() : 0); winfoWrap.setIsActive(w->isActive()); winfoWrap.setIsMinimized(w->isMinimized()); winfoWrap.setIsMaxVert(w->isMaximized()); winfoWrap.setIsMaxHoriz(w->isMaximized()); winfoWrap.setIsFullscreen(w->isFullscreen()); winfoWrap.setIsShaded(w->isShaded()); winfoWrap.setIsOnAllDesktops(w->isOnAllDesktops()); #if KF5_VERSION_MINOR >= 81 winfoWrap.setIsOnAllActivities(w->plasmaActivities().isEmpty()); #else winfoWrap.setIsOnAllActivities(true); #endif winfoWrap.setIsKeepAbove(w->isKeepAbove()); winfoWrap.setIsKeepBelow(w->isKeepBelow()); winfoWrap.setGeometry(w->geometry()); #if KF5_VERSION_MINOR >= 47 winfoWrap.setHasSkipSwitcher(w->skipSwitcher()); #endif winfoWrap.setHasSkipTaskbar(w->skipTaskbar()); //! BEGIN:Window Abilities winfoWrap.setIsClosable(w->isCloseable()); winfoWrap.setIsFullScreenable(w->isFullscreenable()); winfoWrap.setIsMaximizable(w->isMaximizeable()); winfoWrap.setIsMinimizable(w->isMinimizeable()); winfoWrap.setIsMovable(w->isMovable()); winfoWrap.setIsResizable(w->isResizable()); winfoWrap.setIsShadeable(w->isShadeable()); winfoWrap.setIsVirtualDesktopsChangeable(w->isVirtualDesktopChangeable()); //! END:Window Abilities winfoWrap.setDisplay(w->title()); #if KF5_VERSION_MINOR >= 52 winfoWrap.setDesktops(w->plasmaVirtualDesktops()); #endif #if KF5_VERSION_MINOR >= 81 winfoWrap.setActivities(w->plasmaActivities()); #else winfoWrap.setActivities(QStringList()); #endif } else { winfoWrap.setIsValid(false); } if (plasmaBlockedWindow) { windowRemoved(w->internalId()); } return winfoWrap; } AppData WaylandInterface::appDataFor(WindowId wid) { auto window = windowFor(wid); if (window) { const AppData &data = appDataFromUrl(windowUrlFromMetadata(window->appId(), window->pid(), rulesConfig)); return data; } AppData empty; return empty; } KWayland::Client::PlasmaWindow *WaylandInterface::windowFor(WindowId wid) { if (!m_windowManagement) { return nullptr; } auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { return w->isValid() && w->internalId() == wid; }); if (it == m_windowManagement->windows().constEnd()) { return nullptr; } return *it; } QIcon WaylandInterface::iconFor(WindowId wid) { auto window = windowFor(wid); if (window) { return window->icon(); } return QIcon(); } WindowId WaylandInterface::winIdFor(QString appId, QString title) { if (!m_windowManagement) { return -1; } auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&appId, &title](PlasmaWindow * w) noexcept { return w->isValid() && w->appId() == appId && w->title().startsWith(title); }); if (it == m_windowManagement->windows().constEnd()) { return QVariant(); } return (*it)->internalId(); } WindowId WaylandInterface::winIdFor(QString appId, QRect geometry) { if (!m_windowManagement) { return -1; } auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&appId, &geometry](PlasmaWindow * w) noexcept { return w->isValid() && w->appId() == appId && w->geometry() == geometry; }); if (it == m_windowManagement->windows().constEnd()) { return QVariant(); } return (*it)->internalId(); } bool WaylandInterface::windowCanBeDragged(WindowId wid) { auto w = windowFor(wid); if (w && isValidWindow(w)) { WindowInfoWrap winfo = requestInfo(wid); return (winfo.isValid() && w->isMovable() && !winfo.isMinimized() && inCurrentDesktopActivity(winfo)); } return false; } bool WaylandInterface::windowCanBeMaximized(WindowId wid) { auto w = windowFor(wid); if (w && isValidWindow(w)) { WindowInfoWrap winfo = requestInfo(wid); return (winfo.isValid() && w->isMaximizeable() && !winfo.isMinimized() && inCurrentDesktopActivity(winfo)); } return false; } void WaylandInterface::requestActivate(WindowId wid) { auto w = windowFor(wid); if (w) { w->requestActivate(); } } void WaylandInterface::requestClose(WindowId wid) { auto w = windowFor(wid); if (w) { w->requestClose(); } } void WaylandInterface::requestMoveWindow(WindowId wid, QPoint from) { WindowInfoWrap wInfo = requestInfo(wid); if (windowCanBeDragged(wid) && inCurrentDesktopActivity(wInfo)) { auto w = windowFor(wid); if (w && isValidWindow(w)) { w->requestMove(); } } } void WaylandInterface::requestToggleIsOnAllDesktops(WindowId wid) { #if KF5_VERSION_MINOR >= 52 auto w = windowFor(wid); if (w && isValidWindow(w) && m_desktops.count() > 1) { if (w->isOnAllDesktops()) { w->requestEnterVirtualDesktop(m_currentDesktop); } else { const QStringList &now = w->plasmaVirtualDesktops(); foreach (const QString &desktop, now) { w->requestLeaveVirtualDesktop(desktop); } } } #endif } void WaylandInterface::requestToggleKeepAbove(WindowId wid) { auto w = windowFor(wid); if (w) { w->requestToggleKeepAbove(); } } void WaylandInterface::setKeepAbove(WindowId wid, bool active) { auto w = windowFor(wid); if (w) { if (active) { setKeepBelow(wid, false); } if ((w->isKeepAbove() && active) || (!w->isKeepAbove() && !active)) { return; } w->requestToggleKeepAbove(); } } void WaylandInterface::setKeepBelow(WindowId wid, bool active) { auto w = windowFor(wid); if (w) { if (active) { setKeepAbove(wid, false); } if ((w->isKeepBelow() && active) || (!w->isKeepBelow() && !active)) { return; } w->requestToggleKeepBelow(); } } void WaylandInterface::requestToggleMinimized(WindowId wid) { auto w = windowFor(wid); WindowInfoWrap wInfo = requestInfo(wid); if (w && isValidWindow(w) && inCurrentDesktopActivity(wInfo)) { #if KF5_VERSION_MINOR >= 52 if (!m_currentDesktop.isEmpty()) { w->requestEnterVirtualDesktop(m_currentDesktop); } #endif w->requestToggleMinimized(); } } void WaylandInterface::requestToggleMaximized(WindowId wid) { auto w = windowFor(wid); WindowInfoWrap wInfo = requestInfo(wid); if (w && isValidWindow(w) && windowCanBeMaximized(wid) && inCurrentDesktopActivity(wInfo)) { #if KF5_VERSION_MINOR >= 52 if (!m_currentDesktop.isEmpty()) { w->requestEnterVirtualDesktop(m_currentDesktop); } #endif w->requestToggleMaximized(); } } bool WaylandInterface::isPlasmaPanel(const KWayland::Client::PlasmaWindow *w) const { if (!w || (w->appId() != QLatin1String("org.kde.plasmashell"))) { return false; } return AbstractWindowInterface::isPlasmaPanel(w->geometry()); } bool WaylandInterface::isFullScreenWindow(const KWayland::Client::PlasmaWindow *w) const { if (!w) { return false; } return w->isFullscreen() || AbstractWindowInterface::isFullScreenWindow(w->geometry()); } bool WaylandInterface::isSidepanel(const KWayland::Client::PlasmaWindow *w) const { if (!w) { return false; } return AbstractWindowInterface::isSidepanel(w->geometry()); } bool WaylandInterface::isValidWindow(const KWayland::Client::PlasmaWindow *w) { if (!w || !w->isValid()) { return false; } if (windowsTracker()->isValidFor(w->internalId())) { return true; } return isAcceptableWindow(w); } bool WaylandInterface::isAcceptableWindow(const KWayland::Client::PlasmaWindow *w) { if (!w || !w->isValid()) { return false; } //! ignored windows that are not tracked if (hasBlockedTracking(w->internalId())) { return false; } //! whitelisted/approved windows if (isWhitelistedWindow(w->internalId())) { return true; } //! Window Checks bool hasSkipTaskbar = w->skipTaskbar(); bool isSkipped = hasSkipTaskbar; #if KF5_VERSION_MINOR >= 47 bool hasSkipSwitcher = w->skipSwitcher(); isSkipped = hasSkipTaskbar && hasSkipSwitcher; #endif if (isSkipped && ((w->appId() == QLatin1String("yakuake") || (w->appId() == QLatin1String("krunner"))) )) { registerWhitelistedWindow(w->internalId()); } else if (w->appId() == QLatin1String("org.kde.plasmashell")) { if (isSkipped && isSidepanel(w)) { registerWhitelistedWindow(w->internalId()); return true; } else if (isPlasmaPanel(w) || isFullScreenWindow(w)) { registerPlasmaIgnoredWindow(w->internalId()); return false; } } else if ((w->appId() == QLatin1String("latte-dock")) || (w->appId().startsWith(QLatin1String("ksmserver")))) { if (isFullScreenWindow(w)) { registerIgnoredWindow(w->internalId()); return false; } } return !isSkipped; } void WaylandInterface::updateWindow() { PlasmaWindow *pW = qobject_cast(QObject::sender()); if (isValidWindow(pW)) { considerWindowChanged(pW->internalId()); } } void WaylandInterface::windowUnmapped() { PlasmaWindow *pW = qobject_cast(QObject::sender()); if (pW) { untrackWindow(pW); emit windowRemoved(pW->internalId()); } } void WaylandInterface::trackWindow(KWayland::Client::PlasmaWindow *w) { if (!w) { return; } connect(w, &PlasmaWindow::activeChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::titleChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::fullscreenChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::geometryChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::maximizedChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::minimizedChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::shadedChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::skipTaskbarChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::onAllDesktopsChanged, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::parentWindowChanged, this, &WaylandInterface::updateWindow); #if KF5_VERSION_MINOR >= 52 connect(w, &PlasmaWindow::plasmaVirtualDesktopEntered, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::plasmaVirtualDesktopLeft, this, &WaylandInterface::updateWindow); #else connect(w, &PlasmaWindow::virtualDesktopChanged, this, &WaylandInterface::updateWindow); #endif #if KF5_VERSION_MINOR >= 81 connect(w, &PlasmaWindow::plasmaActivityEntered, this, &WaylandInterface::updateWindow); connect(w, &PlasmaWindow::plasmaActivityLeft, this, &WaylandInterface::updateWindow); #endif connect(w, &PlasmaWindow::unmapped, this, &WaylandInterface::windowUnmapped); } void WaylandInterface::untrackWindow(KWayland::Client::PlasmaWindow *w) { if (!w) { return; } disconnect(w, &PlasmaWindow::activeChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::titleChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::fullscreenChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::geometryChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::maximizedChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::minimizedChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::shadedChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::skipTaskbarChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::onAllDesktopsChanged, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::parentWindowChanged, this, &WaylandInterface::updateWindow); #if KF5_VERSION_MINOR >= 52 disconnect(w, &PlasmaWindow::plasmaVirtualDesktopEntered, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::plasmaVirtualDesktopLeft, this, &WaylandInterface::updateWindow); #else disconnect(w, &PlasmaWindow::virtualDesktopChanged, this, &WaylandInterface::updateWindow); #endif #if KF5_VERSION_MINOR >= 81 disconnect(w, &PlasmaWindow::plasmaActivityEntered, this, &WaylandInterface::updateWindow); disconnect(w, &PlasmaWindow::plasmaActivityLeft, this, &WaylandInterface::updateWindow); #endif disconnect(w, &PlasmaWindow::unmapped, this, &WaylandInterface::windowUnmapped); } void WaylandInterface::windowCreatedProxy(KWayland::Client::PlasmaWindow *w) { if (!isAcceptableWindow(w)) { return; } trackWindow(w); emit windowAdded(w->internalId()); if (w->appId() == QLatin1String("latte-dock")) { emit latteWindowAdded(); } } } } #include "waylandinterface.moc"