File indexing completed on 2024-12-22 05:09:23

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 #include "registry.h"
0008 #include "appmenu.h"
0009 #include "blur.h"
0010 #include "compositor.h"
0011 #include "connection_thread.h"
0012 #include "contrast.h"
0013 #include "datadevicemanager.h"
0014 #include "dpms.h"
0015 #include "event_queue.h"
0016 #include "fakeinput.h"
0017 #include "idleinhibit.h"
0018 #include "logging.h"
0019 #include "output.h"
0020 #include "plasmashell.h"
0021 #include "plasmavirtualdesktop.h"
0022 #include "plasmawindowmanagement.h"
0023 #include "pointerconstraints.h"
0024 #include "pointergestures.h"
0025 #include "relativepointer.h"
0026 #include "seat.h"
0027 #include "shadow.h"
0028 #include "shell.h"
0029 #include "shm_pool.h"
0030 #include "slide.h"
0031 #include "subcompositor.h"
0032 #include "textinput_p.h"
0033 #include "wayland_pointer_p.h"
0034 #include "xdgdecoration.h"
0035 #include "xdgforeign_v2.h"
0036 #include "xdgoutput.h"
0037 #include "xdgshell.h"
0038 #include "xdgshell_p.h"
0039 // Qt
0040 #include <QDebug>
0041 // wayland
0042 #include "../compat/wayland-xdg-shell-v5-client-protocol.h"
0043 #include <wayland-appmenu-client-protocol.h>
0044 #include <wayland-blur-client-protocol.h>
0045 #include <wayland-client-protocol.h>
0046 #include <wayland-contrast-client-protocol.h>
0047 #include <wayland-dpms-client-protocol.h>
0048 #include <wayland-fake-input-client-protocol.h>
0049 #include <wayland-idle-inhibit-unstable-v1-client-protocol.h>
0050 #include <wayland-plasma-shell-client-protocol.h>
0051 #include <wayland-plasma-virtual-desktop-client-protocol.h>
0052 #include <wayland-plasma-window-management-client-protocol.h>
0053 #include <wayland-pointer-constraints-unstable-v1-client-protocol.h>
0054 #include <wayland-pointer-gestures-unstable-v1-client-protocol.h>
0055 #include <wayland-relativepointer-unstable-v1-client-protocol.h>
0056 #include <wayland-shadow-client-protocol.h>
0057 #include <wayland-slide-client-protocol.h>
0058 #include <wayland-text-input-v0-client-protocol.h>
0059 #include <wayland-text-input-v2-client-protocol.h>
0060 #include <wayland-xdg-decoration-unstable-v1-client-protocol.h>
0061 #include <wayland-xdg-foreign-unstable-v2-client-protocol.h>
0062 #include <wayland-xdg-output-unstable-v1-client-protocol.h>
0063 #include <wayland-xdg-shell-client-protocol.h>
0064 #include <wayland-xdg-shell-v6-client-protocol.h>
0065 
0066 /*****
0067  * How to add another interface:
0068  * * define a new enum value in Registry::Interface
0069  * * define the bind<InterfaceName> method
0070  * * define the create<InterfaceName> method
0071  * * define the <interfaceName>Announced signal
0072  * * define the <interfaceName>Removed signal
0073  * * add a block to s_interfaces
0074  * * add the BIND macro for the new bind<InterfaceName>
0075  * * add the CREATE macro for the new create<InterfaceName>
0076  * * extend registry unit test to verify that it works
0077  ****/
0078 
0079 namespace KWayland
0080 {
0081 namespace Client
0082 {
0083 namespace
0084 {
0085 struct SuppertedInterfaceData {
0086     quint32 maxVersion;
0087     QByteArray name;
0088     const wl_interface *interface;
0089     void (Registry::*announcedSignal)(quint32, quint32);
0090     void (Registry::*removedSignal)(quint32);
0091 };
0092 // clang-format off
0093 static const QMap<Registry::Interface, SuppertedInterfaceData> s_interfaces = {
0094     {Registry::Interface::Compositor, {
0095         4,
0096         QByteArrayLiteral("wl_compositor"),
0097         &wl_compositor_interface,
0098         &Registry::compositorAnnounced,
0099         &Registry::compositorRemoved
0100     }},
0101     {Registry::Interface::DataDeviceManager, {
0102         3,
0103         QByteArrayLiteral("wl_data_device_manager"),
0104         &wl_data_device_manager_interface,
0105         &Registry::dataDeviceManagerAnnounced,
0106         &Registry::dataDeviceManagerRemoved
0107     }},
0108     {Registry::Interface::Output, {
0109         4,
0110         QByteArrayLiteral("wl_output"),
0111         &wl_output_interface,
0112         &Registry::outputAnnounced,
0113         &Registry::outputRemoved
0114     }},
0115     {Registry::Interface::Shm, {
0116         1,
0117         QByteArrayLiteral("wl_shm"),
0118         &wl_shm_interface,
0119         &Registry::shmAnnounced,
0120         &Registry::shmRemoved
0121     }},
0122     {Registry::Interface::Seat, {
0123         5,
0124         QByteArrayLiteral("wl_seat"),
0125         &wl_seat_interface,
0126         &Registry::seatAnnounced,
0127         &Registry::seatRemoved
0128     }},
0129     {Registry::Interface::Shell, {
0130         1,
0131         QByteArrayLiteral("wl_shell"),
0132         &wl_shell_interface,
0133         &Registry::shellAnnounced,
0134         &Registry::shellRemoved
0135     }},
0136     {Registry::Interface::SubCompositor, {
0137         1,
0138         QByteArrayLiteral("wl_subcompositor"),
0139         &wl_subcompositor_interface,
0140         &Registry::subCompositorAnnounced,
0141         &Registry::subCompositorRemoved
0142     }},
0143     {Registry::Interface::PlasmaShell, {
0144         8,
0145         QByteArrayLiteral("org_kde_plasma_shell"),
0146         &org_kde_plasma_shell_interface,
0147         &Registry::plasmaShellAnnounced,
0148         &Registry::plasmaShellRemoved
0149     }},
0150     {Registry::Interface::PlasmaVirtualDesktopManagement, {
0151         2,
0152         QByteArrayLiteral("org_kde_plasma_virtual_desktop_management"),
0153         &org_kde_plasma_virtual_desktop_management_interface,
0154         &Registry::plasmaVirtualDesktopManagementAnnounced,
0155         &Registry::plasmaVirtualDesktopManagementRemoved
0156     }},
0157     {Registry::Interface::PlasmaWindowManagement, {
0158         16,
0159         QByteArrayLiteral("org_kde_plasma_window_management"),
0160         &org_kde_plasma_window_management_interface,
0161         &Registry::plasmaWindowManagementAnnounced,
0162         &Registry::plasmaWindowManagementRemoved
0163     }},
0164     {Registry::Interface::FakeInput, {
0165         4,
0166         QByteArrayLiteral("org_kde_kwin_fake_input"),
0167         &org_kde_kwin_fake_input_interface,
0168         &Registry::fakeInputAnnounced,
0169         &Registry::fakeInputRemoved
0170     }},
0171     {Registry::Interface::Shadow, {
0172         2,
0173         QByteArrayLiteral("org_kde_kwin_shadow_manager"),
0174         &org_kde_kwin_shadow_manager_interface,
0175         &Registry::shadowAnnounced,
0176         &Registry::shadowRemoved
0177     }},
0178     {Registry::Interface::Blur, {
0179         1,
0180         QByteArrayLiteral("org_kde_kwin_blur_manager"),
0181         &org_kde_kwin_blur_manager_interface,
0182         &Registry::blurAnnounced,
0183         &Registry::blurRemoved
0184     }},
0185     {Registry::Interface::Contrast, {
0186         2,
0187         QByteArrayLiteral("org_kde_kwin_contrast_manager"),
0188         &org_kde_kwin_contrast_manager_interface,
0189         &Registry::contrastAnnounced,
0190         &Registry::contrastRemoved
0191     }},
0192     {Registry::Interface::Slide, {
0193         1,
0194         QByteArrayLiteral("org_kde_kwin_slide_manager"),
0195         &org_kde_kwin_slide_manager_interface,
0196         &Registry::slideAnnounced,
0197         &Registry::slideRemoved
0198     }},
0199     {Registry::Interface::Dpms, {
0200         1,
0201         QByteArrayLiteral("org_kde_kwin_dpms_manager"),
0202         &org_kde_kwin_dpms_manager_interface,
0203         &Registry::dpmsAnnounced,
0204         &Registry::dpmsRemoved
0205     }},
0206     {Registry::Interface::TextInputManagerUnstableV0, {
0207         1,
0208         QByteArrayLiteral("wl_text_input_manager"),
0209         &wl_text_input_manager_interface,
0210         &Registry::textInputManagerUnstableV0Announced,
0211         &Registry::textInputManagerUnstableV0Removed
0212     }},
0213     {Registry::Interface::TextInputManagerUnstableV2, {
0214         1,
0215         QByteArrayLiteral("zwp_text_input_manager_v2"),
0216         &zwp_text_input_manager_v2_interface,
0217         &Registry::textInputManagerUnstableV2Announced,
0218         &Registry::textInputManagerUnstableV2Removed
0219     }},
0220     {Registry::Interface::XdgShellUnstableV5, {
0221         1,
0222         QByteArrayLiteral("xdg_shell"),
0223         &zxdg_shell_v5_interface,
0224         &Registry::xdgShellUnstableV5Announced,
0225         &Registry::xdgShellUnstableV5Removed
0226     }},
0227     {Registry::Interface::RelativePointerManagerUnstableV1, {
0228         1,
0229         QByteArrayLiteral("zwp_relative_pointer_manager_v1"),
0230         &zwp_relative_pointer_manager_v1_interface,
0231         &Registry::relativePointerManagerUnstableV1Announced,
0232         &Registry::relativePointerManagerUnstableV1Removed
0233     }},
0234     {Registry::Interface::PointerGesturesUnstableV1, {
0235         1,
0236         QByteArrayLiteral("zwp_pointer_gestures_v1"),
0237         &zwp_pointer_gestures_v1_interface,
0238         &Registry::pointerGesturesUnstableV1Announced,
0239         &Registry::pointerGesturesUnstableV1Removed
0240     }},
0241     {Registry::Interface::PointerConstraintsUnstableV1, {
0242         1,
0243         QByteArrayLiteral("zwp_pointer_constraints_v1"),
0244         &zwp_pointer_constraints_v1_interface,
0245         &Registry::pointerConstraintsUnstableV1Announced,
0246         &Registry::pointerConstraintsUnstableV1Removed
0247     }},
0248     {Registry::Interface::XdgExporterUnstableV2, {
0249         1,
0250         QByteArrayLiteral("zxdg_exporter_v2"),
0251         &zxdg_exporter_v2_interface,
0252         &Registry::exporterUnstableV2Announced,
0253         &Registry::exporterUnstableV2Removed
0254     }},
0255     {Registry::Interface::XdgImporterUnstableV2, {
0256         1,
0257         QByteArrayLiteral("zxdg_importer_v2"),
0258         &zxdg_importer_v2_interface,
0259         &Registry::importerUnstableV2Announced,
0260         &Registry::importerUnstableV2Removed
0261     }},
0262     {Registry::Interface::XdgShellUnstableV6, {
0263         1,
0264         QByteArrayLiteral("zxdg_shell_v6"),
0265         &zxdg_shell_v6_interface,
0266         &Registry::xdgShellUnstableV6Announced,
0267         &Registry::xdgShellUnstableV6Removed
0268     }},
0269     {Registry::Interface::IdleInhibitManagerUnstableV1, {
0270         1,
0271         QByteArrayLiteral("zwp_idle_inhibit_manager_v1"),
0272         &zwp_idle_inhibit_manager_v1_interface,
0273         &Registry::idleInhibitManagerUnstableV1Announced,
0274         &Registry::idleInhibitManagerUnstableV1Removed
0275     }},
0276     {Registry::Interface::AppMenu, {
0277         1,
0278         QByteArrayLiteral("org_kde_kwin_appmenu_manager"),
0279         &org_kde_kwin_appmenu_manager_interface,
0280         &Registry::appMenuAnnounced,
0281         &Registry::appMenuRemoved
0282     }},
0283     {Registry::Interface::XdgOutputUnstableV1, {
0284         2,
0285         QByteArrayLiteral("zxdg_output_manager_v1"),
0286         &zxdg_output_manager_v1_interface,
0287         &Registry::xdgOutputAnnounced,
0288         &Registry::xdgOutputRemoved
0289     }},
0290     {Registry::Interface::XdgShellStable, {
0291         1,
0292         QByteArrayLiteral("xdg_wm_base"),
0293         &xdg_wm_base_interface,
0294         &Registry::xdgShellStableAnnounced,
0295         &Registry::xdgShellStableRemoved
0296     }},
0297     {Registry::Interface::XdgDecorationUnstableV1, {
0298         1,
0299         QByteArrayLiteral("zxdg_decoration_manager_v1"),
0300         &zxdg_decoration_manager_v1_interface,
0301         &Registry::xdgDecorationAnnounced,
0302         &Registry::xdgDecorationRemoved
0303     }},
0304     {Registry::Interface::PlasmaActivationFeedback, {
0305         1,
0306         QByteArrayLiteral("org_kde_plasma_activation_feedback"),
0307         &org_kde_plasma_activation_feedback_interface,
0308         &Registry::plasmaActivationFeedbackAnnounced,
0309         &Registry::plasmaActivationFeedbackRemoved
0310     }},
0311 };
0312 // clang-format on
0313 
0314 static quint32 maxVersion(const Registry::Interface &interface)
0315 {
0316     auto it = s_interfaces.find(interface);
0317     if (it != s_interfaces.end()) {
0318         return it.value().maxVersion;
0319     }
0320     return 0;
0321 }
0322 }
0323 
0324 class Q_DECL_HIDDEN Registry::Private
0325 {
0326 public:
0327     Private(Registry *q);
0328     void setup();
0329     bool hasInterface(Interface interface) const;
0330     AnnouncedInterface interface(Interface interface) const;
0331     QList<AnnouncedInterface> interfaces(Interface interface) const;
0332     Interface interfaceForName(quint32 name) const;
0333     template<typename T>
0334     T *bind(Interface interface, uint32_t name, uint32_t version) const;
0335     template<class T, typename WL>
0336     T *create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const);
0337 
0338     WaylandPointer<wl_registry, wl_registry_destroy> registry;
0339     static const struct wl_callback_listener s_callbackListener;
0340     WaylandPointer<wl_callback, wl_callback_destroy> callback;
0341     EventQueue *queue = nullptr;
0342 
0343 private:
0344     void handleAnnounce(uint32_t name, const char *interface, uint32_t version);
0345     void handleRemove(uint32_t name);
0346     void handleGlobalSync();
0347     static void globalAnnounce(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version);
0348     static void globalRemove(void *data, struct wl_registry *registry, uint32_t name);
0349     static void globalSync(void *data, struct wl_callback *callback, uint32_t serial);
0350 
0351     Registry *q;
0352     struct InterfaceData {
0353         Interface interface;
0354         uint32_t name;
0355         uint32_t version;
0356     };
0357     QList<InterfaceData> m_interfaces;
0358     static const struct wl_registry_listener s_registryListener;
0359 };
0360 
0361 Registry::Private::Private(Registry *q)
0362     : q(q)
0363 {
0364 }
0365 
0366 void Registry::Private::setup()
0367 {
0368     wl_registry_add_listener(registry, &s_registryListener, this);
0369     wl_callback_add_listener(callback, &s_callbackListener, this);
0370 }
0371 
0372 Registry::Registry(QObject *parent)
0373     : QObject(parent)
0374     , d(new Private(this))
0375 {
0376 }
0377 
0378 Registry::~Registry()
0379 {
0380     release();
0381 }
0382 
0383 void Registry::release()
0384 {
0385     d->registry.release();
0386     d->callback.release();
0387 }
0388 
0389 void Registry::destroy()
0390 {
0391     Q_EMIT registryDestroyed();
0392     d->registry.destroy();
0393     d->callback.destroy();
0394 }
0395 
0396 void Registry::create(wl_display *display)
0397 {
0398     Q_ASSERT(display);
0399     Q_ASSERT(!isValid());
0400     d->registry.setup(wl_display_get_registry(display));
0401     d->callback.setup(wl_display_sync(display));
0402     if (d->queue) {
0403         d->queue->addProxy(d->registry);
0404         d->queue->addProxy(d->callback);
0405     }
0406 }
0407 
0408 void Registry::create(ConnectionThread *connection)
0409 {
0410     create(connection->display());
0411     connect(connection, &ConnectionThread::connectionDied, this, &Registry::destroy);
0412 }
0413 
0414 void Registry::setup()
0415 {
0416     Q_ASSERT(isValid());
0417     d->setup();
0418 }
0419 
0420 void Registry::setEventQueue(EventQueue *queue)
0421 {
0422     d->queue = queue;
0423     if (!queue) {
0424         return;
0425     }
0426     if (d->registry) {
0427         d->queue->addProxy(d->registry);
0428     }
0429     if (d->callback) {
0430         d->queue->addProxy(d->callback);
0431     }
0432 }
0433 
0434 EventQueue *Registry::eventQueue()
0435 {
0436     return d->queue;
0437 }
0438 
0439 #ifndef K_DOXYGEN
0440 const struct wl_registry_listener Registry::Private::s_registryListener = {globalAnnounce, globalRemove};
0441 
0442 const struct wl_callback_listener Registry::Private::s_callbackListener = {globalSync};
0443 #endif
0444 
0445 void Registry::Private::globalAnnounce(void *data, wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
0446 {
0447     auto r = reinterpret_cast<Registry::Private *>(data);
0448     Q_ASSERT(registry == r->registry);
0449     r->handleAnnounce(name, interface, version);
0450 }
0451 
0452 void Registry::Private::globalRemove(void *data, wl_registry *registry, uint32_t name)
0453 {
0454     auto r = reinterpret_cast<Registry::Private *>(data);
0455     Q_ASSERT(registry == r->registry);
0456     r->handleRemove(name);
0457 }
0458 
0459 void Registry::Private::globalSync(void *data, wl_callback *callback, uint32_t serial)
0460 {
0461     Q_UNUSED(serial)
0462     auto r = reinterpret_cast<Registry::Private *>(data);
0463     Q_ASSERT(r->callback == callback);
0464     r->handleGlobalSync();
0465     r->callback.release();
0466 }
0467 
0468 void Registry::Private::handleGlobalSync()
0469 {
0470     Q_EMIT q->interfacesAnnounced();
0471 }
0472 
0473 namespace
0474 {
0475 static Registry::Interface nameToInterface(const char *interface)
0476 {
0477     for (auto it = s_interfaces.constBegin(); it != s_interfaces.constEnd(); ++it) {
0478         if (qstrcmp(interface, it.value().name) == 0) {
0479             return it.key();
0480         }
0481     }
0482     return Registry::Interface::Unknown;
0483 }
0484 }
0485 
0486 void Registry::Private::handleAnnounce(uint32_t name, const char *interface, uint32_t version)
0487 {
0488     Interface i = nameToInterface(interface);
0489     Q_EMIT q->interfaceAnnounced(QByteArray(interface), name, version);
0490     if (i == Interface::Unknown) {
0491         qCDebug(KWAYLAND_CLIENT) << "Unknown interface announced: " << interface << "/" << name << "/" << version;
0492         return;
0493     }
0494     qCDebug(KWAYLAND_CLIENT) << "Wayland Interface: " << interface << "/" << name << "/" << version;
0495     m_interfaces.append({i, name, version});
0496     auto it = s_interfaces.constFind(i);
0497     if (it != s_interfaces.end()) {
0498         Q_EMIT(q->*it.value().announcedSignal)(name, version);
0499     }
0500 }
0501 
0502 void Registry::Private::handleRemove(uint32_t name)
0503 {
0504     auto it = std::find_if(m_interfaces.begin(), m_interfaces.end(), [name](const InterfaceData &data) {
0505         return data.name == name;
0506     });
0507     if (it != m_interfaces.end()) {
0508         InterfaceData data = *(it);
0509         m_interfaces.erase(it);
0510         auto sit = s_interfaces.find(data.interface);
0511         if (sit != s_interfaces.end()) {
0512             Q_EMIT(q->*sit.value().removedSignal)(data.name);
0513         }
0514     }
0515     Q_EMIT q->interfaceRemoved(name);
0516 }
0517 
0518 bool Registry::Private::hasInterface(Registry::Interface interface) const
0519 {
0520     auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [interface](const InterfaceData &data) {
0521         return data.interface == interface;
0522     });
0523     return it != m_interfaces.constEnd();
0524 }
0525 
0526 QList<Registry::AnnouncedInterface> Registry::Private::interfaces(Interface interface) const
0527 {
0528     QList<Registry::AnnouncedInterface> retVal;
0529     for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
0530         const auto &data = *it;
0531         if (data.interface == interface) {
0532             retVal << AnnouncedInterface{data.name, data.version};
0533         }
0534     }
0535     return retVal;
0536 }
0537 
0538 Registry::AnnouncedInterface Registry::Private::interface(Interface interface) const
0539 {
0540     const auto all = interfaces(interface);
0541     if (!all.isEmpty()) {
0542         return all.last();
0543     }
0544     return AnnouncedInterface{0, 0};
0545 }
0546 
0547 Registry::Interface Registry::Private::interfaceForName(quint32 name) const
0548 {
0549     auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [name](const InterfaceData &data) {
0550         return data.name == name;
0551     });
0552     if (it == m_interfaces.constEnd()) {
0553         return Interface::Unknown;
0554     }
0555     return (*it).interface;
0556 }
0557 
0558 bool Registry::hasInterface(Registry::Interface interface) const
0559 {
0560     return d->hasInterface(interface);
0561 }
0562 
0563 QList<Registry::AnnouncedInterface> Registry::interfaces(Interface interface) const
0564 {
0565     return d->interfaces(interface);
0566 }
0567 
0568 Registry::AnnouncedInterface Registry::interface(Interface interface) const
0569 {
0570     return d->interface(interface);
0571 }
0572 
0573 // clang-format off
0574 #define BIND2(__NAME__, __INAME__, __WL__) \
0575 __WL__ *Registry::bind##__NAME__(uint32_t name, uint32_t version) const \
0576 { \
0577     return d->bind<__WL__>(Interface::__INAME__, name, qMin(maxVersion(Interface::__INAME__), version)); \
0578 }
0579 
0580 #define BIND(__NAME__, __WL__) BIND2(__NAME__, __NAME__, __WL__)
0581 // clang-format on
0582 
0583 BIND(Compositor, wl_compositor)
0584 BIND(Output, wl_output)
0585 BIND(Seat, wl_seat)
0586 BIND(Shell, wl_shell)
0587 BIND(Shm, wl_shm)
0588 BIND(SubCompositor, wl_subcompositor)
0589 BIND(DataDeviceManager, wl_data_device_manager)
0590 BIND(PlasmaShell, org_kde_plasma_shell)
0591 BIND(PlasmaActivationFeedback, org_kde_plasma_activation_feedback)
0592 BIND(PlasmaVirtualDesktopManagement, org_kde_plasma_virtual_desktop_management)
0593 BIND(PlasmaWindowManagement, org_kde_plasma_window_management)
0594 BIND(FakeInput, org_kde_kwin_fake_input)
0595 BIND(TextInputManagerUnstableV0, wl_text_input_manager)
0596 BIND(TextInputManagerUnstableV2, zwp_text_input_manager_v2)
0597 BIND(XdgShellUnstableV5, xdg_shell)
0598 BIND(XdgShellUnstableV6, zxdg_shell_v6)
0599 BIND(XdgShellStable, xdg_wm_base)
0600 BIND(RelativePointerManagerUnstableV1, zwp_relative_pointer_manager_v1)
0601 BIND(PointerGesturesUnstableV1, zwp_pointer_gestures_v1)
0602 BIND(PointerConstraintsUnstableV1, zwp_pointer_constraints_v1)
0603 BIND(XdgExporterUnstableV2, zxdg_exporter_v2)
0604 BIND(XdgImporterUnstableV2, zxdg_importer_v2)
0605 BIND(IdleInhibitManagerUnstableV1, zwp_idle_inhibit_manager_v1)
0606 BIND2(ShadowManager, Shadow, org_kde_kwin_shadow_manager)
0607 BIND2(BlurManager, Blur, org_kde_kwin_blur_manager)
0608 BIND2(ContrastManager, Contrast, org_kde_kwin_contrast_manager)
0609 BIND2(SlideManager, Slide, org_kde_kwin_slide_manager)
0610 BIND2(DpmsManager, Dpms, org_kde_kwin_dpms_manager)
0611 BIND2(AppMenuManager, AppMenu, org_kde_kwin_appmenu_manager)
0612 BIND(XdgOutputUnstableV1, zxdg_output_manager_v1)
0613 BIND(XdgDecorationUnstableV1, zxdg_decoration_manager_v1)
0614 
0615 #undef BIND
0616 #undef BIND2
0617 
0618 template<class T, typename WL>
0619 T *Registry::Private::create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const)
0620 {
0621     T *t = new T(parent);
0622     t->setEventQueue(queue);
0623     t->setup((q->*bindMethod)(name, version));
0624     QObject::connect(q, &Registry::interfaceRemoved, t, [t, name](quint32 removed) {
0625         if (name == removed) {
0626             Q_EMIT t->removed();
0627         }
0628     });
0629     QObject::connect(q, &Registry::registryDestroyed, t, &T::destroy);
0630     return t;
0631 }
0632 
0633 // clang-format off
0634 #define CREATE2(__NAME__, __BINDNAME__) \
0635 __NAME__ *Registry::create##__NAME__(quint32 name, quint32 version, QObject *parent) \
0636 { \
0637     return d->create<__NAME__>(name, version, parent, &Registry::bind##__BINDNAME__); \
0638 }
0639 
0640 #define CREATE(__NAME__) CREATE2(__NAME__, __NAME__)
0641 // clang-format on
0642 
0643 CREATE(Compositor)
0644 CREATE(Seat)
0645 CREATE(Shell)
0646 CREATE(SubCompositor)
0647 CREATE(Output)
0648 CREATE(DataDeviceManager)
0649 CREATE(PlasmaShell)
0650 CREATE(PlasmaActivationFeedback)
0651 CREATE(PlasmaVirtualDesktopManagement)
0652 CREATE(PlasmaWindowManagement)
0653 CREATE(FakeInput)
0654 CREATE(ShadowManager)
0655 CREATE(BlurManager)
0656 CREATE(ContrastManager)
0657 CREATE(SlideManager)
0658 CREATE(DpmsManager)
0659 CREATE2(ShmPool, Shm)
0660 CREATE(AppMenuManager)
0661 
0662 #undef CREATE
0663 #undef CREATE2
0664 
0665 XdgExporter *Registry::createXdgExporter(quint32 name, quint32 version, QObject *parent)
0666 {
0667     // only V1 supported for now
0668     return d->create<XdgExporterUnstableV2>(name, version, parent, &Registry::bindXdgExporterUnstableV2);
0669 }
0670 
0671 XdgImporter *Registry::createXdgImporter(quint32 name, quint32 version, QObject *parent)
0672 {
0673     // only V1 supported for now
0674     return d->create<XdgImporterUnstableV2>(name, version, parent, &Registry::bindXdgImporterUnstableV2);
0675 }
0676 
0677 TextInputManager *Registry::createTextInputManager(quint32 name, quint32 version, QObject *parent)
0678 {
0679     switch (d->interfaceForName(name)) {
0680     case Interface::TextInputManagerUnstableV0:
0681         return d->create<TextInputManagerUnstableV0>(name, version, parent, &Registry::bindTextInputManagerUnstableV0);
0682     case Interface::TextInputManagerUnstableV2:
0683         return d->create<TextInputManagerUnstableV2>(name, version, parent, &Registry::bindTextInputManagerUnstableV2);
0684     default:
0685         return nullptr;
0686     }
0687 }
0688 
0689 XdgShell *Registry::createXdgShell(quint32 name, quint32 version, QObject *parent)
0690 {
0691     switch (d->interfaceForName(name)) {
0692     case Interface::XdgShellUnstableV5:
0693         return d->create<XdgShellUnstableV5>(name, version, parent, &Registry::bindXdgShellUnstableV5);
0694     case Interface::XdgShellUnstableV6:
0695         return d->create<XdgShellUnstableV6>(name, version, parent, &Registry::bindXdgShellUnstableV6);
0696     case Interface::XdgShellStable:
0697         return d->create<XdgShellStable>(name, version, parent, &Registry::bindXdgShellStable);
0698     default:
0699         return nullptr;
0700     }
0701 }
0702 
0703 RelativePointerManager *Registry::createRelativePointerManager(quint32 name, quint32 version, QObject *parent)
0704 {
0705     switch (d->interfaceForName(name)) {
0706     case Interface::RelativePointerManagerUnstableV1:
0707         return d->create<RelativePointerManager>(name, version, parent, &Registry::bindRelativePointerManagerUnstableV1);
0708     default:
0709         return nullptr;
0710     }
0711 }
0712 
0713 PointerGestures *Registry::createPointerGestures(quint32 name, quint32 version, QObject *parent)
0714 {
0715     switch (d->interfaceForName(name)) {
0716     case Interface::PointerGesturesUnstableV1:
0717         return d->create<PointerGestures>(name, version, parent, &Registry::bindPointerGesturesUnstableV1);
0718     default:
0719         return nullptr;
0720     }
0721 }
0722 
0723 PointerConstraints *Registry::createPointerConstraints(quint32 name, quint32 version, QObject *parent)
0724 {
0725     switch (d->interfaceForName(name)) {
0726     case Interface::PointerConstraintsUnstableV1:
0727         return d->create<PointerConstraints>(name, version, parent, &Registry::bindPointerConstraintsUnstableV1);
0728     default:
0729         return nullptr;
0730     }
0731 }
0732 
0733 IdleInhibitManager *Registry::createIdleInhibitManager(quint32 name, quint32 version, QObject *parent)
0734 {
0735     switch (d->interfaceForName(name)) {
0736     case Interface::IdleInhibitManagerUnstableV1:
0737         return d->create<IdleInhibitManager>(name, version, parent, &Registry::bindIdleInhibitManagerUnstableV1);
0738     default:
0739         return nullptr;
0740     }
0741 }
0742 
0743 XdgOutputManager *Registry::createXdgOutputManager(quint32 name, quint32 version, QObject *parent)
0744 {
0745     switch (d->interfaceForName(name)) {
0746     case Interface::XdgOutputUnstableV1:
0747         return d->create<XdgOutputManager>(name, version, parent, &Registry::bindXdgOutputUnstableV1);
0748     default:
0749         return nullptr;
0750     }
0751 }
0752 
0753 XdgDecorationManager *Registry::createXdgDecorationManager(quint32 name, quint32 version, QObject *parent)
0754 {
0755     switch (d->interfaceForName(name)) {
0756     case Interface::XdgDecorationUnstableV1:
0757         return d->create<XdgDecorationManager>(name, version, parent, &Registry::bindXdgDecorationUnstableV1);
0758     default:
0759         return nullptr;
0760     }
0761 }
0762 
0763 namespace
0764 {
0765 static const wl_interface *wlInterface(Registry::Interface interface)
0766 {
0767     auto it = s_interfaces.find(interface);
0768     if (it != s_interfaces.end()) {
0769         return it.value().interface;
0770     }
0771     return nullptr;
0772 }
0773 }
0774 
0775 template<typename T>
0776 T *Registry::Private::bind(Registry::Interface interface, uint32_t name, uint32_t version) const
0777 {
0778     auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [=](const InterfaceData &data) {
0779         return data.interface == interface && data.name == name && data.version >= version;
0780     });
0781     if (it == m_interfaces.constEnd()) {
0782         qCDebug(KWAYLAND_CLIENT) << "Don't have interface " << int(interface) << "with name " << name << "and minimum version" << version;
0783         return nullptr;
0784     }
0785     auto t = reinterpret_cast<T *>(wl_registry_bind(registry, name, wlInterface(interface), version));
0786     if (queue) {
0787         queue->addProxy(t);
0788     }
0789     return t;
0790 }
0791 
0792 bool Registry::isValid() const
0793 {
0794     return d->registry.isValid();
0795 }
0796 
0797 wl_registry *Registry::registry()
0798 {
0799     return d->registry;
0800 }
0801 
0802 Registry::operator wl_registry *() const
0803 {
0804     return d->registry;
0805 }
0806 
0807 Registry::operator wl_registry *()
0808 {
0809     return d->registry;
0810 }
0811 
0812 }
0813 }
0814 
0815 #include "moc_registry.cpp"