diff --git a/src/windowsystem/waylandintegration.cpp b/src/windowsystem/waylandintegration.cpp index 780ed2c..95c2464 100644 --- a/src/windowsystem/waylandintegration.cpp +++ b/src/windowsystem/waylandintegration.cpp @@ -1,205 +1,235 @@ /* * Copyright 2014 Martin Gräßlin * Copyright 2015 Marco Martin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "waylandintegration.h" #include "logging.h" #include #include #include #include +#include #include #include #include #include #include #include +#include + class WaylandIntegrationSingleton { public: WaylandIntegration self; }; Q_GLOBAL_STATIC(WaylandIntegrationSingleton, privateWaylandIntegrationSelf) WaylandIntegration::WaylandIntegration() : QObject() { setupKWaylandIntegration(); } WaylandIntegration::~WaylandIntegration() {} void WaylandIntegration::setupKWaylandIntegration() { using namespace KWayland::Client; m_waylandConnection = ConnectionThread::fromApplication(this); if (!m_waylandConnection) { qCWarning(KWAYLAND_KWS) << "Failed getting Wayland connection from QPA"; return; } m_registry = new Registry(this); m_registry->create(m_waylandConnection); m_waylandCompositor = Compositor::fromApplication(this); + //when the Qt QPA closes it deletes the wl_display + //closing wl_display deletes the wl_registry + //when we destroy the kwayland wrapper we double delete + //as we're a singleton we're not deleted till after qApp + //we want to release our wayland parts first + connect(qApp, &QCoreApplication::aboutToQuit, this, [=]() { + if (m_waylandBlurManager) { + m_waylandBlurManager->release(); + } + if (m_waylandContrastManager) { + m_waylandContrastManager->release(); + } + if (m_waylandSlideManager) { + m_waylandSlideManager->release(); + } + if (m_waylandCompositor) { + m_waylandCompositor->release(); + } + if (m_wm) { + m_wm->release(); + } + if (m_waylandPlasmaShell) { + m_waylandPlasmaShell->release(); + } + m_registry->release(); + }); + m_registry->setup(); m_waylandConnection->roundtrip(); } WaylandIntegration *WaylandIntegration::self() { return &privateWaylandIntegrationSelf()->self; } KWayland::Client::ConnectionThread *WaylandIntegration::waylandConnection() const { return m_waylandConnection; } KWayland::Client::BlurManager *WaylandIntegration::waylandBlurManager() { if (!m_waylandBlurManager) { const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Blur); if (wmInterface.name == 0) { return nullptr; } m_waylandBlurManager = m_registry->createBlurManager(wmInterface.name, wmInterface.version, this); connect(m_waylandBlurManager, &KWayland::Client::BlurManager::removed, this, [this] () { m_waylandBlurManager->deleteLater(); m_waylandBlurManager = nullptr; } ); } return m_waylandBlurManager; } KWayland::Client::ContrastManager *WaylandIntegration::waylandContrastManager() { if (!m_waylandContrastManager) { const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Contrast); if (wmInterface.name == 0) { return nullptr; } m_waylandContrastManager = m_registry->createContrastManager(wmInterface.name, wmInterface.version, this); connect(m_waylandContrastManager, &KWayland::Client::ContrastManager::removed, this, [this] () { m_waylandContrastManager->deleteLater(); m_waylandContrastManager = nullptr; } ); } return m_waylandContrastManager; } KWayland::Client::SlideManager *WaylandIntegration::waylandSlideManager() { if (!m_waylandSlideManager) { const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Slide); if (wmInterface.name == 0) { return nullptr; } m_waylandSlideManager = m_registry->createSlideManager(wmInterface.name, wmInterface.version, this); connect(m_waylandSlideManager, &KWayland::Client::SlideManager::removed, this, [this] () { m_waylandSlideManager->deleteLater(); m_waylandSlideManager = nullptr; } ); } return m_waylandSlideManager; } KWayland::Client::Compositor *WaylandIntegration::waylandCompositor() const { return m_waylandCompositor; } KWayland::Client::PlasmaWindowManagement *WaylandIntegration::plasmaWindowManagement() { using namespace KWayland::Client; if (!m_wm) { const Registry::AnnouncedInterface wmInterface = m_registry->interface(Registry::Interface::PlasmaWindowManagement); if (wmInterface.name == 0) { qCWarning(KWAYLAND_KWS) << "This compositor does not support the Plasma Window Management interface"; return nullptr; } m_wm = m_registry->createPlasmaWindowManagement(wmInterface.name, wmInterface.version, this); connect(m_wm, &PlasmaWindowManagement::windowCreated, this, [this] (PlasmaWindow *w) { emit KWindowSystem::self()->windowAdded(w->internalId()); emit KWindowSystem::self()->stackingOrderChanged(); connect(w, &PlasmaWindow::unmapped, this, [w] { emit KWindowSystem::self()->windowRemoved(w->internalId()); emit KWindowSystem::self()->stackingOrderChanged(); } ); } ); connect(m_wm, &PlasmaWindowManagement::activeWindowChanged, this, [this] { if (PlasmaWindow *w = m_wm->activeWindow()) { emit KWindowSystem::self()->activeWindowChanged(w->internalId()); } else { emit KWindowSystem::self()->activeWindowChanged(0); } } ); connect(m_wm, &PlasmaWindowManagement::showingDesktopChanged, KWindowSystem::self(), &KWindowSystem::showingDesktopChanged); qCDebug(KWAYLAND_KWS) << "Plasma Window Management interface bound"; } return m_wm; } KWayland::Client::PlasmaShell *WaylandIntegration::waylandPlasmaShell() { if (!m_waylandPlasmaShell) { const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::PlasmaShell); if (wmInterface.name == 0) { return nullptr; } m_waylandPlasmaShell = m_registry->createPlasmaShell(wmInterface.name, wmInterface.version, this); } return m_waylandPlasmaShell; }