diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index a7be8cb7..2dceb434 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,86 +1,86 @@ set(lattedock-app_SRCS ../liblattedock/dock.cpp packageplugins/shell/dockpackage.cpp - abstractwindowinterface.cpp alternativeshelper.cpp commontools.cpp dockcorona.cpp globalshortcuts.cpp importer.cpp infoview.cpp launcherssignals.cpp layout.cpp layoutmanager.cpp plasmathemeextended.cpp schemecolors.cpp screenpool.cpp sortedactivitiesmodel.cpp - waylandinterface.cpp - windowinfowrap.cpp - xwindowinterface.cpp dock/contextmenu.cpp dock/dockconfigview.cpp dock/docksecconfigview.cpp dock/dockview.cpp dock/effects.cpp dock/panelshadows.cpp dock/positioner.cpp dock/screenedgeghostwindow.cpp dock/visibilitymanager.cpp settings/settingsdialog.cpp settings/universalsettings.cpp settings/delegates/activitycmbboxdelegate.cpp settings/delegates/checkboxdelegate.cpp settings/delegates/colorcmbboxdelegate.cpp settings/delegates/colorcmbboxitemdelegate.cpp settings/delegates/layoutnamedelegate.cpp + wm/abstractwindowinterface.cpp + wm/waylandinterface.cpp + wm/windowinfowrap.cpp + wm/xwindowinterface.cpp main.cpp ) set(latte_dbusXML dbus/org.kde.LatteDock.xml) qt5_add_dbus_adaptor(lattedock-app_SRCS ${latte_dbusXML} dockcorona.h Latte::DockCorona lattedockadaptor) ki18n_wrap_ui(lattedock-app_SRCS settingsdialog.ui) add_executable(latte-dock ${lattedock-app_SRCS}) include(FakeTarget.cmake) target_link_libraries(latte-dock Qt5::DBus Qt5::Quick Qt5::Qml KF5::I18n KF5::DBusAddons KF5::Declarative KF5::CoreAddons KF5::GlobalAccel KF5::Archive KF5::Crash KF5::XmlGui KF5::Plasma KF5::PlasmaQuick KF5::Activities KF5::Notifications KF5::NewStuff KF5::QuickAddons KF5::WaylandClient ) if(HAVE_X11) target_link_libraries(latte-dock Qt5::X11Extras KF5::WindowSystem ${X11_LIBRARIES} ${XCB_LIBRARIES} ) endif() configure_file(org.kde.latte-dock.desktop.cmake org.kde.latte-dock.desktop) configure_file(org.kde.latte-dock.appdata.xml.cmake org.kde.latte-dock.appdata.xml) install(TARGETS latte-dock ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES dbus/org.kde.LatteDock.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR}) install(FILES lattedock.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) install(FILES latte-layouts.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) diff --git a/app/dock/dockconfigview.cpp b/app/dock/dockconfigview.cpp index 19c10a29..6a8304ba 100644 --- a/app/dock/dockconfigview.cpp +++ b/app/dock/dockconfigview.cpp @@ -1,583 +1,583 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dockconfigview.h" #include "dockview.h" #include "panelshadows_p.h" -#include "../abstractwindowinterface.h" #include "../dockcorona.h" #include "../layoutmanager.h" #include "../settings/universalsettings.h" +#include "../wm/abstractwindowinterface.h" #include #include #include #include #include #include #include #include #include #include #include namespace Latte { DockConfigView::DockConfigView(Plasma::Containment *containment, DockView *dockView, QWindow *parent) : PlasmaQuick::ConfigView(containment, parent), m_dockView(dockView) { m_corona = qobject_cast(m_dockView->containment()->corona()); setupWaylandIntegration(); setScreen(m_dockView->screen()); if (containment) { setIcon(qGuiApp->windowIcon()); } m_screenSyncTimer.setSingleShot(true); m_screenSyncTimer.setInterval(100); connections << connect(&m_screenSyncTimer, &QTimer::timeout, this, [this]() { setScreen(m_dockView->screen()); setFlags(wFlags()); syncGeometry(); syncSlideEffect(); }); connections << connect(dockView->visibility(), &VisibilityManager::modeChanged, this, &DockConfigView::syncGeometry); connections << connect(containment, &Plasma::Containment::immutabilityChanged, this, &DockConfigView::immutabilityChanged); m_thicknessSyncTimer.setSingleShot(true); m_thicknessSyncTimer.setInterval(200); connections << connect(&m_thicknessSyncTimer, &QTimer::timeout, this, [this]() { syncGeometry(); }); connections << connect(dockView, &DockView::normalThicknessChanged, [&]() { m_thicknessSyncTimer.start(); }); if (m_corona) { connections << connect(m_corona, SIGNAL(raiseDocksTemporaryChanged()), this, SIGNAL(raiseDocksTemporaryChanged())); } } DockConfigView::~DockConfigView() { qDebug() << "DockConfigView deleting ..."; deleteSecondaryWindow(); foreach (auto var, connections) { QObject::disconnect(var); } if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; } } void DockConfigView::init() { qDebug() << "dock config view : initialization started..."; setDefaultAlphaBuffer(true); setColor(Qt::transparent); PanelShadows::self()->addWindow(this); rootContext()->setContextProperty(QStringLiteral("dock"), m_dockView); rootContext()->setContextProperty(QStringLiteral("dockConfig"), this); if (m_corona) { rootContext()->setContextProperty(QStringLiteral("universalSettings"), m_corona->universalSettings()); rootContext()->setContextProperty(QStringLiteral("layoutManager"), m_corona->layoutManager()); } KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.setTranslationDomain(QStringLiteral("latte-dock")); kdeclarative.setupBindings(); QByteArray tempFilePath = "lattedockconfigurationui"; updateEnabledBorders(); auto source = QUrl::fromLocalFile(m_dockView->containment()->corona()->kPackage().filePath(tempFilePath)); setSource(source); syncGeometry(); syncSlideEffect(); qDebug() << "dock config view : initialization ended..."; } inline Qt::WindowFlags DockConfigView::wFlags() const { return (flags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) & ~Qt::WindowDoesNotAcceptFocus; } QWindow *DockConfigView::secondaryWindow() { return m_secConfigView; } void DockConfigView::setAdvanced(bool advanced) { if (m_advanced == advanced) { return; } m_advanced = advanced; if (m_advanced) { createSecondaryWindow(); } else { deleteSecondaryWindow(); } } void DockConfigView::createSecondaryWindow() { //! do not proceed when secondary window is already created //! or when main dock settings window has not updated yet //! its geometry if (m_secConfigView || geometryWhenVisible().isNull()) { return; } QRect geometry = m_dockView->screenGeometry(); m_secConfigView = new DockSecConfigView(m_dockView, this); m_secConfigView->init(); if (m_secConfigView->geometryWhenVisible().intersects(geometryWhenVisible())) { setShowInlineProperties(true); m_secConfigView->hideConfigWindow(); } else { if (!KWindowSystem::isPlatformWayland()) { QTimer::singleShot(150, m_secConfigView, SLOT(show())); } else { QTimer::singleShot(150, [this]() { m_secConfigView->setVisible(true); }); } setShowInlineProperties(false); } } void DockConfigView::deleteSecondaryWindow() { if (m_secConfigView) { m_secConfigView->deleteLater(); } } QRect DockConfigView::geometryWhenVisible() const { return m_geometryWhenVisible; } void DockConfigView::syncGeometry() { if (!m_dockView->managedLayout() || !m_dockView->containment() || !rootObject()) return; const QSize size(rootObject()->width(), rootObject()->height()); setMaximumSize(size); setMinimumSize(size); resize(size); const auto location = m_dockView->containment()->location(); const auto sGeometry = m_dockView->screenGeometry(); int clearThickness = m_dockView->normalThickness() + m_dockView->fontPixelSize(); QPoint position{0, 0}; switch (m_dockView->containment()->formFactor()) { case Plasma::Types::Horizontal: { if (location == Plasma::Types::TopEdge) { position = {sGeometry.center().x() - size.width() / 2 , sGeometry.y() + clearThickness }; } else if (location == Plasma::Types::BottomEdge) { position = {sGeometry.center().x() - size.width() / 2 , sGeometry.y() + sGeometry.height() - clearThickness - size.height() }; } } break; case Plasma::Types::Vertical: { if (location == Plasma::Types::LeftEdge) { position = {sGeometry.x() + clearThickness , sGeometry.center().y() - size.height() / 2 }; } else if (location == Plasma::Types::RightEdge) { position = {sGeometry.x() + sGeometry.width() - clearThickness - size.width() , sGeometry.center().y() - size.height() / 2 }; } } break; default: qWarning() << "no sync geometry, wrong formFactor"; break; } updateEnabledBorders(); m_geometryWhenVisible = QRect(position.x(), position.y(), size.width(), size.height()); setPosition(position); if (m_shellSurface) { m_shellSurface->setPosition(position); } if (m_advanced) { //! consider even the secondary window can be create createSecondaryWindow(); } } void DockConfigView::syncSlideEffect() { if (!m_dockView->containment()) return; auto slideLocation = WindowSystem::Slide::None; switch (m_dockView->containment()->location()) { case Plasma::Types::TopEdge: slideLocation = WindowSystem::Slide::Top; break; case Plasma::Types::RightEdge: slideLocation = WindowSystem::Slide::Right; break; case Plasma::Types::BottomEdge: slideLocation = WindowSystem::Slide::Bottom; break; case Plasma::Types::LeftEdge: slideLocation = WindowSystem::Slide::Left; break; default: qDebug() << staticMetaObject.className() << "wrong location"; break; } m_corona->wm()->slideWindow(*this, slideLocation); } void DockConfigView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); m_corona->wm()->enableBlurBehind(*this); syncGeometry(); syncSlideEffect(); if (m_dockView && m_dockView->containment()) m_dockView->containment()->setUserConfiguring(true); m_screenSyncTimer.start(); QTimer::singleShot(400, this, &DockConfigView::syncGeometry); emit showSignal(); } void DockConfigView::hideEvent(QHideEvent *ev) { if (!m_dockView) { QQuickWindow::hideEvent(ev); return; } if (m_dockView->containment()) m_dockView->containment()->setUserConfiguring(false); QQuickWindow::hideEvent(ev); const auto mode = m_dockView->visibility()->mode(); const auto previousDockWinBehavior = (m_dockView->flags() & Qt::BypassWindowManagerHint) ? false : true; if (mode == Dock::AlwaysVisible || mode == Dock::WindowsGoBelow) { if (!previousDockWinBehavior) { m_dockView->managedLayout()->recreateDock(m_dockView->containment()); } } else if (m_dockView->dockWinBehavior() != previousDockWinBehavior) { m_dockView->managedLayout()->recreateDock(m_dockView->containment()); } deleteLater(); } void DockConfigView::focusOutEvent(QFocusEvent *ev) { Q_UNUSED(ev); const auto *focusWindow = qGuiApp->focusWindow(); if (focusWindow && (focusWindow->flags().testFlag(Qt::Popup) || focusWindow->flags().testFlag(Qt::ToolTip))) return; if (!m_blockFocusLost && (!m_secConfigView || (m_secConfigView && !m_secConfigView->isActive()))) { hideConfigWindow(); } } void DockConfigView::setupWaylandIntegration() { if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_dockView || !m_dockView->containment()) { // already setup return; } if (m_corona) { using namespace KWayland::Client; PlasmaShell *interface = m_corona->waylandDockCoronaInterface(); if (!interface) { return; } Surface *s = Surface::fromWindow(this); if (!s) { return; } qDebug() << "wayland dock window surface was created..."; m_shellSurface = interface->createSurface(s, this); m_shellSurface->setSkipTaskbar(true); syncGeometry(); } } bool DockConfigView::event(QEvent *e) { if (e->type() == QEvent::PlatformSurface) { if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: if (m_shellSurface) { break; } setupWaylandIntegration(); break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; qDebug() << "WAYLAND config window surface was deleted..."; PanelShadows::self()->removeWindow(this); } break; } } } return PlasmaQuick::ConfigView::event(e); } void DockConfigView::immutabilityChanged(Plasma::Types::ImmutabilityType type) { if (type != Plasma::Types::Mutable && isVisible()) hideConfigWindow(); } bool DockConfigView::sticker() const { return m_blockFocusLost; } void DockConfigView::setSticker(bool blockFocusLost) { if (m_blockFocusLost == blockFocusLost) return; m_blockFocusLost = blockFocusLost; } bool DockConfigView::showInlineProperties() const { return m_showInlineProperties; } void DockConfigView::setShowInlineProperties(bool show) { if (m_showInlineProperties == show) { return; } m_showInlineProperties = show; emit showInlinePropertiesChanged(); } void DockConfigView::addPanelSpacer() { if (m_dockView && m_dockView->containment()) { m_dockView->containment()->createApplet(QStringLiteral("org.kde.latte.spacer")); } } void DockConfigView::hideConfigWindow() { if (m_shellSurface) { //!NOTE: Avoid crash in wayland environment with qt5.9 close(); } else { hide(); } } void DockConfigView::updateLaunchersForGroup(int groupInt) { Dock::LaunchersGroup group = (Dock::LaunchersGroup)groupInt; //! when the layout/global launchers list is empty then the current dock launchers are used for them //! as a start point if (m_corona && m_dockView->managedLayout()) { if ((group == Dock::LayoutLaunchers && m_dockView->managedLayout()->launchers().isEmpty()) || (group == Dock::GlobalLaunchers && m_corona->universalSettings()->launchers().isEmpty())) { Plasma::Containment *c = m_dockView->containment(); const auto &applets = c->applets(); for (auto *applet : applets) { KPluginMetaData meta = applet->kPackage().metadata(); if (meta.pluginId() == "org.kde.latte.plasmoid") { if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value()) { const auto &childItems = appletInterface->childItems(); if (childItems.isEmpty()) { continue; } for (QQuickItem *item : childItems) { if (auto *metaObject = item->metaObject()) { // not using QMetaObject::invokeMethod to avoid warnings when calling // this on applets that don't have it or other child items since this // is pretty much trial and error. // Also, "var" arguments are treated as QVariant in QMetaObject int methodIndex = metaObject->indexOfMethod("getLauncherList()"); if (methodIndex == -1) { continue; } QMetaMethod method = metaObject->method(methodIndex); QVariant launchers; if (method.invoke(item, Q_RETURN_ARG(QVariant, launchers))) { if (group == Dock::LayoutLaunchers) { m_dockView->managedLayout()->setLaunchers(launchers.toStringList()); } else if (group == Dock::GlobalLaunchers) { m_corona->universalSettings()->setLaunchers(launchers.toStringList()); } } } } } } } } } } //!BEGIN borders Plasma::FrameSvg::EnabledBorders DockConfigView::enabledBorders() const { return m_enabledBorders; } void DockConfigView::updateEnabledBorders() { if (!this->screen()) { return; } Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; switch (m_dockView->location()) { case Plasma::Types::TopEdge: borders &= m_inReverse ? ~Plasma::FrameSvg::BottomBorder : ~Plasma::FrameSvg::TopBorder; break; case Plasma::Types::LeftEdge: borders &= ~Plasma::FrameSvg::LeftBorder; break; case Plasma::Types::RightEdge: borders &= ~Plasma::FrameSvg::RightBorder; break; case Plasma::Types::BottomEdge: borders &= m_inReverse ? ~Plasma::FrameSvg::TopBorder : ~Plasma::FrameSvg::BottomBorder; break; default: break; } if (m_enabledBorders != borders) { m_enabledBorders = borders; PanelShadows::self()->addWindow(this, m_enabledBorders); emit enabledBordersChanged(); } } //!END borders } // kate: indent-mode cstyle; indent-width 4; replace-tabs on; diff --git a/app/dock/docksecconfigview.cpp b/app/dock/docksecconfigview.cpp index d4dc8c90..a9b5b684 100644 --- a/app/dock/docksecconfigview.cpp +++ b/app/dock/docksecconfigview.cpp @@ -1,387 +1,387 @@ /* * Copyright 2018 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "docksecconfigview.h" #include "dockconfigview.h" #include "dockview.h" #include "panelshadows_p.h" -#include "../abstractwindowinterface.h" #include "../dockcorona.h" +#include "../wm/abstractwindowinterface.h" #include #include #include #include #include #include #include #include #include #include #include namespace Latte { DockSecConfigView::DockSecConfigView(DockView *dockView, QWindow *parent) : QQuickView(nullptr), m_parent(parent), m_dockView(dockView) { m_corona = qobject_cast(m_dockView->containment()->corona()); setupWaylandIntegration(); setResizeMode(QQuickView::SizeViewToRootObject); setScreen(m_dockView->screen()); if (dockView && dockView->containment()) { setIcon(qGuiApp->windowIcon()); } m_screenSyncTimer.setSingleShot(true); m_screenSyncTimer.setInterval(100); connections << connect(&m_screenSyncTimer, &QTimer::timeout, this, [this]() { setScreen(m_dockView->screen()); setFlags(wFlags()); syncGeometry(); syncSlideEffect(); }); connections << connect(dockView->visibility(), &VisibilityManager::modeChanged, this, &DockSecConfigView::syncGeometry); m_thicknessSyncTimer.setSingleShot(true); m_thicknessSyncTimer.setInterval(200); connections << connect(&m_thicknessSyncTimer, &QTimer::timeout, this, [this]() { syncGeometry(); }); connections << connect(dockView, &DockView::normalThicknessChanged, [&]() { m_thicknessSyncTimer.start(); }); } DockSecConfigView::~DockSecConfigView() { qDebug() << "SecDockConfigView deleting ..."; foreach (auto var, connections) { QObject::disconnect(var); } if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; } } void DockSecConfigView::init() { qDebug() << "dock secondary config view : initialization started..."; setDefaultAlphaBuffer(true); setColor(Qt::transparent); PanelShadows::self()->addWindow(this); rootContext()->setContextProperty(QStringLiteral("dock"), m_dockView); rootContext()->setContextProperty(QStringLiteral("dockConfig"), this); rootContext()->setContextProperty(QStringLiteral("plasmoid"), m_dockView->containment()->property("_plasma_graphicObject").value()); KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.setTranslationDomain(QStringLiteral("latte-dock")); kdeclarative.setupBindings(); QByteArray tempFilePath = "lattedocksecondaryconfigurationui"; updateEnabledBorders(); auto source = QUrl::fromLocalFile(m_dockView->containment()->corona()->kPackage().filePath(tempFilePath)); setSource(source); syncGeometry(); syncSlideEffect(); m_parent->requestActivate(); qDebug() << "dock secondary config view : initialization ended..."; } inline Qt::WindowFlags DockSecConfigView::wFlags() const { return (flags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) & ~Qt::WindowDoesNotAcceptFocus; } QRect DockSecConfigView::geometryWhenVisible() const { return m_geometryWhenVisible; } void DockSecConfigView::syncGeometry() { if (!m_dockView->managedLayout() || !m_dockView->containment() || !rootObject()) return; const QSize size(rootObject()->width(), rootObject()->height()); setMaximumSize(size); setMinimumSize(size); resize(size); const auto location = m_dockView->containment()->location(); const auto sGeometry = m_dockView->screenGeometry(); int clearThickness = m_dockView->normalThickness() + m_dockView->fontPixelSize(); int secondaryConfigSpacing = 2 * m_dockView->fontPixelSize(); QPoint position{0, 0}; switch (m_dockView->containment()->formFactor()) { case Plasma::Types::Horizontal: { if (location == Plasma::Types::TopEdge) { int yPos = m_dockView->y() + clearThickness; position = {m_dockView->x() + secondaryConfigSpacing, yPos}; } else if (location == Plasma::Types::BottomEdge) { int yPos; yPos = sGeometry.y() + sGeometry.height() - clearThickness - size.height(); position = {m_dockView->x() + m_dockView->width() - secondaryConfigSpacing - size.width(), yPos}; } } break; case Plasma::Types::Vertical: { if (location == Plasma::Types::LeftEdge) { position = {sGeometry.x() + clearThickness , m_dockView->y() + secondaryConfigSpacing }; } else if (location == Plasma::Types::RightEdge) { position = {sGeometry.x() + sGeometry.width() - clearThickness - size.width() , m_dockView->y() + secondaryConfigSpacing }; } } break; default: qWarning() << "no sync geometry, wrong formFactor"; break; } updateEnabledBorders(); m_geometryWhenVisible = QRect(position.x(), position.y(), size.width(), size.height()); setPosition(position); if (m_shellSurface) { m_shellSurface->setPosition(position); } } void DockSecConfigView::syncSlideEffect() { if (!m_dockView->containment()) return; auto slideLocation = WindowSystem::Slide::None; switch (m_dockView->containment()->location()) { case Plasma::Types::TopEdge: slideLocation = WindowSystem::Slide::Top; break; case Plasma::Types::RightEdge: slideLocation = WindowSystem::Slide::Right; break; case Plasma::Types::BottomEdge: slideLocation = WindowSystem::Slide::Bottom; break; case Plasma::Types::LeftEdge: slideLocation = WindowSystem::Slide::Left; break; default: qDebug() << staticMetaObject.className() << "wrong location"; break; } m_corona->wm()->slideWindow(*this, slideLocation); } void DockSecConfigView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); m_corona->wm()->enableBlurBehind(*this); syncGeometry(); syncSlideEffect(); m_screenSyncTimer.start(); QTimer::singleShot(400, this, &DockSecConfigView::syncGeometry); emit showSignal(); } void DockSecConfigView::focusOutEvent(QFocusEvent *ev) { Q_UNUSED(ev); const auto *focusWindow = qGuiApp->focusWindow(); if (focusWindow && (focusWindow->flags().testFlag(Qt::Popup) || focusWindow->flags().testFlag(Qt::ToolTip))) return; const auto parent = qobject_cast(m_parent); if (parent && !parent->sticker() && !parent->isActive()) { parent->hideConfigWindow(); } } void DockSecConfigView::setupWaylandIntegration() { if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_dockView || !m_dockView->containment()) { // already setup return; } if (m_corona) { using namespace KWayland::Client; PlasmaShell *interface = m_corona->waylandDockCoronaInterface(); if (!interface) { return; } Surface *s = Surface::fromWindow(this); if (!s) { return; } qDebug() << "wayland dock window surface was created..."; m_shellSurface = interface->createSurface(s, this); m_shellSurface->setSkipTaskbar(true); syncGeometry(); } } bool DockSecConfigView::event(QEvent *e) { if (e->type() == QEvent::PlatformSurface) { if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: if (m_shellSurface) { break; } setupWaylandIntegration(); break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; qDebug() << "WAYLAND secondary config window surface was deleted..."; PanelShadows::self()->removeWindow(this); } break; } } } return QQuickView::event(e); } void DockSecConfigView::hideConfigWindow() { if (m_shellSurface) { //!NOTE: Avoid crash in wayland environment with qt5.9 close(); } else { hide(); } } //!BEGIN borders Plasma::FrameSvg::EnabledBorders DockSecConfigView::enabledBorders() const { return m_enabledBorders; } void DockSecConfigView::updateEnabledBorders() { if (!this->screen()) { return; } Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; switch (m_dockView->location()) { case Plasma::Types::TopEdge: borders &= ~Plasma::FrameSvg::TopBorder; break; case Plasma::Types::LeftEdge: borders &= ~Plasma::FrameSvg::LeftBorder; break; case Plasma::Types::RightEdge: borders &= ~Plasma::FrameSvg::RightBorder; break; case Plasma::Types::BottomEdge: borders &= ~Plasma::FrameSvg::BottomBorder; break; default: break; } if (m_enabledBorders != borders) { m_enabledBorders = borders; PanelShadows::self()->addWindow(this, m_enabledBorders); emit enabledBordersChanged(); } } //!END borders } // kate: indent-mode cstyle; indent-width 4; replace-tabs on; diff --git a/app/dock/visibilitymanager.cpp b/app/dock/visibilitymanager.cpp index 8e95233a..c95bcd97 100644 --- a/app/dock/visibilitymanager.cpp +++ b/app/dock/visibilitymanager.cpp @@ -1,1251 +1,1251 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "visibilitymanager.h" #include "visibilitymanager_p.h" #include "dockview.h" #include "positioner.h" #include "screenedgeghostwindow.h" #include "../dockcorona.h" #include "../layoutmanager.h" #include "../screenpool.h" -#include "../windowinfowrap.h" +#include "../wm/windowinfowrap.h" #include "../../liblattedock/extras.h" #include #include #include namespace Latte { //! BEGIN: VisiblityManagerPrivate implementation VisibilityManagerPrivate::VisibilityManagerPrivate(PlasmaQuick::ContainmentView *view, VisibilityManager *q) : QObject(nullptr), q(q), view(view) { dockView = qobject_cast(view); dockCorona = qobject_cast(view->corona()); wm = dockCorona->wm(); if (dockView) { connect(dockView, &DockView::eventTriggered, this, &VisibilityManagerPrivate::viewEventManager); connect(dockView, &DockView::absGeometryChanged, this, &VisibilityManagerPrivate::setDockGeometry); } timerStartUp.setInterval(5000); timerStartUp.setSingleShot(true); timerCheckWindows.setInterval(350); timerCheckWindows.setSingleShot(true); timerShow.setSingleShot(true); timerHide.setSingleShot(true); connect(&timerCheckWindows, &QTimer::timeout, this, &VisibilityManagerPrivate::checkAllWindows); connect(&timerShow, &QTimer::timeout, this, [this, q]() { if (isHidden) { // qDebug() << "must be shown"; emit this->q->mustBeShown(VisibilityManager::QPrivateSignal{}); } }); connect(&timerHide, &QTimer::timeout, this, [this]() { if (!blockHiding && !isHidden && !dragEnter) { // qDebug() << "must be hide"; emit this->q->mustBeHide(VisibilityManager::QPrivateSignal{}); } }); wm->setDockExtraFlags(*view); wm->addDock(view->winId()); restoreConfig(); } VisibilityManagerPrivate::~VisibilityManagerPrivate() { qDebug() << "VisibilityManagerPrivate deleting..."; wm->removeDockStruts(*view); wm->removeDock(view->winId()); if (edgeGhostWindow) { edgeGhostWindow->deleteLater(); } } inline void VisibilityManagerPrivate::setMode(Dock::Visibility mode) { if (this->mode == mode) return; Q_ASSERT_X(mode != Dock::None, q->staticMetaObject.className(), "set visibility to Dock::None"); // clear mode for (auto &c : connections) { disconnect(c); } if (mode != Dock::DodgeAllWindows && !enabledDynamicBackgroundFlag) { windows.clear(); } if (this->mode == Dock::AlwaysVisible) { wm->removeDockStruts(*view); } else { connections[3] = connect(wm, &WindowSystem::currentDesktopChanged , this, [&] { if (raiseOnDesktopChange) raiseDockTemporarily(); }); connections[4] = connect(wm, &WindowSystem::currentActivityChanged , this, [&]() { if (raiseOnActivityChange) raiseDockTemporarily(); else updateHiddenState(); }); } timerShow.stop(); timerHide.stop(); timerCheckWindows.stop(); this->mode = mode; switch (this->mode) { case Dock::AlwaysVisible: { //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::WindowsGoBelow); } if (view->containment() && !dockView->inEditMode() && view->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } connections[0] = connect(view->containment(), &Plasma::Containment::locationChanged , this, [&]() { if (dockView->inEditMode()) wm->removeDockStruts(*view); }); connections[1] = connect(dockView, &DockView::inEditModeChanged , this, [&]() { if (!dockView->inEditMode() && !dockView->positioner()->inLocationChangeAnimation() && view->screen()) wm->setDockStruts(*view, dockGeometry, view->containment()->location()); }); if (dockCorona && dockCorona->layoutManager()->memoryUsage() == Dock::MultipleLayouts) { connections[2] = connect(dockCorona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, [&]() { updateStrutsBasedOnLayoutsAndActivities(); }); connections[3] = connect(dockView, &DockView::activitiesChanged, this, [&]() { updateStrutsBasedOnLayoutsAndActivities(); }); } raiseDock(true); } break; case Dock::AutoHide: { //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::AutoHide); } raiseDock(containsMouse); } break; case Dock::DodgeActive: { //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::AutoHide); } connections[0] = connect(wm, &WindowSystem::activeWindowChanged , this, &VisibilityManagerPrivate::dodgeActive); connections[1] = connect(wm, &WindowSystem::windowChanged , this, &VisibilityManagerPrivate::dodgeActive); dodgeActive(wm->activeWindow()); } break; case Dock::DodgeMaximized: { //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::AutoHide); } connections[0] = connect(wm, &WindowSystem::activeWindowChanged , this, &VisibilityManagerPrivate::dodgeMaximized); connections[1] = connect(wm, &WindowSystem::windowChanged , this, &VisibilityManagerPrivate::dodgeMaximized); dodgeMaximized(wm->activeWindow()); } break; case Dock::DodgeAllWindows: { //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::AutoHide); } for (const auto &wid : wm->windows()) { windows.insert(wid, wm->requestInfo(wid)); } connections[0] = connect(wm, &WindowSystem::windowChanged , this, &VisibilityManagerPrivate::dodgeWindows); connections[1] = connect(wm, &WindowSystem::windowRemoved , this, [&](WindowId wid) { windows.remove(wid); timerCheckWindows.start(); }); connections[2] = connect(wm, &WindowSystem::windowAdded , this, [&](WindowId wid) { windows.insert(wid, wm->requestInfo(wid)); timerCheckWindows.start(); }); timerCheckWindows.start(); } break; case Dock::WindowsGoBelow: //set wayland visibility mode if (dockView->surface()) { dockView->surface()->setPanelBehavior(KWayland::Client::PlasmaShellSurface::PanelBehavior::WindowsGoBelow); } break; default: break; } view->containment()->config().writeEntry("visibility", static_cast(mode)); updateKWinEdgesSupport(); emit q->modeChanged(); } void VisibilityManagerPrivate::updateStrutsBasedOnLayoutsAndActivities() { bool multipleLayoutsAndCurrent = (dockCorona->layoutManager()->memoryUsage() == Dock::MultipleLayouts && dockView->managedLayout() && !dockView->positioner()->inLocationChangeAnimation() && dockView->managedLayout()->name() == dockCorona->layoutManager()->currentLayoutName()); if (dockCorona->layoutManager()->memoryUsage() == Dock::SingleLayout || multipleLayoutsAndCurrent) { wm->setDockStruts(*view, dockGeometry, view->location()); } else { wm->removeDockStruts(*view); } } void VisibilityManagerPrivate::setRaiseOnDesktop(bool enable) { if (enable == raiseOnDesktopChange) return; raiseOnDesktopChange = enable; emit q->raiseOnDesktopChanged(); } void VisibilityManagerPrivate::setRaiseOnActivity(bool enable) { if (enable == raiseOnActivityChange) return; raiseOnActivityChange = enable; emit q->raiseOnActivityChanged(); } inline void VisibilityManagerPrivate::setIsHidden(bool isHidden) { if (this->isHidden == isHidden) return; if (blockHiding && isHidden) { qWarning() << "isHidden property is blocked, ignoring update"; return; } this->isHidden = isHidden; if (q->supportsKWinEdges()) { bool inCurrentLayout = (dockCorona->layoutManager()->memoryUsage() == Dock::SingleLayout || (dockCorona->layoutManager()->memoryUsage() == Dock::MultipleLayouts && dockView->managedLayout() && !dockView->positioner()->inLocationChangeAnimation() && dockView->managedLayout()->name() == dockCorona->layoutManager()->currentLayoutName())); if (inCurrentLayout) { wm->setEdgeStateFor(edgeGhostWindow, isHidden); } else { wm->setEdgeStateFor(edgeGhostWindow, false); } } emit q->isHiddenChanged(); } void VisibilityManagerPrivate::setBlockHiding(bool blockHiding) { if (this->blockHiding == blockHiding) return; this->blockHiding = blockHiding; // qDebug() << "blockHiding:" << blockHiding; if (this->blockHiding) { timerHide.stop(); if (isHidden) { emit q->mustBeShown(VisibilityManager::QPrivateSignal{}); } } else { updateHiddenState(); } emit q->blockHidingChanged(); } inline void VisibilityManagerPrivate::setTimerShow(int msec) { timerShow.setInterval(msec); emit q->timerShowChanged(); } inline void VisibilityManagerPrivate::setTimerHide(int msec) { timerHide.setInterval(msec); emit q->timerHideChanged(); } inline void VisibilityManagerPrivate::raiseDock(bool raise) { if (blockHiding) return; if (raise) { timerHide.stop(); if (!timerShow.isActive()) { timerShow.start(); } } else if (!dragEnter) { timerShow.stop(); if (hideNow) { hideNow = false; emit q->mustBeHide(VisibilityManager::QPrivateSignal{}); } else if (!timerHide.isActive()) { timerHide.start(); } } } void VisibilityManagerPrivate::raiseDockTemporarily() { if (raiseTemporarily) return; raiseTemporarily = true; timerHide.stop(); timerShow.stop(); if (isHidden) emit q->mustBeShown(VisibilityManager::QPrivateSignal{}); QTimer::singleShot(qBound(1800, 2 * timerHide.interval(), 3000), this, [&]() { raiseTemporarily = false; hideNow = true; updateHiddenState(); }); } void VisibilityManagerPrivate::updateHiddenState() { if (dragEnter) return; switch (mode) { case Dock::AutoHide: raiseDock(containsMouse); break; case Dock::DodgeActive: dodgeActive(wm->activeWindow()); break; case Dock::DodgeMaximized: dodgeMaximized(wm->activeWindow()); break; case Dock::DodgeAllWindows: dodgeWindows(wm->activeWindow()); break; default: break; } } inline void VisibilityManagerPrivate::setDockGeometry(const QRect &geometry) { if (!view->containment()) return; this->dockGeometry = geometry; if (mode == Dock::AlwaysVisible && !dockView->inEditMode() && view->screen()) { updateStrutsBasedOnLayoutsAndActivities(); } } void VisibilityManagerPrivate::setWindowOnActivities(QWindow &window, const QStringList &activities) { wm->setWindowOnActivities(window, activities); } void VisibilityManagerPrivate::applyActivitiesToHiddenWindows(const QStringList &activities) { if (edgeGhostWindow) { wm->setWindowOnActivities(*edgeGhostWindow, activities); } } void VisibilityManagerPrivate::dodgeActive(WindowId wid) { if (raiseTemporarily) return; //!don't send false raiseDock signal when containing mouse if (containsMouse) { raiseDock(true); return; } auto winfo = wm->requestInfo(wid); if (!winfo.isValid() || !winfo.isActive()) { winfo = wm->requestInfo(wm->activeWindow()); if (!winfo.isValid()) { //! very rare case that window manager doesnt have any active window at all raiseDock(true); return; } } //! don't send false raiseDock signal when containing mouse, // Johan comment //! I dont know why that wasnt winfo.wid() //active window, but just wid//the window that made the call if (wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) { bool overlaps{intersects(winfo)}; raiseDock(!overlaps); } } void VisibilityManagerPrivate::dodgeMaximized(WindowId wid) { if (raiseTemporarily) return; //!don't send false raiseDock signal when containing mouse if (containsMouse) { raiseDock(true); return; } auto winfo = wm->requestInfo(wid); if (!winfo.isValid() || !winfo.isActive()) { winfo = wm->requestInfo(wm->activeWindow()); if (!winfo.isValid()) { //! very rare case that window manager doesnt have any active window at all raiseDock(true); return; } } auto intersectsMaxVert = [&]() noexcept -> bool { return ((winfo.isMaxVert() || (view->screen() && view->screen()->availableSize().height() <= winfo.geometry().height())) && intersects(winfo)); }; auto intersectsMaxHoriz = [&]() noexcept -> bool { return ((winfo.isMaxHoriz() || (view->screen() && view->screen()->availableSize().width() <= winfo.geometry().width())) && intersects(winfo)); }; //! don't send false raiseDock signal when containing mouse, // Johan comment //! I dont know why that wasnt winfo.wid() //active window, but just wid//the window that made the call if (wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) { bool overlapsMaximized{view->formFactor() == Plasma::Types::Vertical ? intersectsMaxHoriz() : intersectsMaxVert()}; raiseDock(!overlapsMaximized); } } void VisibilityManagerPrivate::dodgeWindows(WindowId wid) { if (raiseTemporarily) return; if (windows.find(wid) == std::end(windows)) return; //!don't send false raiseDock signal when containing mouse if (containsMouse) { raiseDock(true); return; } windows[wid] = wm->requestInfo(wid); auto &winfo = windows[wid]; if (!winfo.isValid() || !wm->isOnCurrentDesktop(wid) || !wm->isOnCurrentActivity(wid)) return; if (intersects(winfo)) raiseDock(false); else timerCheckWindows.start(); } void VisibilityManagerPrivate::checkAllWindows() { if (raiseTemporarily) return; bool raise{true}; bool existsFaultyWindow{false}; for (const auto &winfo : windows) { // if (winfo.geometry() == QRect(0, 0, 0, 0)) { existsFaultyWindow = true; } if (!winfo.isValid() || !wm->isOnCurrentDesktop(winfo.wid()) || !wm->isOnCurrentActivity(winfo.wid())) continue; if (winfo.isFullscreen()) { raise = false; break; } else if (intersects(winfo)) { raise = false; break; } } cleanupFaultyWindows(); raiseDock(raise); } inline bool VisibilityManagerPrivate::intersects(const WindowInfoWrap &winfo) { return (!winfo.isMinimized() && winfo.geometry().intersects(dockGeometry) && !winfo.isShaded()); } inline void VisibilityManagerPrivate::saveConfig() { if (!view->containment()) return; auto config = view->containment()->config(); config.writeEntry("enableKWinEdges", enableKWinEdgesFromUser); config.writeEntry("timerShow", timerShow.interval()); config.writeEntry("timerHide", timerHide.interval()); config.writeEntry("raiseOnDesktopChange", raiseOnDesktopChange); config.writeEntry("raiseOnActivityChange", raiseOnActivityChange); view->containment()->configNeedsSaving(); } inline void VisibilityManagerPrivate::restoreConfig() { if (!view->containment()) return; auto config = view->containment()->config(); timerShow.setInterval(config.readEntry("timerShow", 0)); timerHide.setInterval(config.readEntry("timerHide", 700)); emit q->timerShowChanged(); emit q->timerHideChanged(); enableKWinEdgesFromUser = config.readEntry("enableKWinEdges", true); emit q->enableKWinEdgesChanged(); setRaiseOnDesktop(config.readEntry("raiseOnDesktopChange", false)); setRaiseOnActivity(config.readEntry("raiseOnActivityChange", false)); auto mode = [&]() { return static_cast(view->containment()->config() .readEntry("visibility", static_cast(Dock::DodgeActive))); }; if (mode() == Dock::AlwaysVisible) { setMode(Dock::AlwaysVisible); } else { connect(&timerStartUp, &QTimer::timeout, this, [ &, mode]() { setMode(mode()); }); connect(view->containment(), &Plasma::Containment::userConfiguringChanged , this, [&](bool configuring) { if (configuring && timerStartUp.isActive()) timerStartUp.start(100); }); timerStartUp.start(); } connect(view->containment(), &Plasma::Containment::userConfiguringChanged , this, [&](bool configuring) { if (!configuring) saveConfig(); }); } void VisibilityManagerPrivate::setContainsMouse(bool contains) { if (containsMouse == contains) { return; } containsMouse = contains; emit q->containsMouseChanged(); if (contains && mode != Dock::AlwaysVisible) { raiseDock(true); } } void VisibilityManagerPrivate::viewEventManager(QEvent *ev) { switch (ev->type()) { case QEvent::Enter: setContainsMouse(true); break; case QEvent::Leave: setContainsMouse(false); updateHiddenState(); break; case QEvent::DragEnter: dragEnter = true; if (isHidden) emit q->mustBeShown(VisibilityManager::QPrivateSignal{}); break; case QEvent::DragLeave: case QEvent::Drop: dragEnter = false; updateHiddenState(); break; case QEvent::Show: wm->setDockExtraFlags(*view); break; default: break; } } void VisibilityManagerPrivate::cleanupFaultyWindows() { foreach (auto key, windows.keys()) { auto winfo = windows[key]; //! garbage windows removing if (winfo.geometry() == QRect(0, 0, 0, 0)) { //qDebug() << "Faulty Geometry ::: " << winfo.wid(); windows.remove(key); } } } //! Dynamic Background functions void VisibilityManagerPrivate::setEnabledDynamicBackground(bool active) { if (enabledDynamicBackgroundFlag == active) { return; } enabledDynamicBackgroundFlag = active; if (active) { if (mode != Dock::DodgeAllWindows) { for (const auto &wid : wm->windows()) { windows.insert(wid, wm->requestInfo(wid)); } } connectionsDynBackground[0] = connect(view->corona(), &Plasma::Corona::availableScreenRectChanged, this, &VisibilityManagerPrivate::updateAvailableScreenGeometry); connectionsDynBackground[1] = connect(wm, &WindowSystem::windowChanged, this, [&](WindowId wid) { windows[wid] = wm->requestInfo(wid); updateDynamicBackgroundWindowFlags(); }); connectionsDynBackground[2] = connect(wm, &WindowSystem::windowRemoved, this, [&](WindowId wid) { windows.remove(wid); }); connectionsDynBackground[3] = connect(wm, &WindowSystem::windowAdded, this, [&](WindowId wid) { windows.insert(wid, wm->requestInfo(wid)); updateDynamicBackgroundWindowFlags(); }); connectionsDynBackground[4] = connect(wm, &WindowSystem::activeWindowChanged, this, [&](WindowId wid) { if (windows.contains(lastActiveWindowWid)) { windows[lastActiveWindowWid] = wm->requestInfo(lastActiveWindowWid); } windows[wid] = wm->requestInfo(wid); lastActiveWindowWid = wid; updateDynamicBackgroundWindowFlags(); }); connectionsDynBackground[5] = connect(wm, &WindowSystem::currentDesktopChanged, this, [&] { updateDynamicBackgroundWindowFlags(); }); connectionsDynBackground[6] = connect(wm, &WindowSystem::currentActivityChanged, this, [&] { updateDynamicBackgroundWindowFlags(); }); updateAvailableScreenGeometry(); updateDynamicBackgroundWindowFlags(); } else { // clear mode for (auto &c : connectionsDynBackground) { disconnect(c); } if (mode != Dock::DodgeAllWindows) { windows.clear(); } // ATTENTION: this was creating a crash under wayland environment through the blur effect // setExistsWindowMaximized(false); // setExistsWindowSnapped(false); } emit q->enabledDynamicBackgroundChanged(); } void VisibilityManagerPrivate::setExistsWindowMaximized(bool windowMaximized) { if (windowIsMaximizedFlag == windowMaximized) { return; } windowIsMaximizedFlag = windowMaximized; emit q->existsWindowMaximizedChanged(); } void VisibilityManagerPrivate::setExistsWindowSnapped(bool windowSnapped) { if (windowIsSnappedFlag == windowSnapped) { return; } windowIsSnappedFlag = windowSnapped; emit q->existsWindowSnappedChanged(); } void VisibilityManagerPrivate::setTouchingWindowScheme(SchemeColors *scheme) { if (touchingScheme == scheme) { return; } touchingScheme = scheme; emit q->touchingWindowSchemeChanged(); } void VisibilityManagerPrivate::updateAvailableScreenGeometry() { if (!view || !view->containment()) { return; } int currentScrId = dockView->positioner()->currentScreenId(); QRect tempAvailableScreenGeometry = dockCorona->availableScreenRectWithCriteria(currentScrId, {Dock::AlwaysVisible}, {}); if (tempAvailableScreenGeometry != availableScreenGeometry) { availableScreenGeometry = tempAvailableScreenGeometry; snappedWindowsGeometries.clear(); //! for top dock the snapped geometries would be int halfWidth1 = std::floor(availableScreenGeometry.width() / 2); int halfWidth2 = availableScreenGeometry.width() - halfWidth1; int halfHeight1 = std::floor((availableScreenGeometry.height()) / 2); int halfHeight2 = availableScreenGeometry.height() - halfHeight1; int x1 = availableScreenGeometry.x(); int x2 = availableScreenGeometry.x() + halfWidth1; int y1 = availableScreenGeometry.y(); int y2 = availableScreenGeometry.y() + halfHeight1; QRect snap1; QRect snap2; QRect snap3; QRect snap4; if (view->formFactor() == Plasma::Types::Horizontal) { if (view->location() == Plasma::Types::TopEdge) { snap1 = QRect(x1, y1, halfWidth1, halfHeight1); snap3 = QRect(x2, y1, halfWidth2, halfHeight1); } else if ((view->location() == Plasma::Types::BottomEdge)) { snap1 = QRect(x1, y2, halfWidth1, halfHeight2); snap3 = QRect(x2, y2, halfWidth2, halfHeight2); } snap2 = QRect(x1, y1, halfWidth1, availableScreenGeometry.height()); snap4 = QRect(x2, y1, halfWidth2, availableScreenGeometry.height()); } else if (view->formFactor() == Plasma::Types::Vertical) { QRect snap5; if (view->location() == Plasma::Types::LeftEdge) { snap1 = QRect(x1, y1, halfWidth1, halfHeight1); snap3 = QRect(x1, y2, halfWidth1, halfHeight2); snap5 = QRect(x1, y1, halfWidth1, availableScreenGeometry.height()); } else if ((view->location() == Plasma::Types::RightEdge)) { snap1 = QRect(x2, y1, halfWidth2, halfHeight1); snap3 = QRect(x2, y2, halfWidth2, halfHeight2); snap5 = QRect(x2, y1, halfWidth2, availableScreenGeometry.height()); } snap2 = QRect(x1, y1, availableScreenGeometry.width(), halfHeight1); snap4 = QRect(x1, y2, availableScreenGeometry.width(), halfHeight2); snappedWindowsGeometries.append(snap5); } snappedWindowsGeometries.append(snap1); snappedWindowsGeometries.append(snap2); snappedWindowsGeometries.append(snap3); snappedWindowsGeometries.append(snap4); updateDynamicBackgroundWindowFlags(); } } bool VisibilityManagerPrivate::isMaximizedInCurrentScreen(const WindowInfoWrap &winfo) { //! updated implementation to identify the screen that the maximized window is present //! in order to avoid: https://bugs.kde.org/show_bug.cgi?id=397700 if (winfo.isValid() && !winfo.isMinimized() && wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) { if (winfo.isMaximized() && availableScreenGeometry.contains(winfo.geometry().center())) { return true; } } return false; } bool VisibilityManagerPrivate::isTouchingPanelEdge(const WindowInfoWrap &winfo) { if (winfo.isValid() && !winfo.isMinimized() && wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) { bool touchingPanelEdge{false}; QRect screenGeometry = dockView->screenGeometry(); bool inCurrentScreen{screenGeometry.contains(winfo.geometry().topLeft()) || screenGeometry.contains(winfo.geometry().bottomRight())}; if (inCurrentScreen) { if (view->location() == Plasma::Types::TopEdge) { touchingPanelEdge = (winfo.geometry().y() == availableScreenGeometry.y()); } else if (view->location() == Plasma::Types::BottomEdge) { touchingPanelEdge = (winfo.geometry().bottom() == availableScreenGeometry.bottom()); } else if (view->location() == Plasma::Types::LeftEdge) { touchingPanelEdge = (winfo.geometry().x() == availableScreenGeometry.x()); } else if (view->location() == Plasma::Types::RightEdge) { touchingPanelEdge = (winfo.geometry().right() == availableScreenGeometry.right()); } } return touchingPanelEdge; } return false; } void VisibilityManagerPrivate::updateDynamicBackgroundWindowFlags() { bool foundSnap{false}; bool foundMaximized{false}; //! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0), //! maybe a garbage collector here is a good idea!!! bool existsFaultyWindow{false}; WindowId maxWinId; WindowId snapWinId; for (const auto &winfo : windows) { if (isMaximizedInCurrentScreen(winfo)) { foundMaximized = true; maxWinId = winfo.wid(); } if (winfo.isActive() && isTouchingPanelEdge(winfo)) { foundSnap = true; snapWinId = winfo.wid(); } if (!existsFaultyWindow && winfo.geometry() == QRect(0, 0, 0, 0)) { existsFaultyWindow = true; } //qDebug() << "window geometry ::: " << winfo.geometry(); } //! active windows that are touching the panel edge should have a higher priority //! this is why are identified first if (!foundSnap) { for (const auto &winfo : windows) { if ((winfo.isKeepAbove() && isTouchingPanelEdge(winfo)) || (!winfo.isActive() && snappedWindowsGeometries.contains(winfo.geometry()))) { foundSnap = true; snapWinId = winfo.wid(); break; } } } if (existsFaultyWindow) { cleanupFaultyWindows(); } /*if (!foundMaximized && !foundSnap) { qDebug() << "SCREEN GEOMETRY : " << availableScreenGeometry; qDebug() << "SNAPS ::: " << snappedWindowsGeometries; } qDebug() << " FOUND ::: " << foundMaximized << foundSnap;*/ setExistsWindowMaximized(foundMaximized); setExistsWindowSnapped(foundSnap); //! update color scheme for touching window if (foundSnap) { //! first the snap one because that would mean it is active setTouchingWindowScheme(wm->schemeForWindow(snapWinId)); } else if (foundMaximized) { setTouchingWindowScheme(wm->schemeForWindow(maxWinId)); } else { setTouchingWindowScheme(nullptr); } } //! KWin Edges Support functions void VisibilityManagerPrivate::setEnableKWinEdges(bool enable) { if (enableKWinEdgesFromUser == enable) { return; } enableKWinEdgesFromUser = enable; emit q->enableKWinEdgesChanged(); updateKWinEdgesSupport(); } void VisibilityManagerPrivate::updateKWinEdgesSupport() { if (mode == Dock::AutoHide || mode == Dock::DodgeActive || mode == Dock::DodgeAllWindows || mode == Dock::DodgeMaximized) { if (enableKWinEdgesFromUser) { createEdgeGhostWindow(); } else if (!enableKWinEdgesFromUser) { deleteEdgeGhostWindow(); } } else if (mode == Dock::AlwaysVisible || mode == Dock::WindowsGoBelow) { deleteEdgeGhostWindow(); } } void VisibilityManagerPrivate::createEdgeGhostWindow() { if (!edgeGhostWindow) { edgeGhostWindow = new ScreenEdgeGhostWindow(dockView); wm->setDockExtraFlags(*edgeGhostWindow); connect(edgeGhostWindow, &ScreenEdgeGhostWindow::containsMouseChanged, this, [ = ](bool contains) { if (contains) { emit this->q->mustBeShown(VisibilityManager::QPrivateSignal{}); } }); connectionsKWinEdges[0] = connect(wm, &WindowSystem::currentActivityChanged, this, [&]() { bool inCurrentLayout = (dockCorona->layoutManager()->memoryUsage() == Dock::SingleLayout || (dockCorona->layoutManager()->memoryUsage() == Dock::MultipleLayouts && dockView->managedLayout() && !dockView->positioner()->inLocationChangeAnimation() && dockView->managedLayout()->name() == dockCorona->layoutManager()->currentLayoutName())); if (edgeGhostWindow) { if (inCurrentLayout) { wm->setEdgeStateFor(edgeGhostWindow, isHidden); } else { wm->setEdgeStateFor(edgeGhostWindow, false); } } }); emit q->supportsKWinEdgesChanged(); } } void VisibilityManagerPrivate::deleteEdgeGhostWindow() { if (edgeGhostWindow) { edgeGhostWindow->deleteLater(); edgeGhostWindow = nullptr; for (auto &c : connectionsKWinEdges) { disconnect(c); } emit q->supportsKWinEdgesChanged(); } } //! Window Functions void VisibilityManagerPrivate::requestToggleMaximizeForActiveWindow() { WindowInfoWrap actInfo = wm->requestInfoActive(); //active window can be toggled only when it is in the same screen if (actInfo.isValid() && !actInfo.geometry().isNull() && dockView->screenGeometry().contains(actInfo.geometry().center())) { wm->requestToggleMaximized(actInfo.wid()); } } void VisibilityManagerPrivate::requestMoveActiveWindow(int localX, int localY) { WindowInfoWrap actInfo = wm->requestInfoActive(); //active window can be dragged only when it is in the same screen if (actInfo.isValid() && !actInfo.geometry().isNull() && dockView->screenGeometry().contains(actInfo.geometry().center())) { QPoint globalPoint{dockView->x() + localX, dockView->y() + localY}; wm->requestMoveWindow(actInfo.wid(), globalPoint); } } bool VisibilityManagerPrivate::activeWindowCanBeDragged() { WindowInfoWrap actInfo = wm->requestInfoActive(); //active window can be dragged only when it is in the same screen if (actInfo.isValid() && !actInfo.geometry().isNull() && dockView->screenGeometry().contains(actInfo.geometry().center())) { return wm->windowCanBeDragged(actInfo.wid()); } return false; } //! END: VisibilityManagerPrivate implementation //! BEGIN: VisibilityManager implementation VisibilityManager::VisibilityManager(PlasmaQuick::ContainmentView *view) : d(new VisibilityManagerPrivate(view, this)) { DockView *dockView = qobject_cast(view); if (dockView) { connect(this, &VisibilityManager::modeChanged, dockView->corona(), &Plasma::Corona::availableScreenRectChanged); } } VisibilityManager::~VisibilityManager() { qDebug() << "VisibilityManager deleting..."; delete d; } Dock::Visibility VisibilityManager::mode() const { return d->mode; } void VisibilityManager::setMode(Dock::Visibility mode) { d->setMode(mode); } void VisibilityManager::setWindowOnActivities(QWindow &window, const QStringList &activities) { d->setWindowOnActivities(window, activities); } void VisibilityManager::applyActivitiesToHiddenWindows(const QStringList &activities) { d->applyActivitiesToHiddenWindows(activities); } bool VisibilityManager::raiseOnDesktop() const { return d->raiseOnDesktopChange; } void VisibilityManager::setRaiseOnDesktop(bool enable) { d->setRaiseOnDesktop(enable); } bool VisibilityManager::raiseOnActivity() const { return d->raiseOnActivityChange; } void VisibilityManager::setRaiseOnActivity(bool enable) { d->setRaiseOnActivity(enable); } bool VisibilityManager::isHidden() const { return d->isHidden; } void VisibilityManager::setIsHidden(bool isHidden) { d->setIsHidden(isHidden); } bool VisibilityManager::blockHiding() const { return d->blockHiding; } void VisibilityManager::setBlockHiding(bool blockHiding) { d->setBlockHiding(blockHiding); } bool VisibilityManager::containsMouse() const { return d->containsMouse; } int VisibilityManager::timerShow() const { return d->timerShow.interval(); } void VisibilityManager::setTimerShow(int msec) { d->setTimerShow(msec); } int VisibilityManager::timerHide() const { return d->timerHide.interval(); } void VisibilityManager::setTimerHide(int msec) { d->setTimerHide(msec); } //! Dynamic Background functions bool VisibilityManager::enabledDynamicBackground() const { return d->enabledDynamicBackgroundFlag; } void VisibilityManager::setEnabledDynamicBackground(bool active) { d->setEnabledDynamicBackground(active); } bool VisibilityManager::existsWindowMaximized() const { return d->windowIsMaximizedFlag; } bool VisibilityManager::existsWindowSnapped() const { return d->windowIsSnappedFlag; } SchemeColors *VisibilityManager::touchingWindowScheme() const { return d->touchingScheme; } //! KWin Edges Support functions bool VisibilityManager::enableKWinEdges() const { return d->enableKWinEdgesFromUser; } void VisibilityManager::setEnableKWinEdges(bool enable) { d->setEnableKWinEdges(enable); } bool VisibilityManager::supportsKWinEdges() const { return (d->edgeGhostWindow != nullptr); } //! Window Functions void VisibilityManager::requestToggleMaximizeForActiveWindow() { d->requestToggleMaximizeForActiveWindow(); } void VisibilityManager::requestMoveActiveWindow(int localX, int localY) { d->requestMoveActiveWindow(localX, localY); } bool VisibilityManager::activeWindowCanBeDragged() { return d->activeWindowCanBeDragged(); } //! END: VisibilityManager implementation } diff --git a/app/dock/visibilitymanager.h b/app/dock/visibilitymanager.h index 0911df3d..3b46900c 100644 --- a/app/dock/visibilitymanager.h +++ b/app/dock/visibilitymanager.h @@ -1,142 +1,142 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VISIBILITYMANAGER_H #define VISIBILITYMANAGER_H #include "../plasmaquick/containmentview.h" #include "../schemecolors.h" -#include "../windowinfowrap.h" +#include "../wm/windowinfowrap.h" #include "../../liblattedock/dock.h" #include #include #include namespace Latte { class VisibilityManagerPrivate; class VisibilityManager : public QObject { Q_OBJECT Q_PROPERTY(Latte::Dock::Visibility mode READ mode WRITE setMode NOTIFY modeChanged) Q_PROPERTY(bool raiseOnDesktop READ raiseOnDesktop WRITE setRaiseOnDesktop NOTIFY raiseOnDesktopChanged) Q_PROPERTY(bool raiseOnActivity READ raiseOnActivity WRITE setRaiseOnActivity NOTIFY raiseOnActivityChanged) Q_PROPERTY(bool isHidden READ isHidden WRITE setIsHidden NOTIFY isHiddenChanged) Q_PROPERTY(bool blockHiding READ blockHiding WRITE setBlockHiding NOTIFY blockHidingChanged) Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged) //! Dynamic Background Feature (needed options) Q_PROPERTY(bool enabledDynamicBackground READ enabledDynamicBackground WRITE setEnabledDynamicBackground NOTIFY enabledDynamicBackgroundChanged) Q_PROPERTY(bool existsWindowMaximized READ existsWindowMaximized NOTIFY existsWindowMaximizedChanged) Q_PROPERTY(bool existsWindowSnapped READ existsWindowSnapped NOTIFY existsWindowSnappedChanged) Q_PROPERTY(SchemeColors *touchingWindowScheme READ touchingWindowScheme NOTIFY touchingWindowSchemeChanged) //! KWin Edges Support Options Q_PROPERTY(bool enableKWinEdges READ enableKWinEdges WRITE setEnableKWinEdges NOTIFY enableKWinEdgesChanged) Q_PROPERTY(bool supportsKWinEdges READ supportsKWinEdges NOTIFY supportsKWinEdgesChanged) Q_PROPERTY(int timerShow READ timerShow WRITE setTimerShow NOTIFY timerShowChanged) Q_PROPERTY(int timerHide READ timerHide WRITE setTimerHide NOTIFY timerHideChanged) public: explicit VisibilityManager(PlasmaQuick::ContainmentView *view); virtual ~VisibilityManager(); Latte::Dock::Visibility mode() const; void setMode(Latte::Dock::Visibility mode); void setWindowOnActivities(QWindow &window, const QStringList &activities); void applyActivitiesToHiddenWindows(const QStringList &activities); bool raiseOnDesktop() const; void setRaiseOnDesktop(bool enable); bool raiseOnActivity() const; void setRaiseOnActivity(bool enable); bool isHidden() const; void setIsHidden(bool isHidden); bool blockHiding() const; void setBlockHiding(bool blockHiding); bool containsMouse() const; int timerShow() const; void setTimerShow(int msec); int timerHide() const; void setTimerHide(int msec); //! Dynamic Background functions bool enabledDynamicBackground() const; void setEnabledDynamicBackground(bool active); bool existsWindowMaximized() const; bool existsWindowSnapped() const; SchemeColors *touchingWindowScheme() const; //! KWin Edges Support functions bool enableKWinEdges() const; void setEnableKWinEdges(bool enable); bool supportsKWinEdges() const; public slots: Q_INVOKABLE void requestToggleMaximizeForActiveWindow(); Q_INVOKABLE void requestMoveActiveWindow(int localX, int localY); Q_INVOKABLE bool activeWindowCanBeDragged(); signals: void mustBeShown(QPrivateSignal); void mustBeHide(QPrivateSignal); void modeChanged(); void raiseOnDesktopChanged(); void raiseOnActivityChanged(); void isHiddenChanged(); void blockHidingChanged(); void containsMouseChanged(); void timerShowChanged(); void timerHideChanged(); void touchingWindowSchemeChanged(); //! Dynamic Background signals (from options) void enabledDynamicBackgroundChanged(); void existsWindowMaximizedChanged(); void existsWindowSnappedChanged(); //! KWin Edges Support signals void enableKWinEdgesChanged(); void supportsKWinEdgesChanged(); private: VisibilityManagerPrivate *const d; friend class VisibilityManagerPrivate; }; } #endif // VISIBILITYMANAGER_H diff --git a/app/dock/visibilitymanager_p.h b/app/dock/visibilitymanager_p.h index e09ca162..89171d7a 100644 --- a/app/dock/visibilitymanager_p.h +++ b/app/dock/visibilitymanager_p.h @@ -1,138 +1,138 @@ #ifndef VISIBILITYMANAGERPRIVATE_H #define VISIBILITYMANAGERPRIVATE_H -#include "../abstractwindowinterface.h" #include "../schemecolors.h" -#include "../windowinfowrap.h" +#include "../wm/abstractwindowinterface.h" +#include "../wm/windowinfowrap.h" #include "../../liblattedock/dock.h" #include #include #include #include #include #include #include #include namespace Latte { class DockCorona; class DockView; class VisibilityManager; class ScreenEdgeGhostWindow; /*! * \brief The Latte::VisibilityManagerPrivate is a class d-pointer */ class VisibilityManagerPrivate : public QObject { Q_GADGET public: VisibilityManagerPrivate(PlasmaQuick::ContainmentView *view, VisibilityManager *q); ~VisibilityManagerPrivate(); void setMode(Dock::Visibility mode); void setRaiseOnDesktop(bool enable); void setRaiseOnActivity(bool enable); void setContainsMouse(bool contains); void setIsHidden(bool isHidden); void setBlockHiding(bool blockHiding); void setTimerShow(int msec); void setTimerHide(int msec); void raiseDock(bool raise); void raiseDockTemporarily(); void updateHiddenState(); //! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0), //! this is a garbage collector to collect such windows in order to not break the windows array validity. void cleanupFaultyWindows(); //! Dynamic Background Feature void setEnabledDynamicBackground(bool active); void setExistsWindowMaximized(bool windowMaximized); void setExistsWindowSnapped(bool windowSnapped); void setTouchingWindowScheme(SchemeColors *scheme); void updateAvailableScreenGeometry(); void updateDynamicBackgroundWindowFlags(); //! KWin Edges Support functions void createEdgeGhostWindow(); void deleteEdgeGhostWindow(); void setEnableKWinEdges(bool enable); void updateKWinEdgesSupport(); void setDockGeometry(const QRect &rect); void setWindowOnActivities(QWindow &window, const QStringList &activities); void applyActivitiesToHiddenWindows(const QStringList &activities); void windowAdded(WindowId id); void dodgeActive(WindowId id); void dodgeMaximized(WindowId id); void dodgeWindows(WindowId id); void checkAllWindows(); bool intersects(const WindowInfoWrap &winfo); bool isMaximizedInCurrentScreen(const WindowInfoWrap &winfo); bool isTouchingPanelEdge(const WindowInfoWrap &winfo); void updateStrutsBasedOnLayoutsAndActivities(); void requestToggleMaximizeForActiveWindow(); void requestMoveActiveWindow(int localX, int localY); bool activeWindowCanBeDragged(); void saveConfig(); void restoreConfig(); void viewEventManager(QEvent *ev); VisibilityManager *q; PlasmaQuick::ContainmentView *view; AbstractWindowInterface *wm; Dock::Visibility mode{Dock::None}; std::array connections; QMap windows; QTimer timerShow; QTimer timerHide; QTimer timerCheckWindows; QTimer timerStartUp; QRect dockGeometry; bool isHidden{false}; bool dragEnter{false}; bool blockHiding{false}; bool containsMouse{false}; bool raiseTemporarily{false}; bool raiseOnDesktopChange{false}; bool raiseOnActivityChange{false}; bool hideNow{false}; //! Dynamic Background flags and needed information bool enabledDynamicBackgroundFlag{false}; bool windowIsSnappedFlag{false}; bool windowIsMaximizedFlag{false}; QRect availableScreenGeometry; QList snappedWindowsGeometries; std::array connectionsDynBackground; WindowId lastActiveWindowWid; SchemeColors *touchingScheme{nullptr}; //! KWin Edges bool enableKWinEdgesFromUser{true}; std::array connectionsKWinEdges; ScreenEdgeGhostWindow *edgeGhostWindow{nullptr}; DockCorona *dockCorona{nullptr}; DockView *dockView{nullptr}; }; } #endif // VISIBILITYMANAGERPRIVATE_H diff --git a/app/dockcorona.cpp b/app/dockcorona.cpp index 56a981be..c8bfcc10 100644 --- a/app/dockcorona.cpp +++ b/app/dockcorona.cpp @@ -1,956 +1,956 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dockcorona.h" -#include "abstractwindowinterface.h" #include "alternativeshelper.h" #include "globalshortcuts.h" #include "importer.h" #include "launcherssignals.h" #include "layoutmanager.h" #include "plasmathemeextended.h" #include "screenpool.h" -#include "waylandinterface.h" -#include "xwindowinterface.h" #include "dock/dockview.h" #include "packageplugins/shell/dockpackage.h" #include "settings/universalsettings.h" +#include "wm/abstractwindowinterface.h" +#include "wm/waylandinterface.h" +#include "wm/xwindowinterface.h" //dbus adaptor #include "lattedockadaptor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Latte { DockCorona::DockCorona(bool defaultLayoutOnStartup, QString layoutNameOnStartUp, int userSetMemoryUsage, QObject *parent) : Plasma::Corona(parent), m_defaultLayoutOnStartup(defaultLayoutOnStartup), m_userSetMemoryUsage(userSetMemoryUsage), m_layoutNameOnStartUp(layoutNameOnStartUp), m_activityConsumer(new KActivities::Consumer(this)), m_screenPool(new ScreenPool(KSharedConfig::openConfig(), this)), m_globalShortcuts(new GlobalShortcuts(this)), m_universalSettings(new UniversalSettings(KSharedConfig::openConfig(), this)), m_themeExtended(new PlasmaThemeExtended(KSharedConfig::openConfig(), this)), m_layoutManager(new LayoutManager(this)) { //! create the window manager if (KWindowSystem::isPlatformWayland()) { m_wm = new WaylandInterface(this); } else { m_wm = new XWindowInterface(this); } setupWaylandIntegration(); KPackage::Package package(new DockPackage(this)); m_screenPool->load(); if (!package.isValid()) { qWarning() << staticMetaObject.className() << "the package" << package.metadata().rawData() << "is invalid!"; return; } else { qDebug() << staticMetaObject.className() << "the package" << package.metadata().rawData() << "is valid!"; } setKPackage(package); //! universal settings / extendedtheme must be loaded after the package has been set m_universalSettings->load(); m_themeExtended->load(); qmlRegisterTypes(); if (m_activityConsumer && (m_activityConsumer->serviceStatus() == KActivities::Consumer::Running)) { load(); } connect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &DockCorona::load); m_docksScreenSyncTimer.setSingleShot(true); m_docksScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); connect(&m_docksScreenSyncTimer, &QTimer::timeout, this, &DockCorona::syncDockViewsToScreens); connect(m_universalSettings, &UniversalSettings::screenTrackerIntervalChanged, this, [this]() { m_docksScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); }); //! Dbus adaptor initialization new LatteDockAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerObject(QStringLiteral("/Latte"), this); } DockCorona::~DockCorona() { //! BEGIN: Give the time to slide-out docks when closing m_layoutManager->hideAllDocks(); //! Don't delay the destruction under wayland in any case //! because it creates a crash with kwin effects //! https://bugs.kde.org/show_bug.cgi?id=392890 if (!KWindowSystem::isPlatformWayland()) { QTimer::singleShot(400, [this]() { m_quitTimedEnded = true; }); while (!m_quitTimedEnded) { QGuiApplication::processEvents(QEventLoop::AllEvents, 50); } } //! END: slide-out docks when closing m_docksScreenSyncTimer.stop(); if (m_layoutManager->memoryUsage() == Dock::SingleLayout) { cleanConfig(); } qDebug() << "Latte Corona - unload: containments ..."; m_layoutManager->unload(); m_wm->deleteLater(); m_globalShortcuts->deleteLater(); m_layoutManager->deleteLater(); m_screenPool->deleteLater(); m_universalSettings->deleteLater(); m_themeExtended->deleteLater(); disconnect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &DockCorona::load); delete m_activityConsumer; qDebug() << "Latte Corona - deleted..."; } void DockCorona::load() { if (m_activityConsumer && (m_activityConsumer->serviceStatus() == KActivities::Consumer::Running) && m_activitiesStarting) { disconnect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &DockCorona::load); m_layoutManager->load(); m_activitiesStarting = false; connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &DockCorona::primaryOutputChanged, Qt::UniqueConnection); connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &DockCorona::screenCountChanged); connect(m_screenPool, &ScreenPool::primaryPoolChanged, this, &DockCorona::screenCountChanged); QString assignedLayout = m_layoutManager->shouldSwitchToLayout(m_activityConsumer->currentActivity()); QString loadLayoutName = ""; if (!m_defaultLayoutOnStartup && m_layoutNameOnStartUp.isEmpty()) { if (!assignedLayout.isEmpty() && assignedLayout != m_universalSettings->currentLayoutName()) { loadLayoutName = assignedLayout; } else { loadLayoutName = m_universalSettings->currentLayoutName(); } if (!m_layoutManager->layoutExists(loadLayoutName)) { loadLayoutName = m_layoutManager->defaultLayoutName(); m_layoutManager->importDefaultLayout(false); } } else if (m_defaultLayoutOnStartup) { loadLayoutName = m_layoutManager->importer()->uniqueLayoutName(m_layoutManager->defaultLayoutName()); m_layoutManager->importDefaultLayout(true); } else { loadLayoutName = m_layoutNameOnStartUp; } if (m_userSetMemoryUsage != -1 && !KWindowSystem::isPlatformWayland()) { Dock::LayoutsMemoryUsage usage = static_cast(m_userSetMemoryUsage); m_universalSettings->setLayoutsMemoryUsage(usage); } if (KWindowSystem::isPlatformWayland()) { m_universalSettings->setLayoutsMemoryUsage(Dock::SingleLayout); } m_layoutManager->loadLayoutOnStartup(loadLayoutName); //! load screens signals such screenGeometryChanged in order to support //! plasmoid.screenGeometry properly for (QScreen *screen : qGuiApp->screens()) { addOutput(screen); } connect(qGuiApp, &QGuiApplication::screenAdded, this, &DockCorona::addOutput, Qt::UniqueConnection); } } void DockCorona::unload() { qDebug() << "unload: removing containments..."; while (!containments().isEmpty()) { //deleting a containment will remove it from the list due to QObject::destroyed connect in Corona //this form doesn't crash, while qDeleteAll(containments()) does delete containments().first(); } } void DockCorona::setupWaylandIntegration() { if (!KWindowSystem::isPlatformWayland()) { return; } using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication(this); if (!connection) { return; } Registry *registry{new Registry(this)}; registry->create(connection); connect(registry, &Registry::plasmaShellAnnounced, this , [this, registry](quint32 name, quint32 version) { m_waylandDockCorona = registry->createPlasmaShell(name, version, this); }); QObject::connect(registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, [this, registry](quint32 name, quint32 version) { KWayland::Client::PlasmaWindowManagement *pwm = registry->createPlasmaWindowManagement(name, version, this); WaylandInterface *wI = qobject_cast(m_wm); if (wI) { wI->initWindowManagement(pwm); } }); registry->setup(); connection->roundtrip(); } KWayland::Client::PlasmaShell *DockCorona::waylandDockCoronaInterface() const { return m_waylandDockCorona; } void DockCorona::cleanConfig() { auto containmentsEntries = config()->group("Containments"); bool changed = false; foreach (auto cId, containmentsEntries.groupList()) { if (!containmentExists(cId.toUInt())) { //cleanup obsolete containments containmentsEntries.group(cId).deleteGroup(); changed = true; qDebug() << "obsolete containment configuration deleted:" << cId; } else { //cleanup obsolete applets of running containments auto appletsEntries = containmentsEntries.group(cId).group("Applets"); foreach (auto appletId, appletsEntries.groupList()) { if (!appletExists(cId.toUInt(), appletId.toUInt())) { appletsEntries.group(appletId).deleteGroup(); changed = true; qDebug() << "obsolete applet configuration deleted:" << appletId; } } } } if (changed) { config()->sync(); qDebug() << "configuration file cleaned..."; } } bool DockCorona::containmentExists(uint id) const { foreach (auto containment, containments()) { if (id == containment->id()) { return true; } } return false; } bool DockCorona::appletExists(uint containmentId, uint appletId) const { Plasma::Containment *containment = nullptr; foreach (auto cont, containments()) { if (containmentId == cont->id()) { containment = cont; break; } } if (!containment) { return false; } foreach (auto applet, containment->applets()) { if (applet->id() == appletId) { return true; } } return false; } KActivities::Consumer *DockCorona::activitiesConsumer() const { return m_activityConsumer; } ScreenPool *DockCorona::screenPool() const { return m_screenPool; } UniversalSettings *DockCorona::universalSettings() const { return m_universalSettings; } LayoutManager *DockCorona::layoutManager() const { return m_layoutManager; } AbstractWindowInterface *DockCorona::wm() const { return m_wm; } PlasmaThemeExtended *DockCorona::themeExtended() const { return m_themeExtended; } int DockCorona::numScreens() const { return qGuiApp->screens().count(); } QRect DockCorona::screenGeometry(int id) const { const auto screens = qGuiApp->screens(); const QScreen *screen{qGuiApp->primaryScreen()}; QString screenName; if (m_screenPool->knownIds().contains(id)) screenName = m_screenPool->connector(id); foreach (auto scr, screens) { if (scr->name() == screenName) { screen = scr; break; } } return screen->geometry(); } QRegion DockCorona::availableScreenRegion(int id) const { return availableScreenRegionWithCriteria(id); } QRegion DockCorona::availableScreenRegionWithCriteria(int id, QString forLayout) const { const auto screens = qGuiApp->screens(); const QScreen *screen{qGuiApp->primaryScreen()}; QString screenName; if (m_screenPool->knownIds().contains(id)) screenName = m_screenPool->connector(id); foreach (auto scr, screens) { if (scr->name() == screenName) { screen = scr; break; } } if (!screen) return QRegion(); QHash *views; if (forLayout.isEmpty()) { views = m_layoutManager->currentDockViews(); } else { views = m_layoutManager->layoutDockViews(forLayout); } QRegion available(screen->geometry()); if (views) { for (const auto *view : *views) { if (view && view->containment() && view->screen() == screen && view->visibility() && (view->visibility()->mode() != Latte::Dock::AutoHide)) { int realThickness = view->normalThickness() - view->effects()->innerShadow(); // Usually availableScreenRect is used by the desktop, // but Latte don't have desktop, then here just // need calculate available space for top and bottom location, // because the left and right are those who dodge others docks switch (view->location()) { case Plasma::Types::TopEdge: if (view->behaveAsPlasmaPanel()) { available -= view->geometry(); } else { QRect realGeometry; int realWidth = view->maxLength() * view->width(); switch (view->alignment()) { case Latte::Dock::Left: realGeometry = QRect(view->x(), view->y(), realWidth, realThickness); break; case Latte::Dock::Center: case Latte::Dock::Justify: realGeometry = QRect(qMax(view->geometry().x(), view->geometry().center().x() - realWidth / 2), view->y(), realWidth, realThickness); break; case Latte::Dock::Right: realGeometry = QRect(view->geometry().right() - realWidth + 1, view->y(), realWidth, realThickness); break; } available -= realGeometry; } break; case Plasma::Types::BottomEdge: if (view->behaveAsPlasmaPanel()) { available -= view->geometry(); } else { QRect realGeometry; int realWidth = view->maxLength() * view->width(); int realY = view->geometry().bottom() - realThickness + 1; switch (view->alignment()) { case Latte::Dock::Left: realGeometry = QRect(view->x(), realY, realWidth, realThickness); break; case Latte::Dock::Center: case Latte::Dock::Justify: realGeometry = QRect(qMax(view->geometry().x(), view->geometry().center().x() - realWidth / 2), realY, realWidth, realThickness); break; case Latte::Dock::Right: realGeometry = QRect(view->geometry().right() - realWidth + 1, realY, realWidth, realThickness); break; } available -= realGeometry; } break; default: //! bypass clang warnings break; } } } } /*qDebug() << "::::: FREE AREAS :::::"; for (int i = 0; i < available.rectCount(); ++i) { qDebug() << available.rects().at(i); } qDebug() << "::::: END OF FREE AREAS :::::";*/ return available; } QRect DockCorona::availableScreenRect(int id) const { return availableScreenRectWithCriteria(id); } QRect DockCorona::availableScreenRectWithCriteria(int id, QList modes, QList edges) const { const auto screens = qGuiApp->screens(); const QScreen *screen{qGuiApp->primaryScreen()}; if (m_screenPool->knownIds().contains(id)) { QString scrName = m_screenPool->connector(id); foreach (auto scr, screens) { if (scr->name() == scrName) { screen = scr; break; } } } if (!screen) return {}; bool allModes = modes.isEmpty(); bool allEdges = edges.isEmpty(); auto available = screen->geometry(); QHash *views = m_layoutManager->currentDockViews(); if (views) { for (const auto *view : *views) { if (view && view->containment() && view->screen() == screen && ((allEdges || edges.contains(view->location())) && (allModes || (view->visibility() && modes.contains(view->visibility()->mode()))))) { auto dockRect = view->absGeometry(); // Usually availableScreenRect is used by the desktop, // but Latte don't have desktop, then here just // need calculate available space for top and bottom location, // because the left and right are those who dodge others docks switch (view->location()) { case Plasma::Types::TopEdge: available.setTop(dockRect.bottom() + 1); break; case Plasma::Types::BottomEdge: available.setBottom(dockRect.top() - 1); break; case Plasma::Types::LeftEdge: available.setLeft(dockRect.right() + 1); break; case Plasma::Types::RightEdge: available.setRight(dockRect.left() - 1); break; default: //! bypass clang warnings break; } } } } return available; } void DockCorona::addOutput(QScreen *screen) { Q_ASSERT(screen); int id = m_screenPool->id(screen->name()); if (id == -1) { int newId = m_screenPool->firstAvailableId(); m_screenPool->insertScreenMapping(newId, screen->name()); } connect(screen, &QScreen::geometryChanged, this, [ = ]() { const int id = m_screenPool->id(screen->name()); if (id >= 0) { emit screenGeometryChanged(id); emit availableScreenRegionChanged(); emit availableScreenRectChanged(); } }); emit availableScreenRectChanged(); emit screenAdded(m_screenPool->id(screen->name())); } void DockCorona::primaryOutputChanged() { m_docksScreenSyncTimer.start(); } void DockCorona::screenRemoved(QScreen *screen) { Q_ASSERT(screen); } void DockCorona::screenCountChanged() { m_docksScreenSyncTimer.start(); } //! the central functions that updates loading/unloading dockviews //! concerning screen changed (for multi-screen setups mainly) void DockCorona::syncDockViewsToScreens() { m_layoutManager->syncDockViewsToScreens(); } int DockCorona::primaryScreenId() const { return m_screenPool->id(qGuiApp->primaryScreen()->name()); } void DockCorona::closeApplication() { //! this code must be called asynchronously because it is called //! also from qml (Settings window). QTimer::singleShot(5, [this]() { m_layoutManager->hideLatteSettingsDialog(); m_layoutManager->hideAllDocks(); }); //! give the time for the docks to hide themselves QTimer::singleShot(500, [this]() { qGuiApp->quit(); }); } void DockCorona::aboutApplication() { if (aboutDialog) { aboutDialog->hide(); aboutDialog->deleteLater(); } aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData()); connect(aboutDialog.data(), &QDialog::finished, aboutDialog.data(), &QObject::deleteLater); m_wm->skipTaskBar(*aboutDialog); m_wm->setKeepAbove(*aboutDialog, true); aboutDialog->show(); } int DockCorona::screenForContainment(const Plasma::Containment *containment) const { //FIXME: indexOf is not a proper way to support multi-screen // as for environment to environment the indexes change // also there is the following issue triggered // from dockView adaptToScreen() // // in a multi-screen environment that // primary screen is not set to 0 it was // created an endless showing loop at // startup (catch-up race) between // screen:0 and primaryScreen //case in which this containment is child of an applet, hello systray :) if (Plasma::Applet *parentApplet = qobject_cast(containment->parent())) { if (Plasma::Containment *cont = parentApplet->containment()) { return screenForContainment(cont); } else { return -1; } } QHash *views = m_layoutManager->currentDockViews(); //if the panel views already exist, base upon them DockView *view = views ? views->value(containment) : nullptr; if (view && view->screen()) { return m_screenPool->id(view->screen()->name()); } //Failed? fallback on lastScreen() //lastScreen() is the correct screen for panels //It is also correct for desktops *that have the correct activity()* //a containment with lastScreen() == 0 but another activity, //won't be associated to a screen // qDebug() << "ShellCorona screenForContainment: " << containment << " Last screen is " << containment->lastScreen(); for (auto screen : qGuiApp->screens()) { // containment->lastScreen() == m_screenPool->id(screen->name()) to check if the lastScreen refers to a screen that exists/it's known if (containment->lastScreen() == m_screenPool->id(screen->name()) && (containment->activity() == m_activityConsumer->currentActivity() || containment->containmentType() == Plasma::Types::PanelContainment || containment->containmentType() == Plasma::Types::CustomPanelContainment)) { return containment->lastScreen(); } } return -1; } void DockCorona::showAlternativesForApplet(Plasma::Applet *applet) { const QString alternativesQML = kPackage().filePath("appletalternativesui"); if (alternativesQML.isEmpty()) { return; } QHash *views = m_layoutManager->currentDockViews(); DockView *dockView = (*views)[applet->containment()]; KDeclarative::QmlObject *qmlObj{nullptr}; if (dockView) { dockView->setAlternativesIsShown(true); qmlObj = new KDeclarative::QmlObject(dockView); } else { qmlObj = new KDeclarative::QmlObject(this); } qmlObj->setInitializationDelayed(true); qmlObj->setSource(QUrl::fromLocalFile(alternativesQML)); AlternativesHelper *helper = new AlternativesHelper(applet, qmlObj); qmlObj->rootContext()->setContextProperty(QStringLiteral("alternativesHelper"), helper); m_alternativesObjects << qmlObj; qmlObj->completeInitialization(); //! Alternative dialog signals connect(helper, &QObject::destroyed, this, [dockView]() { dockView->setAlternativesIsShown(false); }); connect(qmlObj->rootObject(), SIGNAL(visibleChanged(bool)), this, SLOT(alternativesVisibilityChanged(bool))); connect(applet, &Plasma::Applet::destroyedChanged, this, [this, qmlObj](bool destroyed) { if (!destroyed) { return; } QMutableListIterator it(m_alternativesObjects); while (it.hasNext()) { KDeclarative::QmlObject *obj = it.next(); if (obj == qmlObj) { it.remove(); obj->deleteLater(); } } }); } void DockCorona::alternativesVisibilityChanged(bool visible) { if (visible) { return; } QObject *root = sender(); QMutableListIterator it(m_alternativesObjects); while (it.hasNext()) { KDeclarative::QmlObject *obj = it.next(); if (obj->rootObject() == root) { it.remove(); obj->deleteLater(); } } } void DockCorona::loadDefaultLayout() { qDebug() << "loading default layout"; //! Settting mutable for create a containment setImmutability(Plasma::Types::Mutable); QVariantList args; auto defaultContainment = createContainmentDelayed("org.kde.latte.containment", args); defaultContainment->setContainmentType(Plasma::Types::PanelContainment); defaultContainment->init(); if (!defaultContainment || !defaultContainment->kPackage().isValid()) { qWarning() << "the requested containment plugin can not be located or loaded"; return; } auto config = defaultContainment->config(); defaultContainment->restore(config); using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; Layout *currentLayout = m_layoutManager->activeLayout(m_layoutManager->currentLayoutName()); if (currentLayout) { edges = currentLayout->freeEdges(defaultContainment->screen()); } if ((edges.count() > 0)) { defaultContainment->setLocation(edges.at(0)); } else { defaultContainment->setLocation(Plasma::Types::BottomEdge); } if (m_layoutManager->memoryUsage() == Dock::MultipleLayouts) { config.writeEntry("layoutId", m_layoutManager->currentLayoutName()); } defaultContainment->updateConstraints(Plasma::Types::StartupCompletedConstraint); defaultContainment->save(config); requestConfigSync(); defaultContainment->flushPendingConstraintsEvents(); emit containmentAdded(defaultContainment); emit containmentCreated(defaultContainment); //m_layoutManager->addDock(defaultContainment); defaultContainment->createApplet(QStringLiteral("org.kde.latte.plasmoid")); defaultContainment->createApplet(QStringLiteral("org.kde.plasma.analogclock")); } QStringList DockCorona::containmentsIds() { QStringList ids; foreach (auto containment, containments()) { ids << QString::number(containment->id()); } return ids; } QStringList DockCorona::appletsIds() { QStringList ids; foreach (auto containment, containments()) { auto applets = containment->config().group("Applets"); ids << applets.groupList(); } return ids; } //! Activate launcher menu through dbus interface void DockCorona::activateLauncherMenu() { m_globalShortcuts->activateLauncherMenu(); } void DockCorona::windowColorScheme(QString windowIdAndScheme) { int firstSlash = windowIdAndScheme.indexOf("-"); QString windowIdStr = windowIdAndScheme.mid(0, firstSlash); QString schemeStr = windowIdAndScheme.mid(firstSlash + 1); m_wm->setColorSchemeForWindow(windowIdStr, schemeStr); } //! update badge for specific dock item void DockCorona::updateDockItemBadge(QString identifier, QString value) { m_globalShortcuts->updateDockItemBadge(identifier, value); } void DockCorona::switchToLayout(QString layout) { m_layoutManager->switchToLayout(layout); } void DockCorona::showSettingsWindow(int page) { Dock::LatteConfigPage p = Dock::LayoutPage; if (page >= Dock::LayoutPage && page <= Dock::PreferencesPage) { p = static_cast(page); } m_layoutManager->showLatteSettingsDialog(p); } QStringList DockCorona::contextMenuData() { QStringList data; data << QString::number((int)m_layoutManager->memoryUsage()); data << m_layoutManager->currentLayoutName(); foreach (auto layoutName, m_layoutManager->menuLayouts()) { if (m_layoutManager->activeLayout(layoutName)) { data << QString("1," + layoutName); } else { data << QString("0," + layoutName); } } return data; } inline void DockCorona::qmlRegisterTypes() const { qmlRegisterType(); } } diff --git a/app/infoview.cpp b/app/infoview.cpp index 6409a71e..0ee8d9ae 100644 --- a/app/infoview.cpp +++ b/app/infoview.cpp @@ -1,197 +1,197 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "infoview.h" -#include "abstractwindowinterface.h" #include "dock/panelshadows_p.h" +#include "wm/abstractwindowinterface.h" #include #include #include #include #include #include #include #include #include #include namespace Latte { InfoView::InfoView(DockCorona *corona, QString message, QScreen *screen, QWindow *parent) : QQuickView(parent), m_corona(corona), m_message(message), m_screen(screen) { setupWaylandIntegration(); setResizeMode(QQuickView::SizeViewToRootObject); setColor(QColor(Qt::transparent)); setDefaultAlphaBuffer(true); setIcon(qGuiApp->windowIcon()); setScreen(screen); setFlags(wFlags()); init(); } InfoView::~InfoView() { PanelShadows::self()->removeWindow(this); qDebug() << "InfoView deleting ..."; if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; } } void InfoView::init() { rootContext()->setContextProperty(QStringLiteral("infoWindow"), this); KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.setTranslationDomain(QStringLiteral("latte-dock")); kdeclarative.setupBindings(); auto source = QUrl::fromLocalFile(m_corona->kPackage().filePath("infoviewui")); setSource(source); rootObject()->setProperty("message", m_message); syncGeometry(); } Plasma::FrameSvg::EnabledBorders InfoView::enabledBorders() const { return m_borders; } inline Qt::WindowFlags InfoView::wFlags() const { return (flags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) & ~Qt::WindowDoesNotAcceptFocus; } void InfoView::syncGeometry() { const QSize size(rootObject()->width(), rootObject()->height()); const auto sGeometry = screen()->geometry(); setMaximumSize(size); setMinimumSize(size); resize(size); QPoint position{sGeometry.center().x() - size.width() / 2, sGeometry.center().y() - size.height() / 2 }; setPosition(position); if (m_shellSurface) { m_shellSurface->setPosition(position); } } void InfoView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); m_corona->wm()->enableBlurBehind(*this); syncGeometry(); QTimer::singleShot(400, this, &InfoView::syncGeometry); PanelShadows::self()->addWindow(this); PanelShadows::self()->setEnabledBorders(this, m_borders); } void InfoView::setupWaylandIntegration() { if (m_shellSurface) { // already setup return; } if (m_corona) { using namespace KWayland::Client; PlasmaShell *interface = m_corona->waylandDockCoronaInterface(); if (!interface) { return; } Surface *s = Surface::fromWindow(this); if (!s) { return; } qDebug() << "wayland dock window surface was created..."; m_shellSurface = interface->createSurface(s, this); } } bool InfoView::event(QEvent *e) { if (e->type() == QEvent::PlatformSurface) { if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: if (m_shellSurface) { break; } setupWaylandIntegration(); break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; } PanelShadows::self()->removeWindow(this); break; } } } return QQuickWindow::event(e); } void InfoView::setOnActivities(QStringList activities) { KWindowSystem::setOnActivities(winId(), activities); } } // kate: indent-mode cstyle; indent-width 4; replace-tabs on; diff --git a/app/abstractwindowinterface.cpp b/app/wm/abstractwindowinterface.cpp similarity index 100% rename from app/abstractwindowinterface.cpp rename to app/wm/abstractwindowinterface.cpp diff --git a/app/abstractwindowinterface.h b/app/wm/abstractwindowinterface.h similarity index 100% rename from app/abstractwindowinterface.h rename to app/wm/abstractwindowinterface.h diff --git a/app/waylandinterface.cpp b/app/wm/waylandinterface.cpp similarity index 100% rename from app/waylandinterface.cpp rename to app/wm/waylandinterface.cpp diff --git a/app/waylandinterface.h b/app/wm/waylandinterface.h similarity index 100% rename from app/waylandinterface.h rename to app/wm/waylandinterface.h diff --git a/app/windowinfowrap.cpp b/app/wm/windowinfowrap.cpp similarity index 100% rename from app/windowinfowrap.cpp rename to app/wm/windowinfowrap.cpp diff --git a/app/windowinfowrap.h b/app/wm/windowinfowrap.h similarity index 100% rename from app/windowinfowrap.h rename to app/wm/windowinfowrap.h diff --git a/app/xwindowinterface.cpp b/app/wm/xwindowinterface.cpp similarity index 100% rename from app/xwindowinterface.cpp rename to app/wm/xwindowinterface.cpp diff --git a/app/xwindowinterface.h b/app/wm/xwindowinterface.h similarity index 100% rename from app/xwindowinterface.h rename to app/wm/xwindowinterface.h