diff --git a/src/client/registry.cpp b/src/client/registry.cpp index 7423e2f..a67c327 100644 --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -1,911 +1,911 @@ /******************************************************************** Copyright 2014 Martin Gräßlin Copyright 2018 David Edmundson 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 "registry.h" #include "compositor.h" #include "connection_thread.h" #include "datadevicemanager.h" #include "dpms.h" #include "event_queue.h" #include "fakeinput.h" #include "fullscreen_shell.h" #include "idle.h" #include "idleinhibit.h" #include "keystate.h" #include "remote_access.h" #include "logging.h" #include "outputconfiguration.h" #include "outputmanagement.h" #include "outputdevice.h" #include "output.h" #include "plasmashell.h" #include "plasmavirtualdesktop.h" #include "plasmawindowmanagement.h" #include "pointerconstraints.h" #include "pointergestures.h" #include "seat.h" #include "shadow.h" #include "blur.h" #include "contrast.h" #include "relativepointer.h" #include "server_decoration.h" #include "slide.h" #include "shell.h" #include "shm_pool.h" #include "subcompositor.h" #include "textinput_p.h" #include "xdgshell.h" #include "xdgshell_p.h" #include "wayland_pointer_p.h" #include "xdgforeign_v2.h" #include "appmenu.h" #include "server_decoration_palette.h" #include "xdgoutput.h" #include "xdgdecoration.h" // Qt #include // wayland #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../compat/wayland-xdg-shell-v5-client-protocol.h" #include #include #include #include #include #include #include #include #include #include #include /***** * How to add another interface: * * define a new enum value in Registry::Interface * * define the bind method * * define the create method * * define the Announced signal * * define the Removed signal * * add a block to s_interfaces * * add the BIND macro for the new bind * * add the CREATE macro for the new create * * extend registry unit test to verify that it works ****/ namespace KWayland { namespace Client { namespace { struct SuppertedInterfaceData { quint32 maxVersion; QByteArray name; const wl_interface *interface; void (Registry::*announcedSignal)(quint32, quint32); void (Registry::*removedSignal)(quint32); }; static const QMap s_interfaces = { {Registry::Interface::Compositor, { 4, QByteArrayLiteral("wl_compositor"), &wl_compositor_interface, &Registry::compositorAnnounced, &Registry::compositorRemoved }}, {Registry::Interface::DataDeviceManager, { 3, QByteArrayLiteral("wl_data_device_manager"), &wl_data_device_manager_interface, &Registry::dataDeviceManagerAnnounced, &Registry::dataDeviceManagerRemoved }}, {Registry::Interface::Output, { 3, QByteArrayLiteral("wl_output"), &wl_output_interface, &Registry::outputAnnounced, &Registry::outputRemoved }}, {Registry::Interface::Shm, { 1, QByteArrayLiteral("wl_shm"), &wl_shm_interface, &Registry::shmAnnounced, &Registry::shmRemoved }}, {Registry::Interface::Seat, { 5, QByteArrayLiteral("wl_seat"), &wl_seat_interface, &Registry::seatAnnounced, &Registry::seatRemoved }}, {Registry::Interface::Shell, { 1, QByteArrayLiteral("wl_shell"), &wl_shell_interface, &Registry::shellAnnounced, &Registry::shellRemoved }}, {Registry::Interface::SubCompositor, { 1, QByteArrayLiteral("wl_subcompositor"), &wl_subcompositor_interface, &Registry::subCompositorAnnounced, &Registry::subCompositorRemoved }}, {Registry::Interface::PlasmaShell, { 6, QByteArrayLiteral("org_kde_plasma_shell"), &org_kde_plasma_shell_interface, &Registry::plasmaShellAnnounced, &Registry::plasmaShellRemoved }}, {Registry::Interface::PlasmaVirtualDesktopManagement, { 2, QByteArrayLiteral("org_kde_plasma_virtual_desktop_management"), &org_kde_plasma_virtual_desktop_management_interface, &Registry::plasmaVirtualDesktopManagementAnnounced, &Registry::plasmaVirtualDesktopManagementRemoved }}, {Registry::Interface::PlasmaWindowManagement, { 9, QByteArrayLiteral("org_kde_plasma_window_management"), &org_kde_plasma_window_management_interface, &Registry::plasmaWindowManagementAnnounced, &Registry::plasmaWindowManagementRemoved }}, {Registry::Interface::Idle, { 1, QByteArrayLiteral("org_kde_kwin_idle"), &org_kde_kwin_idle_interface, &Registry::idleAnnounced, &Registry::idleRemoved }}, {Registry::Interface::RemoteAccessManager, { 1, QByteArrayLiteral("org_kde_kwin_remote_access_manager"), &org_kde_kwin_remote_access_manager_interface, &Registry::remoteAccessManagerAnnounced, &Registry::remoteAccessManagerRemoved }}, {Registry::Interface::FakeInput, { 4, QByteArrayLiteral("org_kde_kwin_fake_input"), &org_kde_kwin_fake_input_interface, &Registry::fakeInputAnnounced, &Registry::fakeInputRemoved }}, {Registry::Interface::OutputManagement, { 2, QByteArrayLiteral("org_kde_kwin_outputmanagement"), &org_kde_kwin_outputmanagement_interface, &Registry::outputManagementAnnounced, &Registry::outputManagementRemoved }}, {Registry::Interface::OutputDevice, { 2, QByteArrayLiteral("org_kde_kwin_outputdevice"), &org_kde_kwin_outputdevice_interface, &Registry::outputDeviceAnnounced, &Registry::outputDeviceRemoved }}, {Registry::Interface::Shadow, { 2, QByteArrayLiteral("org_kde_kwin_shadow_manager"), &org_kde_kwin_shadow_manager_interface, &Registry::shadowAnnounced, &Registry::shadowRemoved }}, {Registry::Interface::Blur, { 1, QByteArrayLiteral("org_kde_kwin_blur_manager"), &org_kde_kwin_blur_manager_interface, &Registry::blurAnnounced, &Registry::blurRemoved }}, {Registry::Interface::Contrast, { 1, QByteArrayLiteral("org_kde_kwin_contrast_manager"), &org_kde_kwin_contrast_manager_interface, &Registry::contrastAnnounced, &Registry::contrastRemoved }}, {Registry::Interface::Slide, { 1, QByteArrayLiteral("org_kde_kwin_slide_manager"), &org_kde_kwin_slide_manager_interface, &Registry::slideAnnounced, &Registry::slideRemoved }}, {Registry::Interface::FullscreenShell, { 1, QByteArrayLiteral("_wl_fullscreen_shell"), &_wl_fullscreen_shell_interface, &Registry::fullscreenShellAnnounced, &Registry::fullscreenShellRemoved }}, {Registry::Interface::Dpms, { 1, QByteArrayLiteral("org_kde_kwin_dpms_manager"), &org_kde_kwin_dpms_manager_interface, &Registry::dpmsAnnounced, &Registry::dpmsRemoved }}, {Registry::Interface::ServerSideDecorationManager, { 1, QByteArrayLiteral("org_kde_kwin_server_decoration_manager"), &org_kde_kwin_server_decoration_manager_interface, &Registry::serverSideDecorationManagerAnnounced, &Registry::serverSideDecorationManagerRemoved }}, {Registry::Interface::TextInputManagerUnstableV0, { 1, QByteArrayLiteral("wl_text_input_manager"), &wl_text_input_manager_interface, &Registry::textInputManagerUnstableV0Announced, &Registry::textInputManagerUnstableV0Removed }}, {Registry::Interface::TextInputManagerUnstableV2, { 1, QByteArrayLiteral("zwp_text_input_manager_v2"), &zwp_text_input_manager_v2_interface, &Registry::textInputManagerUnstableV2Announced, &Registry::textInputManagerUnstableV2Removed }}, {Registry::Interface::XdgShellUnstableV5, { 1, QByteArrayLiteral("xdg_shell"), &zxdg_shell_v5_interface, &Registry::xdgShellUnstableV5Announced, &Registry::xdgShellUnstableV5Removed }}, {Registry::Interface::RelativePointerManagerUnstableV1, { 1, QByteArrayLiteral("zwp_relative_pointer_manager_v1"), &zwp_relative_pointer_manager_v1_interface, &Registry::relativePointerManagerUnstableV1Announced, &Registry::relativePointerManagerUnstableV1Removed }}, {Registry::Interface::PointerGesturesUnstableV1, { 1, QByteArrayLiteral("zwp_pointer_gestures_v1"), &zwp_pointer_gestures_v1_interface, &Registry::pointerGesturesUnstableV1Announced, &Registry::pointerGesturesUnstableV1Removed }}, {Registry::Interface::PointerConstraintsUnstableV1, { 1, QByteArrayLiteral("zwp_pointer_constraints_v1"), &zwp_pointer_constraints_v1_interface, &Registry::pointerConstraintsUnstableV1Announced, &Registry::pointerConstraintsUnstableV1Removed }}, {Registry::Interface::XdgExporterUnstableV2, { 1, QByteArrayLiteral("zxdg_exporter_v2"), &zxdg_exporter_v2_interface, &Registry::exporterUnstableV2Announced, &Registry::exporterUnstableV2Removed }}, {Registry::Interface::XdgImporterUnstableV2, { 1, QByteArrayLiteral("zxdg_importer_v2"), &zxdg_importer_v2_interface, &Registry::importerUnstableV2Announced, &Registry::importerUnstableV2Removed }}, {Registry::Interface::XdgShellUnstableV6, { 1, QByteArrayLiteral("zxdg_shell_v6"), &zxdg_shell_v6_interface, &Registry::xdgShellUnstableV6Announced, &Registry::xdgShellUnstableV6Removed }}, {Registry::Interface::IdleInhibitManagerUnstableV1, { 1, QByteArrayLiteral("zwp_idle_inhibit_manager_v1"), &zwp_idle_inhibit_manager_v1_interface, &Registry::idleInhibitManagerUnstableV1Announced, &Registry::idleInhibitManagerUnstableV1Removed }}, {Registry::Interface::AppMenu, { 1, QByteArrayLiteral("org_kde_kwin_appmenu_manager"), &org_kde_kwin_appmenu_manager_interface, &Registry::appMenuAnnounced, &Registry::appMenuRemoved }}, {Registry::Interface::ServerSideDecorationPalette, { 1, QByteArrayLiteral("org_kde_kwin_server_decoration_palette_manager"), &org_kde_kwin_server_decoration_palette_manager_interface, &Registry::serverSideDecorationPaletteManagerAnnounced, &Registry::serverSideDecorationPaletteManagerRemoved }}, {Registry::Interface::XdgOutputUnstableV1, { 1, QByteArrayLiteral("zxdg_output_manager_v1"), &zxdg_output_manager_v1_interface, &Registry::xdgOutputAnnounced, &Registry::xdgOutputRemoved }}, {Registry::Interface::XdgShellStable, { 1, QByteArrayLiteral("xdg_wm_base"), &xdg_wm_base_interface, &Registry::xdgShellStableAnnounced, &Registry::xdgShellStableRemoved }}, {Registry::Interface::XdgDecorationUnstableV1, { 1, QByteArrayLiteral("zxdg_decoration_manager_v1"), &zxdg_decoration_manager_v1_interface, &Registry::xdgDecorationAnnounced, &Registry::xdgDecorationRemoved }}, {Registry::Interface::Keystate, { 1, QByteArrayLiteral("org_kde_kwin_keystate"), &org_kde_kwin_keystate_interface, &Registry::keystateAnnounced, &Registry::keystateRemoved }} }; static quint32 maxVersion(const Registry::Interface &interface) { auto it = s_interfaces.find(interface); if (it != s_interfaces.end()) { return it.value().maxVersion; } return 0; } } class Q_DECL_HIDDEN Registry::Private { public: Private(Registry *q); void setup(); bool hasInterface(Interface interface) const; AnnouncedInterface interface(Interface interface) const; QVector interfaces(Interface interface) const; Interface interfaceForName(quint32 name) const; template T *bind(Interface interface, uint32_t name, uint32_t version) const; template T *create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const); WaylandPointer registry; static const struct wl_callback_listener s_callbackListener; WaylandPointer callback; EventQueue *queue = nullptr; private: void handleAnnounce(uint32_t name, const char *interface, uint32_t version); void handleRemove(uint32_t name); void handleGlobalSync(); static void globalAnnounce(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version); static void globalRemove(void *data, struct wl_registry *registry, uint32_t name); static void globalSync(void *data, struct wl_callback *callback, uint32_t serial); Registry *q; struct InterfaceData { Interface interface; uint32_t name; uint32_t version; }; QList m_interfaces; static const struct wl_registry_listener s_registryListener; }; Registry::Private::Private(Registry *q) : q(q) { } void Registry::Private::setup() { wl_registry_add_listener(registry, &s_registryListener, this); wl_callback_add_listener(callback, &s_callbackListener, this); } Registry::Registry(QObject *parent) : QObject(parent) , d(new Private(this)) { } Registry::~Registry() { release(); } void Registry::release() { d->registry.release(); d->callback.release(); } void Registry::destroy() { emit registryDestroyed(); d->registry.destroy(); d->callback.destroy(); } void Registry::create(wl_display *display) { Q_ASSERT(display); Q_ASSERT(!isValid()); d->registry.setup(wl_display_get_registry(display)); d->callback.setup(wl_display_sync(display)); if (d->queue) { d->queue->addProxy(d->registry); d->queue->addProxy(d->callback); } } void Registry::create(ConnectionThread *connection) { create(connection->display()); connect(connection, &ConnectionThread::connectionDied, this, &Registry::destroy); } void Registry::setup() { Q_ASSERT(isValid()); d->setup(); } void Registry::setEventQueue(EventQueue *queue) { d->queue = queue; if (!queue) { return; } if (d->registry) { d->queue->addProxy(d->registry); } if (d->callback) { d->queue->addProxy(d->callback); } } EventQueue *Registry::eventQueue() { return d->queue; } #ifndef K_DOXYGEN const struct wl_registry_listener Registry::Private::s_registryListener = { globalAnnounce, globalRemove }; const struct wl_callback_listener Registry::Private::s_callbackListener = { globalSync }; #endif void Registry::Private::globalAnnounce(void *data, wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { auto r = reinterpret_cast(data); Q_ASSERT(registry == r->registry); r->handleAnnounce(name, interface, version); } void Registry::Private::globalRemove(void *data, wl_registry *registry, uint32_t name) { auto r = reinterpret_cast(data); Q_ASSERT(registry == r->registry); r->handleRemove(name); } void Registry::Private::globalSync(void* data, wl_callback* callback, uint32_t serial) { Q_UNUSED(serial) auto r = reinterpret_cast(data); Q_ASSERT(r->callback == callback); r->handleGlobalSync(); - r->callback.destroy(); + r->callback.release(); } void Registry::Private::handleGlobalSync() { emit q->interfacesAnnounced(); } namespace { static Registry::Interface nameToInterface(const char *interface) { for (auto it = s_interfaces.constBegin(); it != s_interfaces.constEnd(); ++it) { if (qstrcmp(interface, it.value().name) == 0) { return it.key(); } } return Registry::Interface::Unknown; } } void Registry::Private::handleAnnounce(uint32_t name, const char *interface, uint32_t version) { Interface i = nameToInterface(interface); emit q->interfaceAnnounced(QByteArray(interface), name, version); if (i == Interface::Unknown) { qCDebug(KWAYLAND_CLIENT) << "Unknown interface announced: " << interface << "/" << name << "/" << version; return; } qCDebug(KWAYLAND_CLIENT) << "Wayland Interface: " << interface << "/" << name << "/" << version; m_interfaces.append({i, name, version}); auto it = s_interfaces.constFind(i); if (it != s_interfaces.end()) { emit (q->*it.value().announcedSignal)(name, version); } } void Registry::Private::handleRemove(uint32_t name) { auto it = std::find_if(m_interfaces.begin(), m_interfaces.end(), [name](const InterfaceData &data) { return data.name == name; } ); if (it != m_interfaces.end()) { InterfaceData data = *(it); m_interfaces.erase(it); auto sit = s_interfaces.find(data.interface); if (sit != s_interfaces.end()) { emit (q->*sit.value().removedSignal)(data.name); } } emit q->interfaceRemoved(name); } bool Registry::Private::hasInterface(Registry::Interface interface) const { auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [interface](const InterfaceData &data) { return data.interface == interface; } ); return it != m_interfaces.constEnd(); } QVector Registry::Private::interfaces(Interface interface) const { QVector retVal; for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) { const auto &data = *it; if (data.interface == interface) { retVal << AnnouncedInterface{data.name, data.version}; } } return retVal; } Registry::AnnouncedInterface Registry::Private::interface(Interface interface) const { const auto all = interfaces(interface); if (!all.isEmpty()) { return all.last(); } return AnnouncedInterface{0, 0}; } Registry::Interface Registry::Private::interfaceForName(quint32 name) const { auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [name] (const InterfaceData &data) { return data.name == name; }); if (it == m_interfaces.constEnd()) { return Interface::Unknown; } return (*it).interface; } bool Registry::hasInterface(Registry::Interface interface) const { return d->hasInterface(interface); } QVector Registry::interfaces(Interface interface) const { return d->interfaces(interface); } Registry::AnnouncedInterface Registry::interface(Interface interface) const { return d->interface(interface); } #define BIND2(__NAME__, __INAME__, __WL__) \ __WL__ *Registry::bind##__NAME__(uint32_t name, uint32_t version) const \ { \ return d->bind<__WL__>(Interface::__INAME__, name, qMin(maxVersion(Interface::__INAME__), version)); \ } #define BIND(__NAME__, __WL__) BIND2(__NAME__, __NAME__, __WL__) BIND(Compositor, wl_compositor) BIND(Output, wl_output) BIND(Seat, wl_seat) BIND(Shell, wl_shell) BIND(Shm, wl_shm) BIND(SubCompositor, wl_subcompositor) BIND(FullscreenShell, _wl_fullscreen_shell) BIND(DataDeviceManager, wl_data_device_manager) BIND(PlasmaShell, org_kde_plasma_shell) BIND(PlasmaVirtualDesktopManagement, org_kde_plasma_virtual_desktop_management) BIND(PlasmaWindowManagement, org_kde_plasma_window_management) BIND(Idle, org_kde_kwin_idle) BIND(RemoteAccessManager, org_kde_kwin_remote_access_manager) BIND(FakeInput, org_kde_kwin_fake_input) BIND(OutputManagement, org_kde_kwin_outputmanagement) BIND(OutputDevice, org_kde_kwin_outputdevice) BIND(ServerSideDecorationManager, org_kde_kwin_server_decoration_manager) BIND(TextInputManagerUnstableV0, wl_text_input_manager) BIND(TextInputManagerUnstableV2, zwp_text_input_manager_v2) BIND(XdgShellUnstableV5, xdg_shell) BIND(XdgShellUnstableV6, zxdg_shell_v6) BIND(XdgShellStable, xdg_wm_base) BIND(RelativePointerManagerUnstableV1, zwp_relative_pointer_manager_v1) BIND(PointerGesturesUnstableV1, zwp_pointer_gestures_v1) BIND(PointerConstraintsUnstableV1, zwp_pointer_constraints_v1) BIND(XdgExporterUnstableV2, zxdg_exporter_v2) BIND(XdgImporterUnstableV2, zxdg_importer_v2) BIND(IdleInhibitManagerUnstableV1, zwp_idle_inhibit_manager_v1) BIND(Keystate, org_kde_kwin_keystate) BIND2(ShadowManager, Shadow, org_kde_kwin_shadow_manager) BIND2(BlurManager, Blur, org_kde_kwin_blur_manager) BIND2(ContrastManager, Contrast, org_kde_kwin_contrast_manager) BIND2(SlideManager, Slide, org_kde_kwin_slide_manager) BIND2(DpmsManager, Dpms, org_kde_kwin_dpms_manager) BIND2(AppMenuManager, AppMenu, org_kde_kwin_appmenu_manager) BIND2(ServerSideDecorationPaletteManager, ServerSideDecorationPalette, org_kde_kwin_server_decoration_palette_manager) BIND(XdgOutputUnstableV1, zxdg_output_manager_v1) BIND(XdgDecorationUnstableV1, zxdg_decoration_manager_v1) #undef BIND #undef BIND2 template T *Registry::Private::create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const) { T *t = new T(parent); t->setEventQueue(queue); t->setup((q->*bindMethod)(name, version)); QObject::connect(q, &Registry::interfaceRemoved, t, [t, name] (quint32 removed) { if (name == removed) { emit t->removed(); } } ); QObject::connect(q, &Registry::registryDestroyed, t, &T::destroy); return t; } #define CREATE2(__NAME__, __BINDNAME__) \ __NAME__ *Registry::create##__NAME__(quint32 name, quint32 version, QObject *parent) \ { \ return d->create<__NAME__>(name, version, parent, &Registry::bind##__BINDNAME__); \ } #define CREATE(__NAME__) CREATE2(__NAME__, __NAME__) CREATE(Compositor) CREATE(Seat) CREATE(Shell) CREATE(SubCompositor) CREATE(FullscreenShell) CREATE(Output) CREATE(DataDeviceManager) CREATE(PlasmaShell) CREATE(PlasmaVirtualDesktopManagement) CREATE(PlasmaWindowManagement) CREATE(Idle) CREATE(RemoteAccessManager) CREATE(FakeInput) CREATE(OutputManagement) CREATE(OutputDevice) CREATE(ShadowManager) CREATE(BlurManager) CREATE(ContrastManager) CREATE(SlideManager) CREATE(DpmsManager) CREATE(ServerSideDecorationManager) CREATE2(ShmPool, Shm) CREATE(AppMenuManager) CREATE(Keystate) CREATE(ServerSideDecorationPaletteManager) #undef CREATE #undef CREATE2 XdgExporter *Registry::createXdgExporter(quint32 name, quint32 version, QObject *parent) { //only V1 supported for now return d->create(name, version, parent, &Registry::bindXdgExporterUnstableV2); } XdgImporter *Registry::createXdgImporter(quint32 name, quint32 version, QObject *parent) { //only V1 supported for now return d->create(name, version, parent, &Registry::bindXdgImporterUnstableV2); } TextInputManager *Registry::createTextInputManager(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::TextInputManagerUnstableV0: return d->create(name, version, parent, &Registry::bindTextInputManagerUnstableV0); case Interface::TextInputManagerUnstableV2: return d->create(name, version, parent, &Registry::bindTextInputManagerUnstableV2); default: return nullptr; } } XdgShell *Registry::createXdgShell(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::XdgShellUnstableV5: return d->create(name, version, parent, &Registry::bindXdgShellUnstableV5); case Interface::XdgShellUnstableV6: return d->create(name, version, parent, &Registry::bindXdgShellUnstableV6); case Interface::XdgShellStable: return d->create(name, version, parent, &Registry::bindXdgShellStable); default: return nullptr; } } RelativePointerManager *Registry::createRelativePointerManager(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::RelativePointerManagerUnstableV1: return d->create(name, version, parent, &Registry::bindRelativePointerManagerUnstableV1); default: return nullptr; } } PointerGestures *Registry::createPointerGestures(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::PointerGesturesUnstableV1: return d->create(name, version, parent, &Registry::bindPointerGesturesUnstableV1); default: return nullptr; } } PointerConstraints *Registry::createPointerConstraints(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::PointerConstraintsUnstableV1: return d->create(name, version, parent, &Registry::bindPointerConstraintsUnstableV1); default: return nullptr; } } IdleInhibitManager *Registry::createIdleInhibitManager(quint32 name, quint32 version, QObject *parent) { switch (d->interfaceForName(name)) { case Interface::IdleInhibitManagerUnstableV1: return d->create(name, version, parent, &Registry::bindIdleInhibitManagerUnstableV1); default: return nullptr; } } XdgOutputManager *Registry::createXdgOutputManager(quint32 name, quint32 version, QObject *parent) { switch(d->interfaceForName(name)) { case Interface::XdgOutputUnstableV1: return d->create(name, version, parent, &Registry::bindXdgOutputUnstableV1); default: return nullptr; } } XdgDecorationManager *Registry::createXdgDecorationManager(quint32 name, quint32 version, QObject *parent) { switch(d->interfaceForName(name)) { case Interface::XdgDecorationUnstableV1: return d->create(name, version, parent, &Registry::bindXdgDecorationUnstableV1); default: return nullptr; } } namespace { static const wl_interface *wlInterface(Registry::Interface interface) { auto it = s_interfaces.find(interface); if (it != s_interfaces.end()) { return it.value().interface; } return nullptr; } } template T *Registry::Private::bind(Registry::Interface interface, uint32_t name, uint32_t version) const { auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [=](const InterfaceData &data) { return data.interface == interface && data.name == name && data.version >= version; }); if (it == m_interfaces.constEnd()) { qCDebug(KWAYLAND_CLIENT) << "Don't have interface " << int(interface) << "with name " << name << "and minimum version" << version; return nullptr; } auto t = reinterpret_cast(wl_registry_bind(registry, name, wlInterface(interface), version)); if (queue) { queue->addProxy(t); } return t; } bool Registry::isValid() const { return d->registry.isValid(); } wl_registry *Registry::registry() { return d->registry; } Registry::operator wl_registry*() const { return d->registry; } Registry::operator wl_registry*() { return d->registry; } } }