1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
6 
7     SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 #include "kwin_wayland_test.h"
10 #include "abstract_client.h"
11 #include "screenlockerwatcher.h"
12 #include "wayland_server.h"
13 #include "workspace.h"
14 #include "qwayland-input-method-unstable-v1.h"
15 #include "inputmethod.h"
16 
17 #include <KWayland/Client/compositor.h>
18 #include <KWayland/Client/connection_thread.h>
19 #include <KWayland/Client/event_queue.h>
20 #include <KWayland/Client/registry.h>
21 #include <KWayland/Client/plasmashell.h>
22 #include <KWayland/Client/plasmawindowmanagement.h>
23 #include <KWayland/Client/pointerconstraints.h>
24 #include <KWayland/Client/seat.h>
25 #include <KWayland/Client/server_decoration.h>
26 #include <KWayland/Client/shadow.h>
27 #include <KWayland/Client/shm_pool.h>
28 #include <KWayland/Client/output.h>
29 #include <KWayland/Client/subcompositor.h>
30 #include <KWayland/Client/subsurface.h>
31 #include <KWayland/Client/surface.h>
32 #include <KWayland/Client/textinput.h>
33 #include <KWayland/Client/appmenu.h>
34 #include <KWaylandServer/display.h>
35 
36 //screenlocker
37 #include <KScreenLocker/KsldApp>
38 
39 #include <QThread>
40 
41 // system
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <unistd.h>
45 
46 using namespace KWayland::Client;
47 
48 namespace KWin
49 {
50 namespace Test
51 {
52 
~LayerShellV1()53 LayerShellV1::~LayerShellV1()
54 {
55     destroy();
56 }
57 
~LayerSurfaceV1()58 LayerSurfaceV1::~LayerSurfaceV1()
59 {
60     destroy();
61 }
62 
zwlr_layer_surface_v1_configure(uint32_t serial,uint32_t width,uint32_t height)63 void LayerSurfaceV1::zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height)
64 {
65     Q_EMIT configureRequested(serial, QSize(width, height));
66 }
67 
zwlr_layer_surface_v1_closed()68 void LayerSurfaceV1::zwlr_layer_surface_v1_closed()
69 {
70     Q_EMIT closeRequested();
71 }
72 
~XdgShell()73 XdgShell::~XdgShell()
74 {
75     destroy();
76 }
77 
XdgSurface(XdgShell * shell,KWayland::Client::Surface * surface,QObject * parent)78 XdgSurface::XdgSurface(XdgShell *shell, KWayland::Client::Surface *surface, QObject *parent)
79     : QObject(parent)
80     , QtWayland::xdg_surface(shell->get_xdg_surface(*surface))
81     , m_surface(surface)
82 {
83 }
84 
~XdgSurface()85 XdgSurface::~XdgSurface()
86 {
87     destroy();
88 }
89 
surface() const90 KWayland::Client::Surface *XdgSurface::surface() const
91 {
92     return m_surface;
93 }
94 
xdg_surface_configure(uint32_t serial)95 void XdgSurface::xdg_surface_configure(uint32_t serial)
96 {
97     Q_EMIT configureRequested(serial);
98 }
99 
XdgToplevel(XdgSurface * surface,QObject * parent)100 XdgToplevel::XdgToplevel(XdgSurface *surface, QObject *parent)
101     : QObject(parent)
102     , QtWayland::xdg_toplevel(surface->get_toplevel())
103     , m_xdgSurface(surface)
104 {
105 }
106 
~XdgToplevel()107 XdgToplevel::~XdgToplevel()
108 {
109     destroy();
110 }
111 
xdgSurface() const112 XdgSurface *XdgToplevel::xdgSurface() const
113 {
114     return m_xdgSurface.data();
115 }
116 
xdg_toplevel_configure(int32_t width,int32_t height,wl_array * states)117 void XdgToplevel::xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states)
118 {
119     States requestedStates;
120 
121     const uint32_t *stateData = static_cast<const uint32_t *>(states->data);
122     const size_t stateCount = states->size / sizeof(uint32_t);
123 
124     for (size_t i = 0; i < stateCount; ++i) {
125         switch (stateData[i]) {
126         case QtWayland::xdg_toplevel::state_maximized:
127             requestedStates |= State::Maximized;
128             break;
129         case QtWayland::xdg_toplevel::state_fullscreen:
130             requestedStates |= State::Fullscreen;
131             break;
132         case QtWayland::xdg_toplevel::state_resizing:
133             requestedStates |= State::Resizing;
134             break;
135         case QtWayland::xdg_toplevel::state_activated:
136             requestedStates |= State::Activated;
137             break;
138         }
139     }
140 
141     Q_EMIT configureRequested(QSize(width, height), requestedStates);
142 }
143 
xdg_toplevel_close()144 void XdgToplevel::xdg_toplevel_close()
145 {
146     Q_EMIT closeRequested();
147 }
148 
XdgPositioner(XdgShell * shell)149 XdgPositioner::XdgPositioner(XdgShell *shell)
150     : QtWayland::xdg_positioner(shell->create_positioner())
151 {
152 }
153 
~XdgPositioner()154 XdgPositioner::~XdgPositioner()
155 {
156     destroy();
157 }
158 
XdgPopup(XdgSurface * surface,XdgSurface * parentSurface,XdgPositioner * positioner,QObject * parent)159 XdgPopup::XdgPopup(XdgSurface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, QObject *parent)
160     : QObject(parent)
161     , QtWayland::xdg_popup(surface->get_popup(parentSurface->object(), positioner->object()))
162     , m_xdgSurface(surface)
163 {
164 }
165 
~XdgPopup()166 XdgPopup::~XdgPopup()
167 {
168     destroy();
169 }
170 
xdgSurface() const171 XdgSurface *XdgPopup::xdgSurface() const
172 {
173     return m_xdgSurface.data();
174 }
175 
xdg_popup_configure(int32_t x,int32_t y,int32_t width,int32_t height)176 void XdgPopup::xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height)
177 {
178     Q_EMIT configureRequested(QRect(x, y, width, height));
179 }
180 
xdg_popup_popup_done()181 void XdgPopup::xdg_popup_popup_done()
182 {
183     Q_EMIT doneReceived();
184 }
185 
~XdgDecorationManagerV1()186 XdgDecorationManagerV1::~XdgDecorationManagerV1()
187 {
188     destroy();
189 }
190 
XdgToplevelDecorationV1(XdgDecorationManagerV1 * manager,XdgToplevel * toplevel,QObject * parent)191 XdgToplevelDecorationV1::XdgToplevelDecorationV1(XdgDecorationManagerV1 *manager,
192                                                  XdgToplevel *toplevel, QObject *parent)
193     : QObject(parent)
194     , QtWayland::zxdg_toplevel_decoration_v1(manager->get_toplevel_decoration(toplevel->object()))
195 {
196 }
197 
~XdgToplevelDecorationV1()198 XdgToplevelDecorationV1::~XdgToplevelDecorationV1()
199 {
200     destroy();
201 }
202 
zxdg_toplevel_decoration_v1_configure(uint32_t m)203 void XdgToplevelDecorationV1::zxdg_toplevel_decoration_v1_configure(uint32_t m)
204 {
205     Q_EMIT configureRequested(mode(m));
206 }
207 
~IdleInhibitManagerV1()208 IdleInhibitManagerV1::~IdleInhibitManagerV1()
209 {
210     destroy();
211 }
212 
IdleInhibitorV1(IdleInhibitManagerV1 * manager,KWayland::Client::Surface * surface)213 IdleInhibitorV1::IdleInhibitorV1(IdleInhibitManagerV1 *manager, KWayland::Client::Surface *surface)
214     : QtWayland::zwp_idle_inhibitor_v1(manager->create_inhibitor(*surface))
215 {
216 }
217 
~IdleInhibitorV1()218 IdleInhibitorV1::~IdleInhibitorV1()
219 {
220     destroy();
221 }
222 
223 static struct {
224     ConnectionThread *connection = nullptr;
225     EventQueue *queue = nullptr;
226     KWayland::Client::Compositor *compositor = nullptr;
227     SubCompositor *subCompositor = nullptr;
228     ServerSideDecorationManager *decoration = nullptr;
229     ShadowManager *shadowManager = nullptr;
230     XdgShell *xdgShell = nullptr;
231     ShmPool *shm = nullptr;
232     Seat *seat = nullptr;
233     PlasmaShell *plasmaShell = nullptr;
234     PlasmaWindowManagement *windowManagement = nullptr;
235     PointerConstraints *pointerConstraints = nullptr;
236     Registry *registry = nullptr;
237     WaylandOutputManagementV2 *outputManagementV2 = nullptr;
238     QThread *thread = nullptr;
239     QVector<Output*> outputs;
240     QVector<WaylandOutputDeviceV2 *> outputDevicesV2;
241     IdleInhibitManagerV1 *idleInhibitManagerV1 = nullptr;
242     AppMenuManager *appMenu = nullptr;
243     XdgDecorationManagerV1 *xdgDecorationManagerV1 = nullptr;
244     TextInputManager *textInputManager = nullptr;
245     QtWayland::zwp_input_panel_v1 *inputPanelV1 = nullptr;
246     MockInputMethod *inputMethodV1 = nullptr;
247     QtWayland::zwp_input_method_context_v1 *inputMethodContextV1 = nullptr;
248     LayerShellV1 *layerShellV1 = nullptr;
249     TextInputManagerV3 *textInputManagerV3 = nullptr;
250 } s_waylandConnection;
251 
252 class MockInputMethod : public QtWayland::zwp_input_method_v1
253 {
254 public:
255     MockInputMethod(struct wl_registry *registry, int id, int version);
256     ~MockInputMethod();
257 
client() const258     AbstractClient *client() const { return m_client; }
inputPanelSurface() const259     KWayland::Client::Surface *inputPanelSurface() const { return m_inputSurface; }
260 
261 protected:
262     void zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context) override;
263     void zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context) override;
264 
265 private:
266     QPointer<KWayland::Client::Surface> m_inputSurface;
267     QtWayland::zwp_input_panel_surface_v1 *m_inputMethodSurface = nullptr;
268     QPointer<AbstractClient> m_client;
269 };
270 
inputPanelClient()271 AbstractClient *inputPanelClient()
272 {
273     return s_waylandConnection.inputMethodV1->client();
274 }
275 
inputPanelSurface()276 KWayland::Client::Surface *inputPanelSurface()
277 {
278     return s_waylandConnection.inputMethodV1->inputPanelSurface();
279 }
280 
MockInputMethod(struct wl_registry * registry,int id,int version)281 MockInputMethod::MockInputMethod(struct wl_registry *registry, int id, int version)
282     : QtWayland::zwp_input_method_v1(registry, id, version)
283 {
284 
285 }
~MockInputMethod()286 MockInputMethod::~MockInputMethod()
287 {
288 }
289 
zwp_input_method_v1_activate(struct::zwp_input_method_context_v1 * context)290 void MockInputMethod::zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context)
291 {
292     Q_UNUSED(context)
293     if (!m_inputSurface) {
294         m_inputSurface = Test::createSurface();
295         m_inputMethodSurface = Test::createInputPanelSurfaceV1(m_inputSurface, s_waylandConnection.outputs.first());
296     }
297     m_client = Test::renderAndWaitForShown(m_inputSurface, QSize(1280, 400), Qt::blue);
298 }
299 
zwp_input_method_v1_deactivate(struct::zwp_input_method_context_v1 * context)300 void MockInputMethod::zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context)
301 {
302     zwp_input_method_context_v1_destroy(context);
303 
304     if (m_inputSurface) {
305         m_inputSurface->release();
306         m_inputSurface->destroy();
307         delete m_inputSurface;
308         m_inputSurface = nullptr;
309         delete m_inputMethodSurface;
310         m_inputMethodSurface = nullptr;
311     }
312 }
313 
setupWaylandConnection(AdditionalWaylandInterfaces flags)314 bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
315 {
316     if (s_waylandConnection.connection) {
317         return false;
318     }
319 
320     int sx[2];
321     if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
322         return false;
323     }
324     KWin::waylandServer()->display()->createClient(sx[0]);
325     // setup connection
326     s_waylandConnection.connection = new ConnectionThread;
327     QSignalSpy connectedSpy(s_waylandConnection.connection, &ConnectionThread::connected);
328     if (!connectedSpy.isValid()) {
329         return false;
330     }
331     s_waylandConnection.connection->setSocketFd(sx[1]);
332 
333     s_waylandConnection.thread = new QThread(kwinApp());
334     s_waylandConnection.connection->moveToThread(s_waylandConnection.thread);
335     s_waylandConnection.thread->start();
336 
337     s_waylandConnection.connection->initConnection();
338     if (!connectedSpy.wait()) {
339         return false;
340     }
341 
342     s_waylandConnection.queue = new EventQueue;
343     s_waylandConnection.queue->setup(s_waylandConnection.connection);
344     if (!s_waylandConnection.queue->isValid()) {
345         return false;
346     }
347 
348     Registry *registry = new Registry;
349     s_waylandConnection.registry = registry;
350     registry->setEventQueue(s_waylandConnection.queue);
351 
352     QObject::connect(registry, &Registry::outputAnnounced, [=](quint32 name, quint32 version) {
353         Output* output = registry->createOutput(name, version, s_waylandConnection.registry);
354         s_waylandConnection.outputs << output;
355         QObject::connect(output, &Output::removed, [=]() {
356             output->deleteLater();
357             s_waylandConnection.outputs.removeOne(output);
358         });
359         QObject::connect(output, &Output::destroyed, [=]() {
360             s_waylandConnection.outputs.removeOne(output);
361         });
362     });
363 
364     QObject::connect(registry, &Registry::interfaceAnnounced, [=](const QByteArray &interface, quint32 name, quint32 version) {
365         if (flags & AdditionalWaylandInterface::InputMethodV1) {
366             if (interface == QByteArrayLiteral("zwp_input_method_v1")) {
367                 s_waylandConnection.inputMethodV1 = new MockInputMethod(*registry, name, version);
368             } else if (interface == QByteArrayLiteral("zwp_input_panel_v1")) {
369                 s_waylandConnection.inputPanelV1 = new QtWayland::zwp_input_panel_v1(*registry, name, version);
370             }
371         }
372         if (flags & AdditionalWaylandInterface::LayerShellV1) {
373             if (interface == QByteArrayLiteral("zwlr_layer_shell_v1")) {
374                 s_waylandConnection.layerShellV1 = new LayerShellV1();
375                 s_waylandConnection.layerShellV1->init(*registry, name, version);
376             }
377         }
378         if (flags & AdditionalWaylandInterface::TextInputManagerV3) {
379             // do something
380             if (interface == QByteArrayLiteral("zwp_text_input_manager_v3")) {
381                 s_waylandConnection.textInputManagerV3 = new TextInputManagerV3();
382                 s_waylandConnection.textInputManagerV3->init(*registry, name, version);
383             }
384         }
385         if (interface == QByteArrayLiteral("xdg_wm_base")) {
386             s_waylandConnection.xdgShell = new XdgShell();
387             s_waylandConnection.xdgShell->init(*registry, name, version);
388         }
389         if (flags & AdditionalWaylandInterface::XdgDecorationV1) {
390             if (interface == zxdg_decoration_manager_v1_interface.name) {
391                 s_waylandConnection.xdgDecorationManagerV1 = new XdgDecorationManagerV1();
392                 s_waylandConnection.xdgDecorationManagerV1->init(*registry, name, version);
393                 return;
394             }
395         }
396         if (flags & AdditionalWaylandInterface::IdleInhibitV1) {
397             if (interface == zwp_idle_inhibit_manager_v1_interface.name) {
398                 s_waylandConnection.idleInhibitManagerV1 = new IdleInhibitManagerV1();
399                 s_waylandConnection.idleInhibitManagerV1->init(*registry, name, version);
400                 return;
401             }
402         }
403         if (flags & AdditionalWaylandInterface::OutputDeviceV2) {
404             if (interface == kde_output_device_v2_interface.name) {
405                 WaylandOutputDeviceV2 *device = new WaylandOutputDeviceV2(name);
406                 device->init(*registry, name, version);
407 
408                 s_waylandConnection.outputDevicesV2 << device;
409 
410                 QObject::connect(device, &WaylandOutputDeviceV2::destroyed, [=]() {
411                     s_waylandConnection.outputDevicesV2.removeOne(device);
412                     device->deleteLater();
413                 });
414 
415                 QObject::connect(registry, &KWayland::Client::Registry::interfaceRemoved, device, [name, device](const quint32 &interfaceName) {
416                     if (name == interfaceName) {
417                         s_waylandConnection.outputDevicesV2.removeOne(device);
418                         device->deleteLater();
419                     }
420                 });
421 
422                 return;
423             }
424         }
425         if (flags & AdditionalWaylandInterface::OutputManagementV2) {
426             if (interface == kde_output_management_v2_interface.name) {
427                 s_waylandConnection.outputManagementV2 = new WaylandOutputManagementV2(*registry, name, version);
428                 return;
429             }
430         }
431     });
432 
433     QSignalSpy allAnnounced(registry, &Registry::interfacesAnnounced);
434     if (!allAnnounced.isValid()) {
435         return false;
436     }
437     registry->create(s_waylandConnection.connection);
438     if (!registry->isValid()) {
439         return false;
440     }
441     registry->setup();
442     if (!allAnnounced.wait()) {
443         return false;
444     }
445 
446     s_waylandConnection.compositor = registry->createCompositor(registry->interface(Registry::Interface::Compositor).name, registry->interface(Registry::Interface::Compositor).version);
447     if (!s_waylandConnection.compositor->isValid()) {
448         return false;
449     }
450     s_waylandConnection.subCompositor = registry->createSubCompositor(registry->interface(Registry::Interface::SubCompositor).name, registry->interface(Registry::Interface::SubCompositor).version);
451     if (!s_waylandConnection.subCompositor->isValid()) {
452         return false;
453     }
454     s_waylandConnection.shm = registry->createShmPool(registry->interface(Registry::Interface::Shm).name, registry->interface(Registry::Interface::Shm).version);
455     if (!s_waylandConnection.shm->isValid()) {
456         return false;
457     }
458     if (flags.testFlag(AdditionalWaylandInterface::Seat)) {
459         s_waylandConnection.seat = registry->createSeat(registry->interface(Registry::Interface::Seat).name, registry->interface(Registry::Interface::Seat).version);
460         if (!s_waylandConnection.seat->isValid()) {
461             return false;
462         }
463     }
464     if (flags.testFlag(AdditionalWaylandInterface::ShadowManager)) {
465         s_waylandConnection.shadowManager = registry->createShadowManager(registry->interface(Registry::Interface::Shadow).name,
466                                                                           registry->interface(Registry::Interface::Shadow).version);
467         if (!s_waylandConnection.shadowManager->isValid()) {
468             return false;
469         }
470     }
471     if (flags.testFlag(AdditionalWaylandInterface::Decoration)) {
472         s_waylandConnection.decoration = registry->createServerSideDecorationManager(registry->interface(Registry::Interface::ServerSideDecorationManager).name,
473                                                                                     registry->interface(Registry::Interface::ServerSideDecorationManager).version);
474         if (!s_waylandConnection.decoration->isValid()) {
475             return false;
476         }
477     }
478     if (flags.testFlag(AdditionalWaylandInterface::PlasmaShell)) {
479         s_waylandConnection.plasmaShell = registry->createPlasmaShell(registry->interface(Registry::Interface::PlasmaShell).name,
480                                                                      registry->interface(Registry::Interface::PlasmaShell).version);
481         if (!s_waylandConnection.plasmaShell->isValid()) {
482             return false;
483         }
484     }
485     if (flags.testFlag(AdditionalWaylandInterface::WindowManagement)) {
486         s_waylandConnection.windowManagement = registry->createPlasmaWindowManagement(registry->interface(Registry::Interface::PlasmaWindowManagement).name,
487                                                                                      registry->interface(Registry::Interface::PlasmaWindowManagement).version);
488         if (!s_waylandConnection.windowManagement->isValid()) {
489             return false;
490         }
491     }
492     if (flags.testFlag(AdditionalWaylandInterface::PointerConstraints)) {
493         s_waylandConnection.pointerConstraints = registry->createPointerConstraints(registry->interface(Registry::Interface::PointerConstraintsUnstableV1).name,
494                                                                                    registry->interface(Registry::Interface::PointerConstraintsUnstableV1).version);
495         if (!s_waylandConnection.pointerConstraints->isValid()) {
496             return false;
497         }
498     }
499     if (flags.testFlag(AdditionalWaylandInterface::AppMenu)) {
500         s_waylandConnection.appMenu = registry->createAppMenuManager(registry->interface(Registry::Interface::AppMenu).name, registry->interface(Registry::Interface::AppMenu).version);
501         if (!s_waylandConnection.appMenu->isValid()) {
502             return false;
503         }
504     }
505     if (flags.testFlag(AdditionalWaylandInterface::TextInputManagerV2)) {
506         s_waylandConnection.textInputManager = registry->createTextInputManager(registry->interface(Registry::Interface::TextInputManagerUnstableV2).name, registry->interface(Registry::Interface::TextInputManagerUnstableV2).version);
507         if (!s_waylandConnection.textInputManager->isValid()) {
508             return false;
509         }
510     }
511 
512     return true;
513 }
514 
destroyWaylandConnection()515 void destroyWaylandConnection()
516 {
517     delete s_waylandConnection.compositor;
518     s_waylandConnection.compositor = nullptr;
519     delete s_waylandConnection.subCompositor;
520     s_waylandConnection.subCompositor = nullptr;
521     delete s_waylandConnection.windowManagement;
522     s_waylandConnection.windowManagement = nullptr;
523     delete s_waylandConnection.plasmaShell;
524     s_waylandConnection.plasmaShell = nullptr;
525     delete s_waylandConnection.decoration;
526     s_waylandConnection.decoration = nullptr;
527     delete s_waylandConnection.decoration;
528     s_waylandConnection.decoration = nullptr;
529     delete s_waylandConnection.seat;
530     s_waylandConnection.seat = nullptr;
531     delete s_waylandConnection.pointerConstraints;
532     s_waylandConnection.pointerConstraints = nullptr;
533     delete s_waylandConnection.xdgShell;
534     s_waylandConnection.xdgShell = nullptr;
535     delete s_waylandConnection.shadowManager;
536     s_waylandConnection.shadowManager = nullptr;
537     delete s_waylandConnection.idleInhibitManagerV1;
538     s_waylandConnection.idleInhibitManagerV1 = nullptr;
539     delete s_waylandConnection.shm;
540     s_waylandConnection.shm = nullptr;
541     delete s_waylandConnection.queue;
542     s_waylandConnection.queue = nullptr;
543     delete s_waylandConnection.registry;
544     s_waylandConnection.registry = nullptr;
545     delete s_waylandConnection.appMenu;
546     s_waylandConnection.appMenu = nullptr;
547     delete s_waylandConnection.xdgDecorationManagerV1;
548     s_waylandConnection.xdgDecorationManagerV1 = nullptr;
549     delete s_waylandConnection.textInputManager;
550     s_waylandConnection.textInputManager = nullptr;
551     delete s_waylandConnection.inputPanelV1;
552     s_waylandConnection.inputPanelV1 = nullptr;
553     delete s_waylandConnection.layerShellV1;
554     s_waylandConnection.layerShellV1 = nullptr;
555     delete s_waylandConnection.outputManagementV2;
556     s_waylandConnection.outputManagementV2 = nullptr;
557     if (s_waylandConnection.thread) {
558         QSignalSpy spy(s_waylandConnection.connection, &QObject::destroyed);
559         s_waylandConnection.connection->deleteLater();
560         if (spy.isEmpty()) {
561             QVERIFY(spy.wait());
562         }
563         s_waylandConnection.thread->quit();
564         s_waylandConnection.thread->wait();
565         delete s_waylandConnection.thread;
566         s_waylandConnection.thread = nullptr;
567         s_waylandConnection.connection = nullptr;
568     }
569     s_waylandConnection.outputs.clear();
570     s_waylandConnection.outputDevicesV2.clear();
571 }
572 
waylandConnection()573 ConnectionThread *waylandConnection()
574 {
575     return s_waylandConnection.connection;
576 }
577 
waylandCompositor()578 KWayland::Client::Compositor *waylandCompositor()
579 {
580     return s_waylandConnection.compositor;
581 }
582 
waylandSubCompositor()583 SubCompositor *waylandSubCompositor()
584 {
585     return s_waylandConnection.subCompositor;
586 }
587 
waylandShadowManager()588 ShadowManager *waylandShadowManager()
589 {
590     return s_waylandConnection.shadowManager;
591 }
592 
waylandShmPool()593 ShmPool *waylandShmPool()
594 {
595     return s_waylandConnection.shm;
596 }
597 
waylandSeat()598 Seat *waylandSeat()
599 {
600     return s_waylandConnection.seat;
601 }
602 
waylandServerSideDecoration()603 ServerSideDecorationManager *waylandServerSideDecoration()
604 {
605     return s_waylandConnection.decoration;
606 }
607 
waylandPlasmaShell()608 PlasmaShell *waylandPlasmaShell()
609 {
610     return s_waylandConnection.plasmaShell;
611 }
612 
waylandWindowManagement()613 PlasmaWindowManagement *waylandWindowManagement()
614 {
615     return s_waylandConnection.windowManagement;
616 }
617 
waylandPointerConstraints()618 PointerConstraints *waylandPointerConstraints()
619 {
620     return s_waylandConnection.pointerConstraints;
621 }
622 
waylandAppMenuManager()623 AppMenuManager* waylandAppMenuManager()
624 {
625     return s_waylandConnection.appMenu;
626 }
627 
waylandOutputManagementV2()628 KWin::Test::WaylandOutputManagementV2 *waylandOutputManagementV2()
629 {
630     return s_waylandConnection.outputManagementV2;
631 }
632 
waylandTextInputManager()633 TextInputManager *waylandTextInputManager()
634 {
635     return s_waylandConnection.textInputManager;
636 }
637 
waylandTextInputManagerV3()638 TextInputManagerV3 *waylandTextInputManagerV3()
639 {
640     return s_waylandConnection.textInputManagerV3;
641 }
642 
waylandOutputs()643 QVector<KWayland::Client::Output *> waylandOutputs()
644 {
645     return s_waylandConnection.outputs;
646 }
647 
waylandOutputDevicesV2()648 QVector<KWin::Test::WaylandOutputDeviceV2 *> waylandOutputDevicesV2()
649 {
650     return s_waylandConnection.outputDevicesV2;
651 }
652 
waitForWaylandSurface(AbstractClient * client)653 bool waitForWaylandSurface(AbstractClient *client)
654 {
655     if (client->surface()) {
656         return true;
657     }
658     QSignalSpy surfaceChangedSpy(client, &Toplevel::surfaceChanged);
659     return surfaceChangedSpy.wait();
660 }
661 
waitForWaylandPointer()662 bool waitForWaylandPointer()
663 {
664     if (!s_waylandConnection.seat) {
665         return false;
666     }
667     QSignalSpy hasPointerSpy(s_waylandConnection.seat, &Seat::hasPointerChanged);
668     if (!hasPointerSpy.isValid()) {
669         return false;
670     }
671     return hasPointerSpy.wait();
672 }
673 
waitForWaylandTouch()674 bool waitForWaylandTouch()
675 {
676     if (!s_waylandConnection.seat) {
677         return false;
678     }
679     QSignalSpy hasTouchSpy(s_waylandConnection.seat, &Seat::hasTouchChanged);
680     if (!hasTouchSpy.isValid()) {
681         return false;
682     }
683     return hasTouchSpy.wait();
684 }
685 
waitForWaylandKeyboard()686 bool waitForWaylandKeyboard()
687 {
688     if (!s_waylandConnection.seat) {
689         return false;
690     }
691     QSignalSpy hasKeyboardSpy(s_waylandConnection.seat, &Seat::hasKeyboardChanged);
692     if (!hasKeyboardSpy.isValid()) {
693         return false;
694     }
695     return hasKeyboardSpy.wait();
696 }
697 
render(KWayland::Client::Surface * surface,const QSize & size,const QColor & color,const QImage::Format & format)698 void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format)
699 {
700     QImage img(size, format);
701     img.fill(color);
702     render(surface, img);
703 }
704 
render(KWayland::Client::Surface * surface,const QImage & img)705 void render(KWayland::Client::Surface *surface, const QImage &img)
706 {
707     surface->attachBuffer(s_waylandConnection.shm->createBuffer(img));
708     surface->damage(QRect(QPoint(0, 0), img.size()));
709     surface->commit(KWayland::Client::Surface::CommitFlag::None);
710 }
711 
waitForWaylandWindowShown(int timeout)712 AbstractClient *waitForWaylandWindowShown(int timeout)
713 {
714     QSignalSpy clientAddedSpy(workspace(), &Workspace::clientAdded);
715     if (!clientAddedSpy.isValid()) {
716         return nullptr;
717     }
718     if (!clientAddedSpy.wait(timeout)) {
719         return nullptr;
720     }
721     return clientAddedSpy.first().first().value<AbstractClient *>();
722 }
723 
renderAndWaitForShown(KWayland::Client::Surface * surface,const QSize & size,const QColor & color,const QImage::Format & format,int timeout)724 AbstractClient *renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format, int timeout)
725 {
726     QSignalSpy clientAddedSpy(workspace(), &Workspace::clientAdded);
727     if (!clientAddedSpy.isValid()) {
728         return nullptr;
729     }
730     render(surface, size, color, format);
731     flushWaylandConnection();
732     if (!clientAddedSpy.wait(timeout)) {
733         return nullptr;
734     }
735     return clientAddedSpy.first().first().value<AbstractClient *>();
736 }
737 
flushWaylandConnection()738 void flushWaylandConnection()
739 {
740     if (s_waylandConnection.connection) {
741         s_waylandConnection.connection->flush();
742     }
743 }
744 
createSurface(QObject * parent)745 KWayland::Client::Surface *createSurface(QObject *parent)
746 {
747     if (!s_waylandConnection.compositor) {
748         return nullptr;
749     }
750     auto s = s_waylandConnection.compositor->createSurface(parent);
751     if (!s->isValid()) {
752         delete s;
753         return nullptr;
754     }
755     return s;
756 }
757 
createSubSurface(KWayland::Client::Surface * surface,KWayland::Client::Surface * parentSurface,QObject * parent)758 SubSurface *createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface, QObject *parent)
759 {
760     if (!s_waylandConnection.subCompositor) {
761         return nullptr;
762     }
763     auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent);
764     if (!s->isValid()) {
765         delete s;
766         return nullptr;
767     }
768     return s;
769 }
770 
createLayerSurfaceV1(KWayland::Client::Surface * surface,const QString & scope,Output * output,LayerShellV1::layer layer)771 LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, Output *output, LayerShellV1::layer layer)
772 {
773     LayerShellV1 *shell = s_waylandConnection.layerShellV1;
774     if (!shell) {
775         qWarning() << "Could not create a layer surface because the layer shell global is not bound";
776         return nullptr;
777     }
778 
779     struct ::wl_output *nativeOutput = nullptr;
780     if (output) {
781         nativeOutput = *output;
782     }
783 
784     LayerSurfaceV1 *shellSurface = new LayerSurfaceV1();
785     shellSurface->init(shell->get_layer_surface(*surface, nativeOutput, layer, scope));
786 
787     return shellSurface;
788 }
789 
createInputPanelSurfaceV1(KWayland::Client::Surface * surface,Output * output)790 QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface, Output *output)
791 {
792     if (!s_waylandConnection.inputPanelV1) {
793         qWarning() << "Unable to create the input panel surface. The interface input_panel global is not bound";
794         return nullptr;
795     }
796     QtWayland::zwp_input_panel_surface_v1 *s = new QtWayland::zwp_input_panel_surface_v1(s_waylandConnection.inputPanelV1->get_input_panel_surface(*surface));
797 
798     if (!s->isInitialized()) {
799         delete s;
800         return nullptr;
801     }
802 
803     s->set_toplevel(output->output(), QtWayland::zwp_input_panel_surface_v1::position_center_bottom);
804 
805     return s;
806 }
807 
waitForConfigured(XdgSurface * shellSurface)808 static void waitForConfigured(XdgSurface *shellSurface)
809 {
810     QSignalSpy surfaceConfigureRequestedSpy(shellSurface, &XdgSurface::configureRequested);
811     QVERIFY(surfaceConfigureRequestedSpy.isValid());
812 
813     shellSurface->surface()->commit(KWayland::Client::Surface::CommitFlag::None);
814     QVERIFY(surfaceConfigureRequestedSpy.wait());
815 
816     shellSurface->ack_configure(surfaceConfigureRequestedSpy.last().first().toUInt());
817 }
818 
createXdgToplevelSurface(KWayland::Client::Surface * surface,QObject * parent,CreationSetup configureMode)819 XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent, CreationSetup configureMode)
820 {
821     XdgShell *shell = s_waylandConnection.xdgShell;
822 
823     if (!shell) {
824         qWarning() << "Could not create an xdg_toplevel surface because xdg_wm_base global is not bound";
825         return nullptr;
826     }
827 
828     XdgSurface *xdgSurface = new XdgSurface(shell, surface);
829     XdgToplevel *xdgToplevel = new XdgToplevel(xdgSurface, parent);
830 
831     if (configureMode == CreationSetup::CreateAndConfigure) {
832         waitForConfigured(xdgSurface);
833     }
834 
835     return xdgToplevel;
836 }
837 
createXdgPositioner()838 XdgPositioner *createXdgPositioner()
839 {
840     XdgShell *shell = s_waylandConnection.xdgShell;
841 
842     if (!shell) {
843         qWarning() << "Could not create an xdg_positioner object because xdg_wm_base global is not bound";
844         return nullptr;
845     }
846 
847     return new XdgPositioner(shell);
848 }
849 
createXdgPopupSurface(KWayland::Client::Surface * surface,XdgSurface * parentSurface,XdgPositioner * positioner,QObject * parent,CreationSetup configureMode)850 XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner,
851                                 QObject *parent, CreationSetup configureMode)
852 {
853     XdgShell *shell = s_waylandConnection.xdgShell;
854 
855     if (!shell) {
856         qWarning() << "Could not create an xdg_popup surface because xdg_wm_base global is not bound";
857         return nullptr;
858     }
859 
860     XdgSurface *xdgSurface = new XdgSurface(shell, surface);
861     XdgPopup *xdgPopup = new XdgPopup(xdgSurface, parentSurface, positioner, parent);
862 
863     if (configureMode == CreationSetup::CreateAndConfigure) {
864         waitForConfigured(xdgSurface);
865     }
866 
867     return xdgPopup;
868 }
869 
createXdgToplevelDecorationV1(XdgToplevel * toplevel,QObject * parent)870 XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent)
871 {
872     XdgDecorationManagerV1 *manager = s_waylandConnection.xdgDecorationManagerV1;
873 
874     if (!manager) {
875         qWarning() << "Could not create an xdg_toplevel_decoration_v1 because xdg_decoration_manager_v1 global is not bound";
876         return nullptr;
877     }
878 
879     return new XdgToplevelDecorationV1(manager, toplevel, parent);
880 }
881 
createIdleInhibitorV1(KWayland::Client::Surface * surface)882 IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface)
883 {
884     IdleInhibitManagerV1 *manager = s_waylandConnection.idleInhibitManagerV1;
885     if (!manager) {
886         qWarning() << "Could not create an idle_inhibitor_v1 because idle_inhibit_manager_v1 global is not bound";
887         return nullptr;
888     }
889 
890     return new IdleInhibitorV1(manager, surface);
891 }
892 
waitForWindowDestroyed(AbstractClient * client)893 bool waitForWindowDestroyed(AbstractClient *client)
894 {
895     QSignalSpy destroyedSpy(client, &QObject::destroyed);
896     if (!destroyedSpy.isValid()) {
897         return false;
898     }
899     return destroyedSpy.wait();
900 }
901 
lockScreen()902 bool lockScreen()
903 {
904     if (waylandServer()->isScreenLocked()) {
905         return false;
906     }
907     QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
908     if (!lockStateChangedSpy.isValid()) {
909         return false;
910     }
911     ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate);
912     if (lockStateChangedSpy.count() != 1) {
913         return false;
914     }
915     if (!waylandServer()->isScreenLocked()) {
916         return false;
917     }
918     if (!ScreenLockerWatcher::self()->isLocked()) {
919         QSignalSpy lockedSpy(ScreenLockerWatcher::self(), &ScreenLockerWatcher::locked);
920         if (!lockedSpy.isValid()) {
921             return false;
922         }
923         if (!lockedSpy.wait()) {
924             return false;
925         }
926         if (!ScreenLockerWatcher::self()->isLocked()) {
927             return false;
928         }
929     }
930     return true;
931 }
932 
unlockScreen()933 bool unlockScreen()
934 {
935     QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
936     if (!lockStateChangedSpy.isValid()) {
937         return false;
938     }
939     using namespace ScreenLocker;
940     const auto children = KSldApp::self()->children();
941     for (auto it = children.begin(); it != children.end(); ++it) {
942         if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) {
943             continue;
944         }
945         QMetaObject::invokeMethod(*it, "requestUnlock");
946         break;
947     }
948     if (waylandServer()->isScreenLocked()) {
949         lockStateChangedSpy.wait();
950     }
951     if (waylandServer()->isScreenLocked()) {
952         return true;
953     }
954     if (ScreenLockerWatcher::self()->isLocked()) {
955         QSignalSpy lockedSpy(ScreenLockerWatcher::self(), &ScreenLockerWatcher::locked);
956         if (!lockedSpy.isValid()) {
957             return false;
958         }
959         if (!lockedSpy.wait()) {
960             return false;
961         }
962         if (ScreenLockerWatcher::self()->isLocked()) {
963             return false;
964         }
965     }
966     return true;
967 }
968 
initWaylandWorkspace()969 void initWaylandWorkspace()
970 {
971     QSignalSpy workspaceInitializedSpy(waylandServer(), &WaylandServer::initialized);
972     waylandServer()->initWorkspace();
973     QVERIFY(workspaceInitializedSpy.count() || workspaceInitializedSpy.wait());
974 }
975 
WaylandOutputManagementV2(struct::wl_registry * registry,int id,int version)976 WaylandOutputManagementV2::WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version)
977     : QObject()
978     , QtWayland::kde_output_management_v2()
979 {
980     init(registry, id, version);
981 }
982 
createConfiguration()983 WaylandOutputConfigurationV2 *WaylandOutputManagementV2::createConfiguration()
984 {
985     return new WaylandOutputConfigurationV2(create_configuration());
986 }
987 
WaylandOutputConfigurationV2(struct::kde_output_configuration_v2 * object)988 WaylandOutputConfigurationV2::WaylandOutputConfigurationV2(struct ::kde_output_configuration_v2 *object)
989     : QObject()
990     , QtWayland::kde_output_configuration_v2()
991 {
992     init(object);
993 }
994 
kde_output_configuration_v2_applied()995 void WaylandOutputConfigurationV2::kde_output_configuration_v2_applied()
996 {
997     Q_EMIT applied();
998 }
kde_output_configuration_v2_failed()999 void WaylandOutputConfigurationV2::kde_output_configuration_v2_failed()
1000 {
1001     Q_EMIT failed();
1002 }
1003 
WaylandOutputDeviceV2Mode(struct::kde_output_device_mode_v2 * object)1004 WaylandOutputDeviceV2Mode::WaylandOutputDeviceV2Mode(struct ::kde_output_device_mode_v2 *object)
1005     : QtWayland::kde_output_device_mode_v2(object)
1006 {
1007 }
1008 
~WaylandOutputDeviceV2Mode()1009 WaylandOutputDeviceV2Mode::~WaylandOutputDeviceV2Mode()
1010 {
1011     kde_output_device_mode_v2_destroy(object());
1012 }
1013 
kde_output_device_mode_v2_size(int32_t width,int32_t height)1014 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_size(int32_t width, int32_t height)
1015 {
1016     m_size = QSize(width, height);
1017 }
1018 
kde_output_device_mode_v2_refresh(int32_t refresh)1019 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_refresh(int32_t refresh)
1020 {
1021     m_refreshRate = refresh;
1022 }
1023 
kde_output_device_mode_v2_preferred()1024 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_preferred()
1025 {
1026     m_preferred = true;
1027 }
1028 
kde_output_device_mode_v2_removed()1029 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_removed()
1030 {
1031     Q_EMIT removed();
1032 }
1033 
refreshRate() const1034 int WaylandOutputDeviceV2Mode::refreshRate() const
1035 {
1036     return m_refreshRate;
1037 }
1038 
size() const1039 QSize WaylandOutputDeviceV2Mode::size() const
1040 {
1041     return m_size;
1042 }
1043 
preferred() const1044 bool WaylandOutputDeviceV2Mode::preferred() const
1045 {
1046     return m_preferred;
1047 }
1048 
operator ==(const WaylandOutputDeviceV2Mode & other)1049 bool WaylandOutputDeviceV2Mode::operator==(const WaylandOutputDeviceV2Mode &other)
1050 {
1051     return m_size == other.m_size && m_refreshRate == other.m_refreshRate && m_preferred == other.m_preferred;
1052 }
1053 
get(struct::kde_output_device_mode_v2 * object)1054 WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2Mode::get(struct ::kde_output_device_mode_v2 *object)
1055 {
1056     auto mode = QtWayland::kde_output_device_mode_v2::fromObject(object);
1057     return static_cast<WaylandOutputDeviceV2Mode *>(mode);
1058 }
1059 
WaylandOutputDeviceV2(int id)1060 WaylandOutputDeviceV2::WaylandOutputDeviceV2(int id)
1061     : QObject()
1062     , kde_output_device_v2()
1063     , m_id(id)
1064 {
1065 }
1066 
~WaylandOutputDeviceV2()1067 WaylandOutputDeviceV2::~WaylandOutputDeviceV2()
1068 {
1069     qDeleteAll(m_modes);
1070 
1071     kde_output_device_v2_destroy(object());
1072 }
1073 
kde_output_device_v2_geometry(int32_t x,int32_t y,int32_t physical_width,int32_t physical_height,int32_t subpixel,const QString & make,const QString & model,int32_t transform)1074 void WaylandOutputDeviceV2::kde_output_device_v2_geometry(int32_t x,
1075                                                           int32_t y,
1076                                                           int32_t physical_width,
1077                                                           int32_t physical_height,
1078                                                           int32_t subpixel,
1079                                                           const QString &make,
1080                                                           const QString &model,
1081                                                           int32_t transform)
1082 {
1083     m_pos = QPoint(x, y);
1084     m_physicalSize = QSize(physical_width, physical_height);
1085     m_subpixel = subpixel;
1086     m_manufacturer = make;
1087     m_model = model;
1088     m_transform = transform;
1089 }
1090 
kde_output_device_v2_current_mode(struct::kde_output_device_mode_v2 * mode)1091 void WaylandOutputDeviceV2::kde_output_device_v2_current_mode(struct ::kde_output_device_mode_v2 *mode)
1092 {
1093     auto m = WaylandOutputDeviceV2Mode::get(mode);
1094 
1095     if (*m == *m_mode) {
1096         // unchanged
1097         return;
1098     }
1099     m_mode = m;
1100 }
1101 
kde_output_device_v2_mode(struct::kde_output_device_mode_v2 * mode)1102 void WaylandOutputDeviceV2::kde_output_device_v2_mode(struct ::kde_output_device_mode_v2 *mode)
1103 {
1104     WaylandOutputDeviceV2Mode *m = new WaylandOutputDeviceV2Mode(mode);
1105     // last mode sent is the current one
1106     m_mode = m;
1107     m_modes.append(m);
1108 
1109     connect(m, &WaylandOutputDeviceV2Mode::removed, this, [this, m]() {
1110         m_modes.removeOne(m);
1111         if (m_mode == m) {
1112             if (!m_modes.isEmpty()) {
1113                 m_mode = m_modes.first();
1114             } else {
1115                 // was last mode
1116                 qFatal("KWaylandBackend: no output modes available anymore, this seems like a compositor bug");
1117             }
1118         }
1119 
1120         delete m;
1121     });
1122 }
1123 
modeId() const1124 QString WaylandOutputDeviceV2::modeId() const
1125 {
1126     return QString::number(m_modes.indexOf(m_mode));
1127 }
1128 
deviceModeFromId(const int modeId) const1129 WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2::deviceModeFromId(const int modeId) const
1130 {
1131     return m_modes.at(modeId);
1132 }
1133 
modeName(const WaylandOutputDeviceV2Mode * m) const1134 QString WaylandOutputDeviceV2::modeName(const WaylandOutputDeviceV2Mode *m) const
1135 {
1136     return QString::number(m->size().width()) + QLatin1Char('x') + QString::number(m->size().height()) + QLatin1Char('@')
1137         + QString::number(qRound(m->refreshRate() / 1000.0));
1138 }
1139 
name() const1140 QString WaylandOutputDeviceV2::name() const
1141 {
1142     return QStringLiteral("%1 %2").arg(m_manufacturer, m_model);
1143 }
1144 
operator <<(QDebug dbg,const WaylandOutputDeviceV2 * output)1145 QDebug operator<<(QDebug dbg, const WaylandOutputDeviceV2 *output)
1146 {
1147     dbg << "WaylandOutput(Id:" << output->id() << ", Name:" << QString(output->manufacturer() + QLatin1Char(' ') + output->model()) << ")";
1148     return dbg;
1149 }
1150 
kde_output_device_v2_done()1151 void WaylandOutputDeviceV2::kde_output_device_v2_done()
1152 {
1153     Q_EMIT done();
1154 }
1155 
kde_output_device_v2_scale(wl_fixed_t factor)1156 void WaylandOutputDeviceV2::kde_output_device_v2_scale(wl_fixed_t factor)
1157 {
1158     m_factor = wl_fixed_to_double(factor);
1159 }
1160 
kde_output_device_v2_edid(const QString & edid)1161 void WaylandOutputDeviceV2::kde_output_device_v2_edid(const QString &edid)
1162 {
1163     m_edid = QByteArray::fromBase64(edid.toUtf8());
1164 }
1165 
kde_output_device_v2_enabled(int32_t enabled)1166 void WaylandOutputDeviceV2::kde_output_device_v2_enabled(int32_t enabled)
1167 {
1168     if (m_enabled != enabled) {
1169         m_enabled = enabled;
1170         Q_EMIT enabledChanged();
1171     }
1172 }
1173 
kde_output_device_v2_uuid(const QString & uuid)1174 void WaylandOutputDeviceV2::kde_output_device_v2_uuid(const QString &uuid)
1175 {
1176     m_uuid = uuid;
1177 }
1178 
kde_output_device_v2_serial_number(const QString & serialNumber)1179 void WaylandOutputDeviceV2::kde_output_device_v2_serial_number(const QString &serialNumber)
1180 {
1181     m_serialNumber = serialNumber;
1182 }
1183 
kde_output_device_v2_eisa_id(const QString & eisaId)1184 void WaylandOutputDeviceV2::kde_output_device_v2_eisa_id(const QString &eisaId)
1185 {
1186     m_eisaId = eisaId;
1187 }
1188 
kde_output_device_v2_capabilities(uint32_t flags)1189 void WaylandOutputDeviceV2::kde_output_device_v2_capabilities(uint32_t flags)
1190 {
1191     m_flags = flags;
1192 }
1193 
kde_output_device_v2_overscan(uint32_t overscan)1194 void WaylandOutputDeviceV2::kde_output_device_v2_overscan(uint32_t overscan)
1195 {
1196     m_overscan = overscan;
1197 }
1198 
kde_output_device_v2_vrr_policy(uint32_t vrr_policy)1199 void WaylandOutputDeviceV2::kde_output_device_v2_vrr_policy(uint32_t vrr_policy)
1200 {
1201     m_vrr_policy = vrr_policy;
1202 }
1203 
kde_output_device_v2_rgb_range(uint32_t rgb_range)1204 void WaylandOutputDeviceV2::kde_output_device_v2_rgb_range(uint32_t rgb_range)
1205 {
1206     m_rgbRange = rgb_range;
1207 }
1208 
edid() const1209 QByteArray WaylandOutputDeviceV2::edid() const
1210 {
1211     return m_edid;
1212 }
1213 
enabled() const1214 bool WaylandOutputDeviceV2::enabled() const
1215 {
1216     return m_enabled;
1217 }
1218 
id() const1219 int WaylandOutputDeviceV2::id() const
1220 {
1221     return m_id;
1222 }
1223 
scale() const1224 qreal WaylandOutputDeviceV2::scale() const
1225 {
1226     return m_factor;
1227 }
1228 
manufacturer() const1229 QString WaylandOutputDeviceV2::manufacturer() const
1230 {
1231     return m_manufacturer;
1232 }
1233 
model() const1234 QString WaylandOutputDeviceV2::model() const
1235 {
1236     return m_model;
1237 }
1238 
globalPosition() const1239 QPoint WaylandOutputDeviceV2::globalPosition() const
1240 {
1241     return m_pos;
1242 }
1243 
pixelSize() const1244 QSize WaylandOutputDeviceV2::pixelSize() const
1245 {
1246     return m_mode->size();
1247 }
1248 
refreshRate() const1249 int WaylandOutputDeviceV2::refreshRate() const
1250 {
1251     return m_mode->refreshRate();
1252 }
1253 
vrrPolicy() const1254 uint32_t WaylandOutputDeviceV2::vrrPolicy() const
1255 {
1256     return m_vrr_policy;
1257 }
1258 
overscan() const1259 uint32_t WaylandOutputDeviceV2::overscan() const
1260 {
1261     return m_overscan;
1262 }
1263 
capabilities() const1264 uint32_t WaylandOutputDeviceV2::capabilities() const
1265 {
1266     return m_flags;
1267 }
1268 
rgbRange() const1269 uint32_t WaylandOutputDeviceV2::rgbRange() const
1270 {
1271     return m_rgbRange;
1272 }
1273 
1274 }
1275 }
1276