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