File indexing completed on 2024-05-12 17:00:18

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
0004     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "waylandintegration.h"
0010 #include "logging.h"
0011 
0012 #include <KWayland/Client/blur.h>
0013 #include <KWayland/Client/compositor.h>
0014 #include <KWayland/Client/connection_thread.h>
0015 #include <KWayland/Client/contrast.h>
0016 #include <KWayland/Client/plasmashell.h>
0017 #include <KWayland/Client/plasmawindowmanagement.h>
0018 #include <KWayland/Client/region.h>
0019 #include <KWayland/Client/registry.h>
0020 #include <KWayland/Client/shadow.h>
0021 #include <KWayland/Client/shm_pool.h>
0022 #include <KWayland/Client/slide.h>
0023 #include <KWayland/Client/surface.h>
0024 
0025 #include <KWindowSystem>
0026 
0027 #include "waylandxdgactivationv1_p.h"
0028 #include <QGuiApplication>
0029 
0030 class WaylandIntegrationSingleton
0031 {
0032 public:
0033     WaylandIntegration self;
0034 };
0035 
0036 Q_GLOBAL_STATIC(WaylandIntegrationSingleton, privateWaylandIntegrationSelf)
0037 
0038 WaylandIntegration::WaylandIntegration()
0039     : QObject()
0040 {
0041     setupKWaylandIntegration();
0042 }
0043 
0044 WaylandIntegration::~WaylandIntegration()
0045 {
0046 }
0047 
0048 void WaylandIntegration::setupKWaylandIntegration()
0049 {
0050     using namespace KWayland::Client;
0051     m_waylandConnection = ConnectionThread::fromApplication(this);
0052     if (!m_waylandConnection) {
0053         qCWarning(KWAYLAND_KWS) << "Failed getting Wayland connection from QPA";
0054         return;
0055     }
0056     m_registry = new Registry(qApp);
0057     connect(m_registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this](const QByteArray &interfaceName, quint32 name, quint32 version) {
0058         if (interfaceName != xdg_activation_v1_interface.name)
0059             return;
0060 
0061         m_activationInterface = {name, version};
0062     });
0063     m_registry->create(m_waylandConnection);
0064     m_waylandCompositor = Compositor::fromApplication(this);
0065 
0066     m_registry->setup();
0067     m_waylandConnection->roundtrip();
0068 }
0069 
0070 WaylandIntegration *WaylandIntegration::self()
0071 {
0072     return &privateWaylandIntegrationSelf()->self;
0073 }
0074 
0075 KWayland::Client::Registry *WaylandIntegration::registry() const
0076 {
0077     return m_registry;
0078 }
0079 
0080 KWayland::Client::ConnectionThread *WaylandIntegration::waylandConnection() const
0081 {
0082     return m_waylandConnection;
0083 }
0084 
0085 KWayland::Client::BlurManager *WaylandIntegration::waylandBlurManager()
0086 {
0087     if (!m_waylandBlurManager && m_registry) {
0088         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Blur);
0089 
0090         if (wmInterface.name == 0) {
0091             return nullptr;
0092         }
0093 
0094         m_waylandBlurManager = m_registry->createBlurManager(wmInterface.name, wmInterface.version, qApp);
0095 
0096         connect(m_waylandBlurManager, &KWayland::Client::BlurManager::removed, this, [this]() {
0097             m_waylandBlurManager->deleteLater();
0098         });
0099     }
0100 
0101     return m_waylandBlurManager;
0102 }
0103 
0104 KWayland::Client::ContrastManager *WaylandIntegration::waylandContrastManager()
0105 {
0106     if (!m_waylandContrastManager && m_registry) {
0107         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Contrast);
0108 
0109         if (wmInterface.name == 0) {
0110             return nullptr;
0111         }
0112 
0113         m_waylandContrastManager = m_registry->createContrastManager(wmInterface.name, wmInterface.version, qApp);
0114 
0115         connect(m_waylandContrastManager, &KWayland::Client::ContrastManager::removed, this, [this]() {
0116             m_waylandContrastManager->deleteLater();
0117         });
0118     }
0119     return m_waylandContrastManager;
0120 }
0121 
0122 KWayland::Client::SlideManager *WaylandIntegration::waylandSlideManager()
0123 {
0124     if (!m_waylandSlideManager && m_registry) {
0125         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Slide);
0126 
0127         if (wmInterface.name == 0) {
0128             return nullptr;
0129         }
0130 
0131         m_waylandSlideManager = m_registry->createSlideManager(wmInterface.name, wmInterface.version, qApp);
0132 
0133         connect(m_waylandSlideManager, &KWayland::Client::SlideManager::removed, this, [this]() {
0134             m_waylandSlideManager->deleteLater();
0135         });
0136     }
0137 
0138     return m_waylandSlideManager;
0139 }
0140 
0141 KWayland::Client::ShadowManager *WaylandIntegration::waylandShadowManager()
0142 {
0143     if (!m_waylandShadowManager && m_registry) {
0144         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Shadow);
0145 
0146         if (wmInterface.name == 0) {
0147             qCWarning(KWAYLAND_KWS) << "This compositor does not support the Shadow interface";
0148             return nullptr;
0149         }
0150 
0151         m_waylandShadowManager = m_registry->createShadowManager(wmInterface.name, wmInterface.version, qApp);
0152 
0153         connect(m_waylandShadowManager, &KWayland::Client::ShadowManager::removed, this, [this]() {
0154             m_waylandShadowManager->deleteLater();
0155         });
0156     }
0157 
0158     return m_waylandShadowManager;
0159 }
0160 
0161 KWayland::Client::Compositor *WaylandIntegration::waylandCompositor() const
0162 {
0163     return m_waylandCompositor;
0164 }
0165 
0166 KWayland::Client::PlasmaWindowManagement *WaylandIntegration::plasmaWindowManagement()
0167 {
0168     using namespace KWayland::Client;
0169 
0170     if (!m_wm && m_registry) {
0171         const Registry::AnnouncedInterface wmInterface = m_registry->interface(Registry::Interface::PlasmaWindowManagement);
0172 
0173         if (wmInterface.name == 0) {
0174             qCWarning(KWAYLAND_KWS) << "This compositor does not support the Plasma Window Management interface";
0175             return nullptr;
0176         }
0177 
0178         m_wm = m_registry->createPlasmaWindowManagement(wmInterface.name, wmInterface.version, qApp);
0179         connect(m_wm, &PlasmaWindowManagement::showingDesktopChanged, KWindowSystem::self(), &KWindowSystem::showingDesktopChanged);
0180         qCDebug(KWAYLAND_KWS) << "Plasma Window Management interface bound";
0181 
0182         connect(m_wm, &KWayland::Client::PlasmaWindowManagement::removed, this, [this]() {
0183             m_wm->deleteLater();
0184         });
0185     }
0186 
0187     return m_wm;
0188 }
0189 
0190 KWayland::Client::PlasmaShell *WaylandIntegration::waylandPlasmaShell()
0191 {
0192     if (!m_waylandPlasmaShell && m_registry) {
0193         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::PlasmaShell);
0194 
0195         if (wmInterface.name == 0) {
0196             return nullptr;
0197         }
0198 
0199         m_waylandPlasmaShell = m_registry->createPlasmaShell(wmInterface.name, wmInterface.version, qApp);
0200     }
0201     return m_waylandPlasmaShell;
0202 }
0203 
0204 KWayland::Client::ShmPool *WaylandIntegration::createShmPool()
0205 {
0206     if (m_registry) {
0207         const KWayland::Client::Registry::AnnouncedInterface wmInterface = m_registry->interface(KWayland::Client::Registry::Interface::Shm);
0208 
0209         if (wmInterface.name == 0) {
0210             return nullptr;
0211         }
0212 
0213         return m_registry->createShmPool(wmInterface.name, wmInterface.version);
0214     }
0215 
0216     return nullptr;
0217 }
0218 
0219 WaylandXdgActivationV1 *WaylandIntegration::activation()
0220 {
0221     if (!m_activation && m_registry && m_activationInterface.name) {
0222         m_activation = new WaylandXdgActivationV1(*m_registry, m_activationInterface.name, m_activationInterface.version);
0223     }
0224     return m_activation;
0225 }