diff --git a/src/plasmaquick/CMakeLists.txt b/src/plasmaquick/CMakeLists.txt --- a/src/plasmaquick/CMakeLists.txt +++ b/src/plasmaquick/CMakeLists.txt @@ -21,6 +21,10 @@ ../declarativeimports/core/units.cpp ) +if(HAVE_KWAYLAND) + set(plasmaquick_LIB_SRC ${plasmaquick_LIB_SRC} waylandintegration.cpp) +endif() + ecm_qt_declare_logging_category(PlasmaQuick_LIB_SRCS HEADER debug_p.h IDENTIFIER LOG_PLASMAQUICK CATEGORY_NAME org.kde.plasmaquick) add_library(KF5PlasmaQuick SHARED ${plasmaquick_LIB_SRC}) diff --git a/src/plasmaquick/dialog.cpp b/src/plasmaquick/dialog.cpp --- a/src/plasmaquick/dialog.cpp +++ b/src/plasmaquick/dialog.cpp @@ -48,6 +48,7 @@ #include #if HAVE_KWAYLAND +#include "waylandintegration_p.h" #include #include #endif @@ -704,7 +705,7 @@ } using namespace KWayland::Client; - PlasmaShell *interface = DialogShadows::self()->waylandPlasmaShellInterface(); + PlasmaShell *interface = WaylandIntegration::self()->waylandPlasmaShell(); if (!interface) { return; } diff --git a/src/plasmaquick/dialogshadows.cpp b/src/plasmaquick/dialogshadows.cpp --- a/src/plasmaquick/dialogshadows.cpp +++ b/src/plasmaquick/dialogshadows.cpp @@ -32,12 +32,10 @@ #endif #if HAVE_KWAYLAND -#include -#include +#include "waylandintegration_p.h" #include #include #include -#include #endif #include @@ -53,7 +51,6 @@ , m_isX11(KWindowSystem::isPlatformX11()) #endif { - setupWaylandIntegration(); } ~Private() @@ -80,8 +77,6 @@ void windowDestroyed(QObject *deletedObject); void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders); - void setupWaylandIntegration(); - DialogShadows *q; QList m_shadowPixmaps; @@ -104,10 +99,6 @@ #if HAVE_KWAYLAND struct Wayland { - KWayland::Client::ShadowManager *manager = nullptr; - KWayland::Client::ShmPool *shmPool = nullptr; - KWayland::Client::PlasmaShell *plasmaShell = nullptr; - QList shadowBuffers; }; Wayland m_wayland; @@ -308,9 +299,9 @@ m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-top")).width(), 1)); #if HAVE_KWAYLAND - if (m_wayland.shmPool) { + if (KWayland::Client::ShmPool *shmPool = WaylandIntegration::self()->waylandShmPool()) { for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) { - m_wayland.shadowBuffers << m_wayland.shmPool->createBuffer(it->toImage()); + m_wayland.shadowBuffers << shmPool->createBuffer(it->toImage()); } } #endif @@ -524,7 +515,7 @@ } #endif #if HAVE_KWAYLAND - if (m_wayland.manager) { + if (WaylandIntegration::self()->waylandShadowManager()) { updateShadowWayland(window, enabledBorders); } #endif @@ -553,7 +544,7 @@ void DialogShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) { #if HAVE_KWAYLAND - if (!m_wayland.shmPool) { + if (!WaylandIntegration::self()->waylandShmPool()) { return; } if (m_wayland.shadowBuffers.isEmpty()) { @@ -564,7 +555,8 @@ if (!surface) { return; } - auto shadow = m_wayland.manager->createShadow(surface, surface); + KWayland::Client::ShadowManager *manager = WaylandIntegration::self()->waylandShadowManager(); + auto shadow = manager->createShadow(surface, surface); //shadow-top if (enabledBorders & Plasma::FrameSvg::TopBorder) { @@ -666,7 +658,7 @@ } #endif #if HAVE_KWAYLAND - if (m_wayland.manager) { + if (WaylandIntegration::self()->waylandShadowManager()) { clearShadowWayland(window); } #endif @@ -688,7 +680,8 @@ if (!surface) { return; } - m_wayland.manager->removeShadow(surface); + KWayland::Client::ShadowManager *manager = WaylandIntegration::self()->waylandShadowManager(); + manager->removeShadow(surface); surface->commit(KWayland::Client::Surface::CommitFlag::None); #endif } @@ -698,49 +691,5 @@ return hasElement(QStringLiteral("shadow-left")); } -KWayland::Client::PlasmaShell *DialogShadows::waylandPlasmaShellInterface() const -{ -#if HAVE_KWAYLAND - return d->m_wayland.plasmaShell; -#else - return nullptr; -#endif -} - -void DialogShadows::Private::setupWaylandIntegration() -{ -#if HAVE_KWAYLAND - if (!KWindowSystem::isPlatformWayland()) { - return; - } - using namespace KWayland::Client; - ConnectionThread *connection = ConnectionThread::fromApplication(q); - if (!connection) { - return; - } - Registry *registry = new Registry(q); - registry->create(connection); - connect(registry, &Registry::shadowAnnounced, q, - [this, registry] (quint32 name, quint32 version) { - m_wayland.manager = registry->createShadowManager(name, version, q); - updateShadows(); - }, Qt::QueuedConnection - ); - connect(registry, &Registry::shmAnnounced, q, - [this, registry] (quint32 name, quint32 version) { - m_wayland.shmPool = registry->createShmPool(name, version, q); - updateShadows(); - }, Qt::QueuedConnection - ); - connect(registry, &Registry::plasmaShellAnnounced, q, - [this, registry] (quint32 name, quint32 version) { - m_wayland.plasmaShell = registry->createPlasmaShell(name, version, q); - } - ); - registry->setup(); - connection->roundtrip(); -#endif -} - #include "moc_dialogshadows_p.cpp" diff --git a/src/plasmaquick/dialogshadows_p.h b/src/plasmaquick/dialogshadows_p.h --- a/src/plasmaquick/dialogshadows_p.h +++ b/src/plasmaquick/dialogshadows_p.h @@ -24,14 +24,6 @@ #include "plasma/framesvg.h" #include "plasma/svg.h" -namespace KWayland -{ - namespace Client - { - class PlasmaShell; - } -} - class DialogShadows : public Plasma::Svg { Q_OBJECT @@ -49,8 +41,6 @@ bool enabled() const; - KWayland::Client::PlasmaShell *waylandPlasmaShellInterface() const; - private: class Private; Private *const d; diff --git a/src/plasmaquick/waylandintegration.cpp b/src/plasmaquick/waylandintegration.cpp new file mode 100644 --- /dev/null +++ b/src/plasmaquick/waylandintegration.cpp @@ -0,0 +1,132 @@ +/* + * Copyright 2020 Vlad Zahorodnii + * + * Based on WaylandIntegration from kwayland-integration + * + * Copyright 2014 Martin Gräßlin + * Copyright 2015 Marco Martin + * + * This program 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. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "waylandintegration_p.h" +#include "debug_p.h" + +#include +#include +#include +#include +#include + +#include + +class WaylandIntegrationSingleton +{ +public: + WaylandIntegration self; +}; + +Q_GLOBAL_STATIC(WaylandIntegrationSingleton, privateWaylandIntegrationSelf) + +WaylandIntegration::WaylandIntegration(QObject *parent) + : QObject(parent) +{ + setupKWaylandIntegration(); +} + +WaylandIntegration::~WaylandIntegration() +{ +} + +KWayland::Client::PlasmaShell *WaylandIntegration::waylandPlasmaShell() +{ + if (!m_waylandPlasmaShell && m_registry) { + const KWayland::Client::Registry::AnnouncedInterface interface = + m_registry->interface(KWayland::Client::Registry::Interface::PlasmaShell); + + if (interface.name == 0) { + qCWarning(LOG_PLASMAQUICK) << "The compositor does not support the plasma shell protocol"; + return nullptr; + } + + m_waylandPlasmaShell = m_registry->createPlasmaShell(interface.name, interface.version, qApp); + + connect(m_waylandPlasmaShell, &KWayland::Client::PlasmaShell::removed, this, [this]() { + m_waylandPlasmaShell->deleteLater(); + }); + } + + return m_waylandPlasmaShell; +} + +KWayland::Client::ShadowManager *WaylandIntegration::waylandShadowManager() +{ + if (!m_waylandShadowManager && m_registry) { + const KWayland::Client::Registry::AnnouncedInterface interface = + m_registry->interface(KWayland::Client::Registry::Interface::Shadow); + + if (interface.name == 0) { + qCWarning(LOG_PLASMAQUICK) << "The compositor does not support the shadow protocol"; + return nullptr; + } + + m_waylandShadowManager = m_registry->createShadowManager(interface.name, interface.version, qApp); + + connect(m_waylandShadowManager, &KWayland::Client::ShadowManager::removed, this, [this]() { + m_waylandShadowManager->deleteLater(); + }); + } + + return m_waylandShadowManager; +} + +KWayland::Client::ShmPool *WaylandIntegration::waylandShmPool() +{ + if (!m_waylandShmPool && m_registry) { + const KWayland::Client::Registry::AnnouncedInterface interface = + m_registry->interface(KWayland::Client::Registry::Interface::Shm); + + if (interface.name == 0) { + return nullptr; + } + + m_waylandShmPool = m_registry->createShmPool(interface.name, interface.version, qApp); + + connect(m_waylandShmPool, &KWayland::Client::ShmPool::removed, this, [this]() { + m_waylandShmPool->deleteLater(); + }); + } + + return m_waylandShmPool; +} + +WaylandIntegration *WaylandIntegration::self() +{ + return &privateWaylandIntegrationSelf()->self; +} + +void WaylandIntegration::setupKWaylandIntegration() +{ + KWayland::Client::ConnectionThread *connection = KWayland::Client::ConnectionThread::fromApplication(this); + if (!connection) { + return; + } + + m_registry = new KWayland::Client::Registry(qApp); + m_registry->create(connection); + m_registry->setup(); + + connection->roundtrip(); +} diff --git a/src/plasmaquick/waylandintegration_p.h b/src/plasmaquick/waylandintegration_p.h new file mode 100644 --- /dev/null +++ b/src/plasmaquick/waylandintegration_p.h @@ -0,0 +1,61 @@ +/* + * Copyright 2020 Vlad Zahorodnii + * + * This program 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. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef WAYLANDINTEGRATION_P_H +#define WAYLANDINTEGRATION_P_H + +#include +#include + +namespace KWayland +{ +namespace Client +{ +class PlasmaShell; +class Registry; +class ShadowManager; +class ShmPool; +} +} + +class WaylandIntegration : public QObject +{ + Q_OBJECT + +public: + explicit WaylandIntegration(QObject *parent = nullptr); + ~WaylandIntegration() override; + + KWayland::Client::PlasmaShell *waylandPlasmaShell(); + KWayland::Client::ShadowManager *waylandShadowManager(); + KWayland::Client::ShmPool *waylandShmPool(); + + static WaylandIntegration *self(); + +private: + void setupKWaylandIntegration(); + + QPointer m_registry; + QPointer m_waylandPlasmaShell; + QPointer m_waylandShadowManager; + QPointer m_waylandShmPool; + + Q_DISABLE_COPY(WaylandIntegration) +}; + +#endif // WAYLANDINTEGRATION_P_H