From cb88d134f463c8e2ade8c4f809228615b10ac6ff Mon Sep 17 00:00:00 2001 From: Michail Vourlakos Date: Thu, 1 Mar 2018 23:53:28 +0200 Subject: [PATCH] fix #889,dont crash on applcation exit --the wayland interface couldnt orchestrate correctly with the corona and the application exit. The whole architecture changed and the window manager now is provided by corona and corona is also responsible to keep only one instance of it and close on exit. --- app/abstractwindowinterface.cpp | 16 ------ app/abstractwindowinterface.h | 4 -- app/dock/dockconfigview.cpp | 8 ++- app/dock/dockconfigview.h | 2 + app/dock/docksecconfigview.cpp | 8 ++- app/dock/docksecconfigview.h | 2 + app/dock/dockview.cpp | 6 -- app/dock/visibilitymanager.cpp | 3 +- app/dockcorona.cpp | 32 ++++++++++- app/dockcorona.h | 3 + app/infoview.cpp | 4 +- app/waylandinterface.cpp | 98 ++++++++++++++------------------- app/waylandinterface.h | 12 ++-- 13 files changed, 100 insertions(+), 98 deletions(-) diff --git a/app/abstractwindowinterface.cpp b/app/abstractwindowinterface.cpp index 0aa59a2ea..d0cdf34a8 100644 --- a/app/abstractwindowinterface.cpp +++ b/app/abstractwindowinterface.cpp @@ -51,21 +51,5 @@ void AbstractWindowInterface::removeDock(WindowId wid) m_docks.erase(it); } -AbstractWindowInterface &AbstractWindowInterface::self() -{ - if (m_wm) - return *m_wm; - - if (KWindowSystem::isPlatformWayland()) { - //! TODO: WaylandWindowInterface - m_wm = std::make_unique(); - } else { /* if(KWindowSystem::isPlatformX11) */ - m_wm = std::make_unique(); - } - - return *m_wm; -} - } -std::unique_ptr Latte::AbstractWindowInterface::m_wm; diff --git a/app/abstractwindowinterface.h b/app/abstractwindowinterface.h index a3c2c1b00..908591f1f 100644 --- a/app/abstractwindowinterface.h +++ b/app/abstractwindowinterface.h @@ -80,8 +80,6 @@ public: void addDock(WindowId wid); void removeDock(WindowId wid); - static AbstractWindowInterface &self(); - signals: void activeWindowChanged(WindowId wid); void windowChanged(WindowId winfo); @@ -94,8 +92,6 @@ protected: std::list m_windows; std::list m_docks; QPointer m_activities; - - static std::unique_ptr m_wm; }; // namespace alias diff --git a/app/dock/dockconfigview.cpp b/app/dock/dockconfigview.cpp index 714e47e80..dd6102e81 100644 --- a/app/dock/dockconfigview.cpp +++ b/app/dock/dockconfigview.cpp @@ -52,6 +52,8 @@ DockConfigView::DockConfigView(Plasma::Containment *containment, DockView *dockV : PlasmaQuick::ConfigView(containment, parent), m_dockView(dockView) { + m_corona = qobject_cast(m_dockView->containment()->corona()); + setupWaylandIntegration(); setScreen(m_dockView->screen()); @@ -281,17 +283,17 @@ void DockConfigView::syncSlideEffect() break; } - WindowSystem::self().slideWindow(*this, slideLocation); + m_corona->wm()->slideWindow(*this, slideLocation); } void DockConfigView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); - WindowSystem::self().setDockExtraFlags(*this); + m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); - WindowSystem::self().enableBlurBehind(*this); + m_corona->wm()->enableBlurBehind(*this); syncGeometry(); syncSlideEffect(); diff --git a/app/dock/dockconfigview.h b/app/dock/dockconfigview.h index 09a755cfc..8776da315 100644 --- a/app/dock/dockconfigview.h +++ b/app/dock/dockconfigview.h @@ -48,6 +48,7 @@ class PlasmaShellSurface; namespace Latte { +class DockCorona; class DockView; class DockConfigView : public PlasmaQuick::ConfigView { @@ -122,6 +123,7 @@ private: Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; + DockCorona *m_corona{nullptr}; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; }; diff --git a/app/dock/docksecconfigview.cpp b/app/dock/docksecconfigview.cpp index df468f85a..ed5c5324c 100644 --- a/app/dock/docksecconfigview.cpp +++ b/app/dock/docksecconfigview.cpp @@ -48,6 +48,8 @@ DockSecConfigView::DockSecConfigView(DockView *dockView, QWindow *parent) m_parent(parent), m_dockView(dockView) { + m_corona = qobject_cast(m_dockView->containment()->corona()); + setupWaylandIntegration(); setResizeMode(QQuickView::SizeViewToRootObject); @@ -225,17 +227,17 @@ void DockSecConfigView::syncSlideEffect() break; } - WindowSystem::self().slideWindow(*this, slideLocation); + m_corona->wm()->slideWindow(*this, slideLocation); } void DockSecConfigView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); - WindowSystem::self().setDockExtraFlags(*this); + m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); - WindowSystem::self().enableBlurBehind(*this); + m_corona->wm()->enableBlurBehind(*this); syncGeometry(); syncSlideEffect(); diff --git a/app/dock/docksecconfigview.h b/app/dock/docksecconfigview.h index ee0e7cec6..1000183ee 100644 --- a/app/dock/docksecconfigview.h +++ b/app/dock/docksecconfigview.h @@ -45,6 +45,7 @@ class PlasmaShellSurface; namespace Latte { +class DockCorona; class DockView; class DockSecConfigView : public QQuickView { @@ -90,6 +91,7 @@ private: Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; + DockCorona *m_corona{nullptr}; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; }; diff --git a/app/dock/dockview.cpp b/app/dock/dockview.cpp index 00bebc51e..8b4d9675a 100644 --- a/app/dock/dockview.cpp +++ b/app/dock/dockview.cpp @@ -167,12 +167,6 @@ DockView::~DockView() if (m_visibility) delete m_visibility; - - if (m_shellSurface) { - m_shellSurface->release(); - delete m_shellSurface; - m_shellSurface = nullptr; - } } void DockView::init() diff --git a/app/dock/visibilitymanager.cpp b/app/dock/visibilitymanager.cpp index 5b06c0974..ff337bcdc 100644 --- a/app/dock/visibilitymanager.cpp +++ b/app/dock/visibilitymanager.cpp @@ -33,10 +33,11 @@ namespace Latte { //! BEGIN: VisiblityManagerPrivate implementation VisibilityManagerPrivate::VisibilityManagerPrivate(PlasmaQuick::ContainmentView *view, VisibilityManager *q) - : QObject(nullptr), q(q), view(view), wm(&WindowSystem::self()) + : 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); diff --git a/app/dockcorona.cpp b/app/dockcorona.cpp index 218b3060a..2a511df2c 100644 --- a/app/dockcorona.cpp +++ b/app/dockcorona.cpp @@ -28,6 +28,8 @@ #include "layoutmanager.h" #include "screenpool.h" #include "universalsettings.h" +#include "waylandinterface.h" +#include "xwindowinterface.h" #include "dock/dockview.h" #include "packageplugins/shell/dockpackage.h" @@ -64,6 +66,7 @@ #include #include #include +#include namespace Latte { @@ -78,6 +81,14 @@ DockCorona::DockCorona(bool defaultLayoutOnStartup, QString layoutNameOnStartUp, m_universalSettings(new UniversalSettings(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)); @@ -139,6 +150,7 @@ DockCorona::~DockCorona() m_layoutManager->unload(); + m_wm->deleteLater(); m_globalShortcuts->deleteLater(); m_layoutManager->deleteLater(); m_screenPool->deleteLater(); @@ -228,6 +240,17 @@ void DockCorona::setupWaylandIntegration() 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(); } @@ -323,6 +346,11 @@ LayoutManager *DockCorona::layoutManager() const return m_layoutManager; } +AbstractWindowInterface *DockCorona::wm() const +{ + return m_wm; +} + int DockCorona::numScreens() const { return qGuiApp->screens().count(); @@ -613,8 +641,8 @@ void DockCorona::aboutApplication() aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData()); connect(aboutDialog.data(), &QDialog::finished, aboutDialog.data(), &QObject::deleteLater); - WindowSystem::self().skipTaskBar(*aboutDialog); - WindowSystem::self().setKeepAbove(*aboutDialog, true); + m_wm->skipTaskBar(*aboutDialog); + m_wm->setKeepAbove(*aboutDialog, true); aboutDialog->show(); } diff --git a/app/dockcorona.h b/app/dockcorona.h index c6f6f6fc8..db53c3659 100644 --- a/app/dockcorona.h +++ b/app/dockcorona.h @@ -57,6 +57,7 @@ class PlasmaShell; } namespace Latte { +class AbstractWindowInterface; class ScreenPool; class GlobalShortcuts; class UniversalSettings; @@ -97,6 +98,7 @@ public: void closeApplication(); + AbstractWindowInterface *wm() const; KActivities::Consumer *activitiesConsumer() const; ScreenPool *screenPool() const; UniversalSettings *universalSettings() const; @@ -162,6 +164,7 @@ private: KActivities::Consumer *m_activityConsumer; QPointer aboutDialog; + AbstractWindowInterface *m_wm{nullptr}; ScreenPool *m_screenPool{nullptr}; GlobalShortcuts *m_globalShortcuts{nullptr}; UniversalSettings *m_universalSettings{nullptr}; diff --git a/app/infoview.cpp b/app/infoview.cpp index 8c67f6393..6409a71e0 100644 --- a/app/infoview.cpp +++ b/app/infoview.cpp @@ -119,10 +119,10 @@ void InfoView::showEvent(QShowEvent *ev) { QQuickWindow::showEvent(ev); - WindowSystem::self().setDockExtraFlags(*this); + m_corona->wm()->setDockExtraFlags(*this); setFlags(wFlags()); - WindowSystem::self().enableBlurBehind(*this); + m_corona->wm()->enableBlurBehind(*this); syncGeometry(); diff --git a/app/waylandinterface.cpp b/app/waylandinterface.cpp index 93fe2cdd8..f7256a092 100644 --- a/app/waylandinterface.cpp +++ b/app/waylandinterface.cpp @@ -19,6 +19,7 @@ */ #include "waylandinterface.h" +#include "dockcorona.h" #include "../liblattedock/extras.h" #include @@ -72,7 +73,7 @@ public: if (!s) return; - m_shellSurface = m_waylandInterface->m_plasmaShell->createSurface(s, this); + m_shellSurface = m_waylandInterface->waylandDockCoronaInterface()->createSurface(s, this); qDebug() << "wayland ghost window surface was created..."; m_shellSurface->setSkipTaskbar(true); @@ -88,58 +89,13 @@ public: WaylandInterface::WaylandInterface(QObject *parent) : AbstractWindowInterface(parent) { - m_activities = new KActivities::Consumer(this); - - m_connection = ConnectionThread::fromApplication(this); - - if (!m_connection) { - qWarning() << "Failed getting Wayland connection from QPA"; - return; - } - - m_registry = new Registry(this); - m_registry->create(m_connection); - - connect(qApp, &QCoreApplication::aboutToQuit, this, [&]() { - if (m_wm) - m_wm->release(); - - if (m_plasmaShell) - m_plasmaShell->release(); - - m_registry->release(); - }); - - m_registry->setup(); - m_connection->roundtrip(); + m_corona = qobject_cast(parent); - const auto wmInterface = m_registry->interface(Registry::Interface::PlasmaWindowManagement); - - if (wmInterface.name == 0) { - qWarning() << "This compositor does not support the Plasma Window Management interface"; - return; - } - - m_wm = m_registry->createPlasmaWindowManagement(wmInterface.name, wmInterface.version, this); - connect(m_wm, &PlasmaWindowManagement::windowCreated, this, &WaylandInterface::windowCreatedProxy); - connect(m_wm, &PlasmaWindowManagement::activeWindowChanged, this, [&]() noexcept { - auto w = m_wm->activeWindow(); - emit activeWindowChanged(w ? w->internalId() : 0); - }, Qt::QueuedConnection); - - - const auto shellInterface = m_registry->interface(Registry::Interface::PlasmaShell); - - if (shellInterface.name == 0) { - qWarning() << "Plasma Shell interface can't be created"; - return; - } + m_activities = new KActivities::Consumer(this); - m_plasmaShell = m_registry->createPlasmaShell(shellInterface.name, shellInterface.version, this); connect(m_activities.data(), &KActivities::Consumer::currentActivityChanged , this, &WaylandInterface::currentActivityChanged); - } WaylandInterface::~WaylandInterface() @@ -150,6 +106,22 @@ void WaylandInterface::init() { } +void WaylandInterface::initWindowManagement(KWayland::Client::PlasmaWindowManagement *windowManagement) +{ + m_windowManagement = windowManagement; + + connect(m_windowManagement, &PlasmaWindowManagement::windowCreated, this, &WaylandInterface::windowCreatedProxy); + connect(m_windowManagement, &PlasmaWindowManagement::activeWindowChanged, this, [&]() noexcept { + auto w = m_windowManagement->activeWindow(); + emit activeWindowChanged(w ? w->internalId() : 0); + }, Qt::QueuedConnection); +} + +KWayland::Client::PlasmaShell *WaylandInterface::waylandDockCoronaInterface() const +{ + return m_corona->waylandDockCoronaInterface(); +} + void WaylandInterface::setDockExtraFlags(QWindow &view) { Q_UNUSED(view) @@ -192,7 +164,11 @@ void WaylandInterface::removeDockStruts(QWindow &view) const WindowId WaylandInterface::activeWindow() const { - auto wid = m_wm->activeWindow(); + if (!m_windowManagement) { + return 0; + } + + auto wid = m_windowManagement->activeWindow(); return wid ? wid->internalId() : 0; } @@ -251,7 +227,11 @@ void WaylandInterface::enableBlurBehind(QWindow &view) const WindowInfoWrap WaylandInterface::requestInfoActive() const { - auto w = m_wm->activeWindow(); + if (!m_windowManagement) { + return {}; + } + + auto w = m_windowManagement->activeWindow(); if (!w) return {}; @@ -282,33 +262,37 @@ WindowInfoWrap WaylandInterface::requestInfoActive() const bool WaylandInterface::isOnCurrentDesktop(WindowId wid) const { - auto it = std::find_if(m_wm->windows().constBegin(), m_wm->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { + if (!m_windowManagement) { + return false; + } + + auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { return w->isValid() && w->internalId() == wid; }); - //qDebug() << "desktop:" << (it != m_wm->windows().constEnd() ? (*it)->virtualDesktop() : -1) << KWindowSystem::currentDesktop(); + //qDebug() << "desktop:" << (it != m_windowManagement->windows().constEnd() ? (*it)->virtualDesktop() : -1) << KWindowSystem::currentDesktop(); //return true; - return it != m_wm->windows().constEnd() && ((*it)->virtualDesktop() == KWindowSystem::currentDesktop() || (*it)->isOnAllDesktops()); + return it != m_windowManagement->windows().constEnd() && ((*it)->virtualDesktop() == KWindowSystem::currentDesktop() || (*it)->isOnAllDesktops()); } bool WaylandInterface::isOnCurrentActivity(WindowId wid) const { - auto it = std::find_if(m_wm->windows().constBegin(), m_wm->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { + auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { return w->isValid() && w->internalId() == wid; }); //TODO: Not yet implemented - return it != m_wm->windows().constEnd() && true; + return it != m_windowManagement->windows().constEnd() && true; } WindowInfoWrap WaylandInterface::requestInfo(WindowId wid) const { - auto it = std::find_if(m_wm->windows().constBegin(), m_wm->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { + auto it = std::find_if(m_windowManagement->windows().constBegin(), m_windowManagement->windows().constEnd(), [&wid](PlasmaWindow * w) noexcept { return w->isValid() && w->internalId() == wid; }); - if (it == m_wm->windows().constEnd()) + if (it == m_windowManagement->windows().constEnd()) return {}; WindowInfoWrap winfoWrap; diff --git a/app/waylandinterface.h b/app/waylandinterface.h index 116b86a5a..228d9601a 100644 --- a/app/waylandinterface.h +++ b/app/waylandinterface.h @@ -39,6 +39,8 @@ namespace Latte { +class DockCorona; + namespace Private { /** * @brief this class is use for create the struts inside wayland @@ -72,20 +74,22 @@ public: void slideWindow(QWindow &view, Slide location) const override; void enableBlurBehind(QWindow &view) const override; + void initWindowManagement(KWayland::Client::PlasmaWindowManagement *windowManagement); + private: void init(); inline bool isValidWindow(const KWayland::Client::PlasmaWindow *w) const; void windowCreatedProxy(KWayland::Client::PlasmaWindow *w); + KWayland::Client::PlasmaShell *waylandDockCoronaInterface() const; QSignalMapper *mapper{nullptr}; friend class Private::GhostWindow; mutable QMap m_ghostWindows; - KWayland::Client::Registry *m_registry{nullptr}; - KWayland::Client::ConnectionThread *m_connection{nullptr}; - KWayland::Client::PlasmaWindowManagement *m_wm{nullptr}; - KWayland::Client::PlasmaShell *m_plasmaShell{nullptr}; + KWayland::Client::PlasmaWindowManagement *m_windowManagement{nullptr}; + + DockCorona *m_corona{nullptr}; };