1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7#include "registry.h"
8#include "appmenu.h"
9#include "blur.h"
10#include "compositor.h"
11#include "connection_thread.h"
12#include "contrast.h"
13#include "datadevicemanager.h"
14#include "dpms.h"
15#include "event_queue.h"
16#include "fakeinput.h"
17#include "idleinhibit.h"
18#include "logging.h"
19#include "output.h"
20#include "plasmashell.h"
21#include "plasmavirtualdesktop.h"
22#include "plasmawindowmanagement.h"
23#include "pointerconstraints.h"
24#include "pointergestures.h"
25#include "relativepointer.h"
26#include "seat.h"
27#include "shadow.h"
28#include "shell.h"
29#include "shm_pool.h"
30#include "slide.h"
31#include "subcompositor.h"
32#include "textinput_p.h"
33#include "wayland_pointer_p.h"
34#include "xdgdecoration.h"
35#include "xdgforeign_v2.h"
36#include "xdgoutput.h"
37#include "xdgshell.h"
38#include "xdgshell_p.h"
39// Qt
40#include <QDebug>
41// wayland
42#include "../compat/wayland-xdg-shell-v5-client-protocol.h"
43#include <wayland-appmenu-client-protocol.h>
44#include <wayland-blur-client-protocol.h>
45#include <wayland-client-protocol.h>
46#include <wayland-contrast-client-protocol.h>
47#include <wayland-dpms-client-protocol.h>
48#include <wayland-fake-input-client-protocol.h>
49#include <wayland-idle-inhibit-unstable-v1-client-protocol.h>
50#include <wayland-plasma-shell-client-protocol.h>
51#include <wayland-plasma-virtual-desktop-client-protocol.h>
52#include <wayland-plasma-window-management-client-protocol.h>
53#include <wayland-pointer-constraints-unstable-v1-client-protocol.h>
54#include <wayland-pointer-gestures-unstable-v1-client-protocol.h>
55#include <wayland-relativepointer-unstable-v1-client-protocol.h>
56#include <wayland-shadow-client-protocol.h>
57#include <wayland-slide-client-protocol.h>
58#include <wayland-text-input-v0-client-protocol.h>
59#include <wayland-text-input-v2-client-protocol.h>
60#include <wayland-xdg-decoration-unstable-v1-client-protocol.h>
61#include <wayland-xdg-foreign-unstable-v2-client-protocol.h>
62#include <wayland-xdg-output-unstable-v1-client-protocol.h>
63#include <wayland-xdg-shell-client-protocol.h>
64#include <wayland-xdg-shell-v6-client-protocol.h>
65
66/*****
67 * How to add another interface:
68 * * define a new enum value in Registry::Interface
69 * * define the bind<InterfaceName> method
70 * * define the create<InterfaceName> method
71 * * define the <interfaceName>Announced signal
72 * * define the <interfaceName>Removed signal
73 * * add a block to s_interfaces
74 * * add the BIND macro for the new bind<InterfaceName>
75 * * add the CREATE macro for the new create<InterfaceName>
76 * * extend registry unit test to verify that it works
77 ****/
78
79namespace KWayland
80{
81namespace Client
82{
83namespace
84{
85struct SuppertedInterfaceData {
86 quint32 maxVersion;
87 QByteArray name;
88 const wl_interface *interface;
89 void (Registry::*announcedSignal)(quint32, quint32);
90 void (Registry::*removedSignal)(quint32);
91};
92// clang-format off
93static const QMap<Registry::Interface, SuppertedInterfaceData> s_interfaces = {
94 {Registry::Interface::Compositor, {
95 .maxVersion: 4,
96 QByteArrayLiteral("wl_compositor"),
97 .interface: &wl_compositor_interface,
98 .announcedSignal: &Registry::compositorAnnounced,
99 .removedSignal: &Registry::compositorRemoved
100 }},
101 {Registry::Interface::DataDeviceManager, {
102 .maxVersion: 3,
103 QByteArrayLiteral("wl_data_device_manager"),
104 .interface: &wl_data_device_manager_interface,
105 .announcedSignal: &Registry::dataDeviceManagerAnnounced,
106 .removedSignal: &Registry::dataDeviceManagerRemoved
107 }},
108 {Registry::Interface::Output, {
109 .maxVersion: 4,
110 QByteArrayLiteral("wl_output"),
111 .interface: &wl_output_interface,
112 .announcedSignal: &Registry::outputAnnounced,
113 .removedSignal: &Registry::outputRemoved
114 }},
115 {Registry::Interface::Shm, {
116 .maxVersion: 1,
117 QByteArrayLiteral("wl_shm"),
118 .interface: &wl_shm_interface,
119 .announcedSignal: &Registry::shmAnnounced,
120 .removedSignal: &Registry::shmRemoved
121 }},
122 {Registry::Interface::Seat, {
123 .maxVersion: 5,
124 QByteArrayLiteral("wl_seat"),
125 .interface: &wl_seat_interface,
126 .announcedSignal: &Registry::seatAnnounced,
127 .removedSignal: &Registry::seatRemoved
128 }},
129 {Registry::Interface::Shell, {
130 .maxVersion: 1,
131 QByteArrayLiteral("wl_shell"),
132 .interface: &wl_shell_interface,
133 .announcedSignal: &Registry::shellAnnounced,
134 .removedSignal: &Registry::shellRemoved
135 }},
136 {Registry::Interface::SubCompositor, {
137 .maxVersion: 1,
138 QByteArrayLiteral("wl_subcompositor"),
139 .interface: &wl_subcompositor_interface,
140 .announcedSignal: &Registry::subCompositorAnnounced,
141 .removedSignal: &Registry::subCompositorRemoved
142 }},
143 {Registry::Interface::PlasmaShell, {
144 .maxVersion: 8,
145 QByteArrayLiteral("org_kde_plasma_shell"),
146 .interface: &org_kde_plasma_shell_interface,
147 .announcedSignal: &Registry::plasmaShellAnnounced,
148 .removedSignal: &Registry::plasmaShellRemoved
149 }},
150 {Registry::Interface::PlasmaVirtualDesktopManagement, {
151 .maxVersion: 2,
152 QByteArrayLiteral("org_kde_plasma_virtual_desktop_management"),
153 .interface: &org_kde_plasma_virtual_desktop_management_interface,
154 .announcedSignal: &Registry::plasmaVirtualDesktopManagementAnnounced,
155 .removedSignal: &Registry::plasmaVirtualDesktopManagementRemoved
156 }},
157 {Registry::Interface::PlasmaWindowManagement, {
158 .maxVersion: 16,
159 QByteArrayLiteral("org_kde_plasma_window_management"),
160 .interface: &org_kde_plasma_window_management_interface,
161 .announcedSignal: &Registry::plasmaWindowManagementAnnounced,
162 .removedSignal: &Registry::plasmaWindowManagementRemoved
163 }},
164 {Registry::Interface::FakeInput, {
165 .maxVersion: 4,
166 QByteArrayLiteral("org_kde_kwin_fake_input"),
167 .interface: &org_kde_kwin_fake_input_interface,
168 .announcedSignal: &Registry::fakeInputAnnounced,
169 .removedSignal: &Registry::fakeInputRemoved
170 }},
171 {Registry::Interface::Shadow, {
172 .maxVersion: 2,
173 QByteArrayLiteral("org_kde_kwin_shadow_manager"),
174 .interface: &org_kde_kwin_shadow_manager_interface,
175 .announcedSignal: &Registry::shadowAnnounced,
176 .removedSignal: &Registry::shadowRemoved
177 }},
178 {Registry::Interface::Blur, {
179 .maxVersion: 1,
180 QByteArrayLiteral("org_kde_kwin_blur_manager"),
181 .interface: &org_kde_kwin_blur_manager_interface,
182 .announcedSignal: &Registry::blurAnnounced,
183 .removedSignal: &Registry::blurRemoved
184 }},
185 {Registry::Interface::Contrast, {
186 .maxVersion: 2,
187 QByteArrayLiteral("org_kde_kwin_contrast_manager"),
188 .interface: &org_kde_kwin_contrast_manager_interface,
189 .announcedSignal: &Registry::contrastAnnounced,
190 .removedSignal: &Registry::contrastRemoved
191 }},
192 {Registry::Interface::Slide, {
193 .maxVersion: 1,
194 QByteArrayLiteral("org_kde_kwin_slide_manager"),
195 .interface: &org_kde_kwin_slide_manager_interface,
196 .announcedSignal: &Registry::slideAnnounced,
197 .removedSignal: &Registry::slideRemoved
198 }},
199 {Registry::Interface::Dpms, {
200 .maxVersion: 1,
201 QByteArrayLiteral("org_kde_kwin_dpms_manager"),
202 .interface: &org_kde_kwin_dpms_manager_interface,
203 .announcedSignal: &Registry::dpmsAnnounced,
204 .removedSignal: &Registry::dpmsRemoved
205 }},
206 {Registry::Interface::TextInputManagerUnstableV0, {
207 .maxVersion: 1,
208 QByteArrayLiteral("wl_text_input_manager"),
209 .interface: &wl_text_input_manager_interface,
210 .announcedSignal: &Registry::textInputManagerUnstableV0Announced,
211 .removedSignal: &Registry::textInputManagerUnstableV0Removed
212 }},
213 {Registry::Interface::TextInputManagerUnstableV2, {
214 .maxVersion: 1,
215 QByteArrayLiteral("zwp_text_input_manager_v2"),
216 .interface: &zwp_text_input_manager_v2_interface,
217 .announcedSignal: &Registry::textInputManagerUnstableV2Announced,
218 .removedSignal: &Registry::textInputManagerUnstableV2Removed
219 }},
220 {Registry::Interface::XdgShellUnstableV5, {
221 .maxVersion: 1,
222 QByteArrayLiteral("xdg_shell"),
223 .interface: &zxdg_shell_v5_interface,
224 .announcedSignal: &Registry::xdgShellUnstableV5Announced,
225 .removedSignal: &Registry::xdgShellUnstableV5Removed
226 }},
227 {Registry::Interface::RelativePointerManagerUnstableV1, {
228 .maxVersion: 1,
229 QByteArrayLiteral("zwp_relative_pointer_manager_v1"),
230 .interface: &zwp_relative_pointer_manager_v1_interface,
231 .announcedSignal: &Registry::relativePointerManagerUnstableV1Announced,
232 .removedSignal: &Registry::relativePointerManagerUnstableV1Removed
233 }},
234 {Registry::Interface::PointerGesturesUnstableV1, {
235 .maxVersion: 1,
236 QByteArrayLiteral("zwp_pointer_gestures_v1"),
237 .interface: &zwp_pointer_gestures_v1_interface,
238 .announcedSignal: &Registry::pointerGesturesUnstableV1Announced,
239 .removedSignal: &Registry::pointerGesturesUnstableV1Removed
240 }},
241 {Registry::Interface::PointerConstraintsUnstableV1, {
242 .maxVersion: 1,
243 QByteArrayLiteral("zwp_pointer_constraints_v1"),
244 .interface: &zwp_pointer_constraints_v1_interface,
245 .announcedSignal: &Registry::pointerConstraintsUnstableV1Announced,
246 .removedSignal: &Registry::pointerConstraintsUnstableV1Removed
247 }},
248 {Registry::Interface::XdgExporterUnstableV2, {
249 .maxVersion: 1,
250 QByteArrayLiteral("zxdg_exporter_v2"),
251 .interface: &zxdg_exporter_v2_interface,
252 .announcedSignal: &Registry::exporterUnstableV2Announced,
253 .removedSignal: &Registry::exporterUnstableV2Removed
254 }},
255 {Registry::Interface::XdgImporterUnstableV2, {
256 .maxVersion: 1,
257 QByteArrayLiteral("zxdg_importer_v2"),
258 .interface: &zxdg_importer_v2_interface,
259 .announcedSignal: &Registry::importerUnstableV2Announced,
260 .removedSignal: &Registry::importerUnstableV2Removed
261 }},
262 {Registry::Interface::XdgShellUnstableV6, {
263 .maxVersion: 1,
264 QByteArrayLiteral("zxdg_shell_v6"),
265 .interface: &zxdg_shell_v6_interface,
266 .announcedSignal: &Registry::xdgShellUnstableV6Announced,
267 .removedSignal: &Registry::xdgShellUnstableV6Removed
268 }},
269 {Registry::Interface::IdleInhibitManagerUnstableV1, {
270 .maxVersion: 1,
271 QByteArrayLiteral("zwp_idle_inhibit_manager_v1"),
272 .interface: &zwp_idle_inhibit_manager_v1_interface,
273 .announcedSignal: &Registry::idleInhibitManagerUnstableV1Announced,
274 .removedSignal: &Registry::idleInhibitManagerUnstableV1Removed
275 }},
276 {Registry::Interface::AppMenu, {
277 .maxVersion: 1,
278 QByteArrayLiteral("org_kde_kwin_appmenu_manager"),
279 .interface: &org_kde_kwin_appmenu_manager_interface,
280 .announcedSignal: &Registry::appMenuAnnounced,
281 .removedSignal: &Registry::appMenuRemoved
282 }},
283 {Registry::Interface::XdgOutputUnstableV1, {
284 .maxVersion: 2,
285 QByteArrayLiteral("zxdg_output_manager_v1"),
286 .interface: &zxdg_output_manager_v1_interface,
287 .announcedSignal: &Registry::xdgOutputAnnounced,
288 .removedSignal: &Registry::xdgOutputRemoved
289 }},
290 {Registry::Interface::XdgShellStable, {
291 .maxVersion: 1,
292 QByteArrayLiteral("xdg_wm_base"),
293 .interface: &xdg_wm_base_interface,
294 .announcedSignal: &Registry::xdgShellStableAnnounced,
295 .removedSignal: &Registry::xdgShellStableRemoved
296 }},
297 {Registry::Interface::XdgDecorationUnstableV1, {
298 .maxVersion: 1,
299 QByteArrayLiteral("zxdg_decoration_manager_v1"),
300 .interface: &zxdg_decoration_manager_v1_interface,
301 .announcedSignal: &Registry::xdgDecorationAnnounced,
302 .removedSignal: &Registry::xdgDecorationRemoved
303 }},
304 {Registry::Interface::PlasmaActivationFeedback, {
305 .maxVersion: 1,
306 QByteArrayLiteral("org_kde_plasma_activation_feedback"),
307 .interface: &org_kde_plasma_activation_feedback_interface,
308 .announcedSignal: &Registry::plasmaActivationFeedbackAnnounced,
309 .removedSignal: &Registry::plasmaActivationFeedbackRemoved
310 }},
311};
312// clang-format on
313
314static quint32 maxVersion(const Registry::Interface &interface)
315{
316 auto it = s_interfaces.find(key: interface);
317 if (it != s_interfaces.end()) {
318 return it.value().maxVersion;
319 }
320 return 0;
321}
322}
323
324class Q_DECL_HIDDEN Registry::Private
325{
326public:
327 Private(Registry *q);
328 void setup();
329 bool hasInterface(Interface interface) const;
330 AnnouncedInterface interface(Interface interface) const;
331 QList<AnnouncedInterface> interfaces(Interface interface) const;
332 Interface interfaceForName(quint32 name) const;
333 template<typename T>
334 T *bind(Interface interface, uint32_t name, uint32_t version) const;
335 template<class T, typename WL>
336 T *create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const);
337
338 WaylandPointer<wl_registry, wl_registry_destroy> registry;
339 static const struct wl_callback_listener s_callbackListener;
340 WaylandPointer<wl_callback, wl_callback_destroy> callback;
341 EventQueue *queue = nullptr;
342
343private:
344 void handleAnnounce(uint32_t name, const char *interface, uint32_t version);
345 void handleRemove(uint32_t name);
346 void handleGlobalSync();
347 static void globalAnnounce(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version);
348 static void globalRemove(void *data, struct wl_registry *registry, uint32_t name);
349 static void globalSync(void *data, struct wl_callback *callback, uint32_t serial);
350
351 Registry *q;
352 struct InterfaceData {
353 Interface interface;
354 uint32_t name;
355 uint32_t version;
356 };
357 QList<InterfaceData> m_interfaces;
358 static const struct wl_registry_listener s_registryListener;
359};
360
361Registry::Private::Private(Registry *q)
362 : q(q)
363{
364}
365
366void Registry::Private::setup()
367{
368 wl_registry_add_listener(wl_registry: registry, listener: &s_registryListener, data: this);
369 wl_callback_add_listener(wl_callback: callback, listener: &s_callbackListener, data: this);
370}
371
372Registry::Registry(QObject *parent)
373 : QObject(parent)
374 , d(new Private(this))
375{
376}
377
378Registry::~Registry()
379{
380 release();
381}
382
383void Registry::release()
384{
385 d->registry.release();
386 d->callback.release();
387}
388
389void Registry::destroy()
390{
391 Q_EMIT registryDestroyed();
392 d->registry.destroy();
393 d->callback.destroy();
394}
395
396void Registry::create(wl_display *display)
397{
398 Q_ASSERT(display);
399 Q_ASSERT(!isValid());
400 d->registry.setup(pointer: wl_display_get_registry(wl_display: display));
401 d->callback.setup(pointer: wl_display_sync(wl_display: display));
402 if (d->queue) {
403 d->queue->addProxy(proxy: d->registry);
404 d->queue->addProxy(proxy: d->callback);
405 }
406}
407
408void Registry::create(ConnectionThread *connection)
409{
410 create(display: connection->display());
411 connect(sender: connection, signal: &ConnectionThread::connectionDied, context: this, slot: &Registry::destroy);
412}
413
414void Registry::setup()
415{
416 Q_ASSERT(isValid());
417 d->setup();
418}
419
420void Registry::setEventQueue(EventQueue *queue)
421{
422 d->queue = queue;
423 if (!queue) {
424 return;
425 }
426 if (d->registry) {
427 d->queue->addProxy(proxy: d->registry);
428 }
429 if (d->callback) {
430 d->queue->addProxy(proxy: d->callback);
431 }
432}
433
434EventQueue *Registry::eventQueue()
435{
436 return d->queue;
437}
438
439#ifndef K_DOXYGEN
440const struct wl_registry_listener Registry::Private::s_registryListener = {.global: globalAnnounce, .global_remove: globalRemove};
441
442const struct wl_callback_listener Registry::Private::s_callbackListener = {.done: globalSync};
443#endif
444
445void Registry::Private::globalAnnounce(void *data, wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
446{
447 auto r = reinterpret_cast<Registry::Private *>(data);
448 Q_ASSERT(registry == r->registry);
449 r->handleAnnounce(name, interface, version);
450}
451
452void Registry::Private::globalRemove(void *data, wl_registry *registry, uint32_t name)
453{
454 auto r = reinterpret_cast<Registry::Private *>(data);
455 Q_ASSERT(registry == r->registry);
456 r->handleRemove(name);
457}
458
459void Registry::Private::globalSync(void *data, wl_callback *callback, uint32_t serial)
460{
461 Q_UNUSED(serial)
462 auto r = reinterpret_cast<Registry::Private *>(data);
463 Q_ASSERT(r->callback == callback);
464 r->handleGlobalSync();
465 r->callback.release();
466}
467
468void Registry::Private::handleGlobalSync()
469{
470 Q_EMIT q->interfacesAnnounced();
471}
472
473namespace
474{
475static Registry::Interface nameToInterface(const char *interface)
476{
477 for (auto it = s_interfaces.constBegin(); it != s_interfaces.constEnd(); ++it) {
478 if (qstrcmp(str1: interface, str2: it.value().name) == 0) {
479 return it.key();
480 }
481 }
482 return Registry::Interface::Unknown;
483}
484}
485
486void Registry::Private::handleAnnounce(uint32_t name, const char *interface, uint32_t version)
487{
488 Interface i = nameToInterface(interface);
489 Q_EMIT q->interfaceAnnounced(interface: QByteArray(interface), name, version);
490 if (i == Interface::Unknown) {
491 qCDebug(KWAYLAND_CLIENT) << "Unknown interface announced: " << interface << "/" << name << "/" << version;
492 return;
493 }
494 qCDebug(KWAYLAND_CLIENT) << "Wayland Interface: " << interface << "/" << name << "/" << version;
495 m_interfaces.append(t: {.interface: i, .name: name, .version: version});
496 auto it = s_interfaces.constFind(key: i);
497 if (it != s_interfaces.end()) {
498 Q_EMIT(q->*it.value().announcedSignal)(name, version);
499 }
500}
501
502void Registry::Private::handleRemove(uint32_t name)
503{
504 auto it = std::find_if(first: m_interfaces.begin(), last: m_interfaces.end(), pred: [name](const InterfaceData &data) {
505 return data.name == name;
506 });
507 if (it != m_interfaces.end()) {
508 InterfaceData data = *(it);
509 m_interfaces.erase(pos: it);
510 auto sit = s_interfaces.find(key: data.interface);
511 if (sit != s_interfaces.end()) {
512 Q_EMIT(q->*sit.value().removedSignal)(data.name);
513 }
514 }
515 Q_EMIT q->interfaceRemoved(name);
516}
517
518bool Registry::Private::hasInterface(Registry::Interface interface) const
519{
520 auto it = std::find_if(first: m_interfaces.constBegin(), last: m_interfaces.constEnd(), pred: [interface](const InterfaceData &data) {
521 return data.interface == interface;
522 });
523 return it != m_interfaces.constEnd();
524}
525
526QList<Registry::AnnouncedInterface> Registry::Private::interfaces(Interface interface) const
527{
528 QList<Registry::AnnouncedInterface> retVal;
529 for (auto it = m_interfaces.constBegin(); it != m_interfaces.constEnd(); ++it) {
530 const auto &data = *it;
531 if (data.interface == interface) {
532 retVal << AnnouncedInterface{.name: data.name, .version: data.version};
533 }
534 }
535 return retVal;
536}
537
538Registry::AnnouncedInterface Registry::Private::interface(Interface interface) const
539{
540 const auto all = interfaces(interface);
541 if (!all.isEmpty()) {
542 return all.last();
543 }
544 return AnnouncedInterface{.name: 0, .version: 0};
545}
546
547Registry::Interface Registry::Private::interfaceForName(quint32 name) const
548{
549 auto it = std::find_if(first: m_interfaces.constBegin(), last: m_interfaces.constEnd(), pred: [name](const InterfaceData &data) {
550 return data.name == name;
551 });
552 if (it == m_interfaces.constEnd()) {
553 return Interface::Unknown;
554 }
555 return (*it).interface;
556}
557
558bool Registry::hasInterface(Registry::Interface interface) const
559{
560 return d->hasInterface(interface);
561}
562
563QList<Registry::AnnouncedInterface> Registry::interfaces(Interface interface) const
564{
565 return d->interfaces(interface);
566}
567
568Registry::AnnouncedInterface Registry::interface(Interface interface) const
569{
570 return d->interface(interface);
571}
572
573// clang-format off
574#define BIND2(__NAME__, __INAME__, __WL__) \
575__WL__ *Registry::bind##__NAME__(uint32_t name, uint32_t version) const \
576{ \
577 return d->bind<__WL__>(Interface::__INAME__, name, qMin(maxVersion(Interface::__INAME__), version)); \
578}
579
580#define BIND(__NAME__, __WL__) BIND2(__NAME__, __NAME__, __WL__)
581// clang-format on
582
583BIND(Compositor, wl_compositor)
584BIND(Output, wl_output)
585BIND(Seat, wl_seat)
586BIND(Shell, wl_shell)
587BIND(Shm, wl_shm)
588BIND(SubCompositor, wl_subcompositor)
589BIND(DataDeviceManager, wl_data_device_manager)
590BIND(PlasmaShell, org_kde_plasma_shell)
591BIND(PlasmaActivationFeedback, org_kde_plasma_activation_feedback)
592BIND(PlasmaVirtualDesktopManagement, org_kde_plasma_virtual_desktop_management)
593BIND(PlasmaWindowManagement, org_kde_plasma_window_management)
594BIND(FakeInput, org_kde_kwin_fake_input)
595BIND(TextInputManagerUnstableV0, wl_text_input_manager)
596BIND(TextInputManagerUnstableV2, zwp_text_input_manager_v2)
597BIND(XdgShellUnstableV5, xdg_shell)
598BIND(XdgShellUnstableV6, zxdg_shell_v6)
599BIND(XdgShellStable, xdg_wm_base)
600BIND(RelativePointerManagerUnstableV1, zwp_relative_pointer_manager_v1)
601BIND(PointerGesturesUnstableV1, zwp_pointer_gestures_v1)
602BIND(PointerConstraintsUnstableV1, zwp_pointer_constraints_v1)
603BIND(XdgExporterUnstableV2, zxdg_exporter_v2)
604BIND(XdgImporterUnstableV2, zxdg_importer_v2)
605BIND(IdleInhibitManagerUnstableV1, zwp_idle_inhibit_manager_v1)
606BIND2(ShadowManager, Shadow, org_kde_kwin_shadow_manager)
607BIND2(BlurManager, Blur, org_kde_kwin_blur_manager)
608BIND2(ContrastManager, Contrast, org_kde_kwin_contrast_manager)
609BIND2(SlideManager, Slide, org_kde_kwin_slide_manager)
610BIND2(DpmsManager, Dpms, org_kde_kwin_dpms_manager)
611BIND2(AppMenuManager, AppMenu, org_kde_kwin_appmenu_manager)
612BIND(XdgOutputUnstableV1, zxdg_output_manager_v1)
613BIND(XdgDecorationUnstableV1, zxdg_decoration_manager_v1)
614
615#undef BIND
616#undef BIND2
617
618template<class T, typename WL>
619T *Registry::Private::create(quint32 name, quint32 version, QObject *parent, WL *(Registry::*bindMethod)(uint32_t, uint32_t) const)
620{
621 T *t = new T(parent);
622 t->setEventQueue(queue);
623 t->setup((q->*bindMethod)(name, version));
624 QObject::connect(q, &Registry::interfaceRemoved, t, [t, name](quint32 removed) {
625 if (name == removed) {
626 Q_EMIT t->removed();
627 }
628 });
629 QObject::connect(q, &Registry::registryDestroyed, t, &T::destroy);
630 return t;
631}
632
633// clang-format off
634#define CREATE2(__NAME__, __BINDNAME__) \
635__NAME__ *Registry::create##__NAME__(quint32 name, quint32 version, QObject *parent) \
636{ \
637 return d->create<__NAME__>(name, version, parent, &Registry::bind##__BINDNAME__); \
638}
639
640#define CREATE(__NAME__) CREATE2(__NAME__, __NAME__)
641// clang-format on
642
643CREATE(Compositor)
644CREATE(Seat)
645CREATE(Shell)
646CREATE(SubCompositor)
647CREATE(Output)
648CREATE(DataDeviceManager)
649CREATE(PlasmaShell)
650CREATE(PlasmaActivationFeedback)
651CREATE(PlasmaVirtualDesktopManagement)
652CREATE(PlasmaWindowManagement)
653CREATE(FakeInput)
654CREATE(ShadowManager)
655CREATE(BlurManager)
656CREATE(ContrastManager)
657CREATE(SlideManager)
658CREATE(DpmsManager)
659CREATE2(ShmPool, Shm)
660CREATE(AppMenuManager)
661
662#undef CREATE
663#undef CREATE2
664
665XdgExporter *Registry::createXdgExporter(quint32 name, quint32 version, QObject *parent)
666{
667 // only V1 supported for now
668 return d->create<XdgExporterUnstableV2>(name, version, parent, bindMethod: &Registry::bindXdgExporterUnstableV2);
669}
670
671XdgImporter *Registry::createXdgImporter(quint32 name, quint32 version, QObject *parent)
672{
673 // only V1 supported for now
674 return d->create<XdgImporterUnstableV2>(name, version, parent, bindMethod: &Registry::bindXdgImporterUnstableV2);
675}
676
677TextInputManager *Registry::createTextInputManager(quint32 name, quint32 version, QObject *parent)
678{
679 switch (d->interfaceForName(name)) {
680 case Interface::TextInputManagerUnstableV0:
681 return d->create<TextInputManagerUnstableV0>(name, version, parent, bindMethod: &Registry::bindTextInputManagerUnstableV0);
682 case Interface::TextInputManagerUnstableV2:
683 return d->create<TextInputManagerUnstableV2>(name, version, parent, bindMethod: &Registry::bindTextInputManagerUnstableV2);
684 default:
685 return nullptr;
686 }
687}
688
689XdgShell *Registry::createXdgShell(quint32 name, quint32 version, QObject *parent)
690{
691 switch (d->interfaceForName(name)) {
692 case Interface::XdgShellUnstableV5:
693 return d->create<XdgShellUnstableV5>(name, version, parent, bindMethod: &Registry::bindXdgShellUnstableV5);
694 case Interface::XdgShellUnstableV6:
695 return d->create<XdgShellUnstableV6>(name, version, parent, bindMethod: &Registry::bindXdgShellUnstableV6);
696 case Interface::XdgShellStable:
697 return d->create<XdgShellStable>(name, version, parent, bindMethod: &Registry::bindXdgShellStable);
698 default:
699 return nullptr;
700 }
701}
702
703RelativePointerManager *Registry::createRelativePointerManager(quint32 name, quint32 version, QObject *parent)
704{
705 switch (d->interfaceForName(name)) {
706 case Interface::RelativePointerManagerUnstableV1:
707 return d->create<RelativePointerManager>(name, version, parent, bindMethod: &Registry::bindRelativePointerManagerUnstableV1);
708 default:
709 return nullptr;
710 }
711}
712
713PointerGestures *Registry::createPointerGestures(quint32 name, quint32 version, QObject *parent)
714{
715 switch (d->interfaceForName(name)) {
716 case Interface::PointerGesturesUnstableV1:
717 return d->create<PointerGestures>(name, version, parent, bindMethod: &Registry::bindPointerGesturesUnstableV1);
718 default:
719 return nullptr;
720 }
721}
722
723PointerConstraints *Registry::createPointerConstraints(quint32 name, quint32 version, QObject *parent)
724{
725 switch (d->interfaceForName(name)) {
726 case Interface::PointerConstraintsUnstableV1:
727 return d->create<PointerConstraints>(name, version, parent, bindMethod: &Registry::bindPointerConstraintsUnstableV1);
728 default:
729 return nullptr;
730 }
731}
732
733IdleInhibitManager *Registry::createIdleInhibitManager(quint32 name, quint32 version, QObject *parent)
734{
735 switch (d->interfaceForName(name)) {
736 case Interface::IdleInhibitManagerUnstableV1:
737 return d->create<IdleInhibitManager>(name, version, parent, bindMethod: &Registry::bindIdleInhibitManagerUnstableV1);
738 default:
739 return nullptr;
740 }
741}
742
743XdgOutputManager *Registry::createXdgOutputManager(quint32 name, quint32 version, QObject *parent)
744{
745 switch (d->interfaceForName(name)) {
746 case Interface::XdgOutputUnstableV1:
747 return d->create<XdgOutputManager>(name, version, parent, bindMethod: &Registry::bindXdgOutputUnstableV1);
748 default:
749 return nullptr;
750 }
751}
752
753XdgDecorationManager *Registry::createXdgDecorationManager(quint32 name, quint32 version, QObject *parent)
754{
755 switch (d->interfaceForName(name)) {
756 case Interface::XdgDecorationUnstableV1:
757 return d->create<XdgDecorationManager>(name, version, parent, bindMethod: &Registry::bindXdgDecorationUnstableV1);
758 default:
759 return nullptr;
760 }
761}
762
763namespace
764{
765static const wl_interface *wlInterface(Registry::Interface interface)
766{
767 auto it = s_interfaces.find(key: interface);
768 if (it != s_interfaces.end()) {
769 return it.value().interface;
770 }
771 return nullptr;
772}
773}
774
775template<typename T>
776T *Registry::Private::bind(Registry::Interface interface, uint32_t name, uint32_t version) const
777{
778 auto it = std::find_if(m_interfaces.constBegin(), m_interfaces.constEnd(), [=](const InterfaceData &data) {
779 return data.interface == interface && data.name == name && data.version >= version;
780 });
781 if (it == m_interfaces.constEnd()) {
782 qCDebug(KWAYLAND_CLIENT) << "Don't have interface " << int(interface) << "with name " << name << "and minimum version" << version;
783 return nullptr;
784 }
785 auto t = reinterpret_cast<T *>(wl_registry_bind(wl_registry: registry, name, interface: wlInterface(interface), version));
786 if (queue) {
787 queue->addProxy(t);
788 }
789 return t;
790}
791
792bool Registry::isValid() const
793{
794 return d->registry.isValid();
795}
796
797wl_registry *Registry::registry()
798{
799 return d->registry;
800}
801
802Registry::operator wl_registry *() const
803{
804 return d->registry;
805}
806
807Registry::operator wl_registry *()
808{
809 return d->registry;
810}
811
812}
813}
814
815#include "moc_registry.cpp"
816

source code of kwayland/src/client/registry.cpp