KWin
Loading...
Searching...
No Matches
test_helpers.cpp
Go to the documentation of this file.
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 <config-kwin.h>
10
11#include <QSignalSpy>
12
13#include "kwin_wayland_test.h"
14
15#if KWIN_BUILD_SCREENLOCKER
16#include "screenlockerwatcher.h"
17#endif
18#include "inputmethod.h"
19#include "wayland/display.h"
20#include "wayland_server.h"
21#include "workspace.h"
22#include <wayland-zkde-screencast-unstable-v1-client-protocol.h>
23
24#include <KWayland/Client/appmenu.h>
25#include <KWayland/Client/compositor.h>
26#include <KWayland/Client/connection_thread.h>
27#include <KWayland/Client/event_queue.h>
28#include <KWayland/Client/output.h>
29#include <KWayland/Client/plasmashell.h>
30#include <KWayland/Client/plasmawindowmanagement.h>
31#include <KWayland/Client/pointer.h>
32#include <KWayland/Client/pointerconstraints.h>
33#include <KWayland/Client/registry.h>
34#include <KWayland/Client/seat.h>
35#include <KWayland/Client/shadow.h>
36#include <KWayland/Client/shm_pool.h>
37#include <KWayland/Client/subcompositor.h>
38#include <KWayland/Client/subsurface.h>
39#include <KWayland/Client/surface.h>
40#include <KWayland/Client/textinput.h>
41
42// screenlocker
43#if KWIN_BUILD_SCREENLOCKER
44#include <KScreenLocker/KsldApp>
45#endif
46
47#include <QFutureWatcher>
48#include <QThread>
49#include <QtConcurrentRun>
50
51// system
52#include <sys/socket.h>
53#include <sys/types.h>
54#include <unistd.h>
55#include <xf86drm.h>
56
57namespace KWin
58{
59namespace Test
60{
61
63{
64 destroy();
65}
66
68{
69 destroy();
70}
71
72void LayerSurfaceV1::zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height)
73{
74 Q_EMIT configureRequested(serial, QSize(width, height));
75}
76
81
83{
84 destroy();
85}
86
87XdgSurface::XdgSurface(XdgShell *shell, KWayland::Client::Surface *surface, QObject *parent)
88 : QObject(parent)
89 , QtWayland::xdg_surface(shell->get_xdg_surface(*surface))
90 , m_surface(surface)
91{
92}
93
95{
96 destroy();
97}
98
99KWayland::Client::Surface *XdgSurface::surface() const
100{
101 return m_surface;
102}
103
105{
106 Q_EMIT configureRequested(serial);
107}
108
109XdgToplevel::XdgToplevel(XdgSurface *surface, QObject *parent)
110 : QObject(parent)
111 , QtWayland::xdg_toplevel(surface->get_toplevel())
112 , m_xdgSurface(surface)
113{
114}
115
117{
118 destroy();
119}
120
122{
123 return m_xdgSurface.get();
124}
125
126void XdgToplevel::xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states)
127{
128 States requestedStates;
129
130 const uint32_t *stateData = static_cast<const uint32_t *>(states->data);
131 const size_t stateCount = states->size / sizeof(uint32_t);
132
133 for (size_t i = 0; i < stateCount; ++i) {
134 switch (stateData[i]) {
135 case QtWayland::xdg_toplevel::state_maximized:
136 requestedStates |= State::Maximized;
137 break;
138 case QtWayland::xdg_toplevel::state_fullscreen:
139 requestedStates |= State::Fullscreen;
140 break;
141 case QtWayland::xdg_toplevel::state_resizing:
142 requestedStates |= State::Resizing;
143 break;
144 case QtWayland::xdg_toplevel::state_activated:
145 requestedStates |= State::Activated;
146 break;
147 }
148 }
149
150 Q_EMIT configureRequested(QSize(width, height), requestedStates);
151}
152
154{
155 Q_EMIT closeRequested();
156}
157
159 : QtWayland::xdg_positioner(shell->create_positioner())
160{
161}
162
164{
165 destroy();
166}
167
168XdgPopup::XdgPopup(XdgSurface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, QObject *parent)
169 : QObject(parent)
170 , QtWayland::xdg_popup(surface->get_popup(parentSurface->object(), positioner->object()))
171 , m_xdgSurface(surface)
172{
173}
174
176{
177 destroy();
178}
179
181{
182 return m_xdgSurface.get();
183}
184
185void XdgPopup::xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height)
186{
187 Q_EMIT configureRequested(QRect(x, y, width, height));
188}
189
191{
192 Q_EMIT doneReceived();
193}
194
199
201 XdgToplevel *toplevel, QObject *parent)
202 : QObject(parent)
203 , QtWayland::zxdg_toplevel_decoration_v1(manager->get_toplevel_decoration(toplevel->object()))
204{
205}
206
211
216
221
222IdleInhibitorV1::IdleInhibitorV1(IdleInhibitManagerV1 *manager, KWayland::Client::Surface *surface)
223 : QtWayland::zwp_idle_inhibitor_v1(manager->create_inhibitor(*surface))
224{
225}
226
228{
229 destroy();
230}
231
236
237AutoHideScreenEdgeV1::AutoHideScreenEdgeV1(ScreenEdgeManagerV1 *manager, KWayland::Client::Surface *surface, uint32_t border)
238 : QtWayland::kde_auto_hide_screen_edge_v1(manager->get_auto_hide_screen_edge(border, *surface))
239{
240}
241
246
251
252CursorShapeDeviceV1::CursorShapeDeviceV1(CursorShapeManagerV1 *manager, KWayland::Client::Pointer *pointer)
253 : QtWayland::wp_cursor_shape_device_v1(manager->get_pointer(*pointer))
254{
255}
256
261
263{
264 destroy();
265}
266
271
272static struct
273{
274 KWayland::Client::ConnectionThread *connection = nullptr;
275 KWayland::Client::EventQueue *queue = nullptr;
276 KWayland::Client::Compositor *compositor = nullptr;
277 KWayland::Client::SubCompositor *subCompositor = nullptr;
278 KWayland::Client::ShadowManager *shadowManager = nullptr;
279 XdgShell *xdgShell = nullptr;
280 KWayland::Client::ShmPool *shm = nullptr;
281 KWayland::Client::Seat *seat = nullptr;
282 KWayland::Client::PlasmaShell *plasmaShell = nullptr;
283 KWayland::Client::PlasmaWindowManagement *windowManagement = nullptr;
284 KWayland::Client::PointerConstraints *pointerConstraints = nullptr;
285 KWayland::Client::Registry *registry = nullptr;
287 QThread *thread = nullptr;
288 QList<KWayland::Client::Output *> outputs;
289 QList<WaylandOutputDeviceV2 *> outputDevicesV2;
291 KWayland::Client::AppMenuManager *appMenu = nullptr;
293 KWayland::Client::TextInputManager *textInputManager = nullptr;
294 QtWayland::zwp_input_panel_v1 *inputPanelV1 = nullptr;
296 QtWayland::zwp_input_method_context_v1 *inputMethodContextV1 = nullptr;
305} s_waylandConnection;
306
308{
309 return s_waylandConnection.inputMethodV1;
310}
311
312KWayland::Client::Surface *inputPanelSurface()
313{
314 return s_waylandConnection.inputMethodV1->inputPanelSurface();
315}
316
317MockInputMethod::MockInputMethod(struct wl_registry *registry, int id, int version)
318 : QtWayland::zwp_input_method_v1(registry, id, version)
319{
320}
324
325void MockInputMethod::zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context)
326{
327 if (!m_inputSurface) {
328 m_inputSurface = Test::createSurface();
329 m_inputMethodSurface = Test::createInputPanelSurfaceV1(m_inputSurface.get(), s_waylandConnection.outputs.first(), m_mode);
330 }
331 m_context = context;
332
333 switch (m_mode) {
334 case Mode::TopLevel:
335 Test::render(m_inputSurface.get(), QSize(1280, 400), Qt::blue);
336 break;
337 case Mode::Overlay:
338 Test::render(m_inputSurface.get(), QSize(200, 50), Qt::blue);
339 break;
340 }
341
342 Q_EMIT activate();
343}
344
346{
347 m_mode = mode;
348}
349
350void MockInputMethod::zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context)
351{
352 QCOMPARE(context, m_context);
353 zwp_input_method_context_v1_destroy(context);
354 m_context = nullptr;
355
356 if (m_inputSurface) {
357 m_inputSurface->release();
358 m_inputSurface->destroy();
359 m_inputSurface.reset();
360 delete m_inputMethodSurface;
361 m_inputMethodSurface = nullptr;
362 }
363}
364
365bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
366{
367 if (s_waylandConnection.connection) {
368 return false;
369 }
370
371 int sx[2];
372 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
373 return false;
374 }
376 // setup connection
377 s_waylandConnection.connection = new KWayland::Client::ConnectionThread;
378 QSignalSpy connectedSpy(s_waylandConnection.connection, &KWayland::Client::ConnectionThread::connected);
379 if (!connectedSpy.isValid()) {
380 return false;
381 }
382 s_waylandConnection.connection->setSocketFd(sx[1]);
383
384 s_waylandConnection.thread = new QThread(kwinApp());
385 s_waylandConnection.connection->moveToThread(s_waylandConnection.thread);
386 s_waylandConnection.thread->start();
387
388 s_waylandConnection.connection->initConnection();
389 if (!connectedSpy.wait()) {
390 return false;
391 }
392
393 s_waylandConnection.queue = new KWayland::Client::EventQueue;
394 s_waylandConnection.queue->setup(s_waylandConnection.connection);
395 if (!s_waylandConnection.queue->isValid()) {
396 return false;
397 }
398
399 KWayland::Client::Registry *registry = new KWayland::Client::Registry;
400 s_waylandConnection.registry = registry;
401 registry->setEventQueue(s_waylandConnection.queue);
402
403 QObject::connect(registry, &KWayland::Client::Registry::outputAnnounced, [=](quint32 name, quint32 version) {
404 KWayland::Client::Output *output = registry->createOutput(name, version, s_waylandConnection.registry);
405 s_waylandConnection.outputs << output;
406 QObject::connect(output, &KWayland::Client::Output::removed, [=]() {
407 output->deleteLater();
408 s_waylandConnection.outputs.removeOne(output);
409 });
410 QObject::connect(output, &KWayland::Client::Output::destroyed, [=]() {
411 s_waylandConnection.outputs.removeOne(output);
412 });
413 });
414
415 QObject::connect(registry, &KWayland::Client::Registry::interfaceAnnounced, [=](const QByteArray &interface, quint32 name, quint32 version) {
417 if (interface == QByteArrayLiteral("zwp_input_method_v1")) {
418 s_waylandConnection.inputMethodV1 = new MockInputMethod(*registry, name, version);
419 } else if (interface == QByteArrayLiteral("zwp_input_panel_v1")) {
420 s_waylandConnection.inputPanelV1 = new QtWayland::zwp_input_panel_v1(*registry, name, version);
421 }
422 }
424 if (interface == QByteArrayLiteral("zwlr_layer_shell_v1")) {
425 s_waylandConnection.layerShellV1 = new LayerShellV1();
426 s_waylandConnection.layerShellV1->init(*registry, name, version);
427 }
428 }
430 // do something
431 if (interface == QByteArrayLiteral("zwp_text_input_manager_v3")) {
432 s_waylandConnection.textInputManagerV3 = new TextInputManagerV3();
433 s_waylandConnection.textInputManagerV3->init(*registry, name, version);
434 }
435 }
436 if (interface == QByteArrayLiteral("xdg_wm_base")) {
437 s_waylandConnection.xdgShell = new XdgShell();
438 s_waylandConnection.xdgShell->init(*registry, name, version);
439 }
441 if (interface == zxdg_decoration_manager_v1_interface.name) {
442 s_waylandConnection.xdgDecorationManagerV1 = new XdgDecorationManagerV1();
443 s_waylandConnection.xdgDecorationManagerV1->init(*registry, name, version);
444 return;
445 }
446 }
448 if (interface == zwp_idle_inhibit_manager_v1_interface.name) {
449 s_waylandConnection.idleInhibitManagerV1 = new IdleInhibitManagerV1();
450 s_waylandConnection.idleInhibitManagerV1->init(*registry, name, version);
451 return;
452 }
453 }
455 if (interface == kde_output_device_v2_interface.name) {
457 device->init(*registry, name, version);
458
459 s_waylandConnection.outputDevicesV2 << device;
460
461 QObject::connect(device, &WaylandOutputDeviceV2::destroyed, [=]() {
462 s_waylandConnection.outputDevicesV2.removeOne(device);
463 device->deleteLater();
464 });
465
466 QObject::connect(registry, &KWayland::Client::Registry::interfaceRemoved, device, [name, device](const quint32 &interfaceName) {
467 if (name == interfaceName) {
468 s_waylandConnection.outputDevicesV2.removeOne(device);
469 device->deleteLater();
470 }
471 });
472
473 return;
474 }
475 }
477 if (interface == kde_output_management_v2_interface.name) {
478 s_waylandConnection.outputManagementV2 = new WaylandOutputManagementV2(*registry, name, version);
479 return;
480 }
481 }
483 if (interface == wp_fractional_scale_manager_v1_interface.name) {
484 s_waylandConnection.fractionalScaleManagerV1 = new FractionalScaleManagerV1();
485 s_waylandConnection.fractionalScaleManagerV1->init(*registry, name, version);
486 return;
487 }
488 }
490 if (interface == zkde_screencast_unstable_v1_interface.name) {
491 s_waylandConnection.screencastingV1 = new ScreencastingV1();
492 s_waylandConnection.screencastingV1->init(*registry, name, version);
493 return;
494 }
495 }
497 if (interface == kde_screen_edge_manager_v1_interface.name) {
498 s_waylandConnection.screenEdgeManagerV1 = new ScreenEdgeManagerV1();
499 s_waylandConnection.screenEdgeManagerV1->init(*registry, name, version);
500 return;
501 }
502 }
504 if (interface == wp_cursor_shape_manager_v1_interface.name) {
505 s_waylandConnection.cursorShapeManagerV1 = new CursorShapeManagerV1();
506 s_waylandConnection.cursorShapeManagerV1->init(*registry, name, version);
507 }
508 }
510 if (interface == org_kde_kwin_fake_input_interface.name) {
511 s_waylandConnection.fakeInput = new FakeInput();
512 s_waylandConnection.fakeInput->init(*registry, name, version);
513 }
514 }
516 if (interface == wp_security_context_manager_v1_interface.name) {
517 s_waylandConnection.securityContextManagerV1 = new SecurityContextManagerV1();
518 s_waylandConnection.securityContextManagerV1->init(*registry, name, version);
519 }
520 }
521 });
522
523 QSignalSpy allAnnounced(registry, &KWayland::Client::Registry::interfacesAnnounced);
524 if (!allAnnounced.isValid()) {
525 return false;
526 }
527 registry->create(s_waylandConnection.connection);
528 if (!registry->isValid()) {
529 return false;
530 }
531 registry->setup();
532 if (!allAnnounced.wait()) {
533 return false;
534 }
535
536 s_waylandConnection.compositor = registry->createCompositor(registry->interface(KWayland::Client::Registry::Interface::Compositor).name, registry->interface(KWayland::Client::Registry::Interface::Compositor).version);
537 if (!s_waylandConnection.compositor->isValid()) {
538 return false;
539 }
540 s_waylandConnection.subCompositor = registry->createSubCompositor(registry->interface(KWayland::Client::Registry::Interface::SubCompositor).name, registry->interface(KWayland::Client::Registry::Interface::SubCompositor).version);
541 if (!s_waylandConnection.subCompositor->isValid()) {
542 return false;
543 }
544 s_waylandConnection.shm = registry->createShmPool(registry->interface(KWayland::Client::Registry::Interface::Shm).name, registry->interface(KWayland::Client::Registry::Interface::Shm).version);
545 if (!s_waylandConnection.shm->isValid()) {
546 return false;
547 }
548 if (flags.testFlag(AdditionalWaylandInterface::Seat)) {
549 s_waylandConnection.seat = registry->createSeat(registry->interface(KWayland::Client::Registry::Interface::Seat).name, registry->interface(KWayland::Client::Registry::Interface::Seat).version);
550 if (!s_waylandConnection.seat->isValid()) {
551 return false;
552 }
553 }
554 if (flags.testFlag(AdditionalWaylandInterface::ShadowManager)) {
555 s_waylandConnection.shadowManager = registry->createShadowManager(registry->interface(KWayland::Client::Registry::Interface::Shadow).name,
556 registry->interface(KWayland::Client::Registry::Interface::Shadow).version);
557 if (!s_waylandConnection.shadowManager->isValid()) {
558 return false;
559 }
560 }
561 if (flags.testFlag(AdditionalWaylandInterface::PlasmaShell)) {
562 s_waylandConnection.plasmaShell = registry->createPlasmaShell(registry->interface(KWayland::Client::Registry::Interface::PlasmaShell).name,
563 registry->interface(KWayland::Client::Registry::Interface::PlasmaShell).version);
564 if (!s_waylandConnection.plasmaShell->isValid()) {
565 return false;
566 }
567 }
569 s_waylandConnection.windowManagement = registry->createPlasmaWindowManagement(registry->interface(KWayland::Client::Registry::Interface::PlasmaWindowManagement).name,
570 registry->interface(KWayland::Client::Registry::Interface::PlasmaWindowManagement).version);
571 if (!s_waylandConnection.windowManagement->isValid()) {
572 return false;
573 }
574 }
576 s_waylandConnection.pointerConstraints = registry->createPointerConstraints(registry->interface(KWayland::Client::Registry::Interface::PointerConstraintsUnstableV1).name,
577 registry->interface(KWayland::Client::Registry::Interface::PointerConstraintsUnstableV1).version);
578 if (!s_waylandConnection.pointerConstraints->isValid()) {
579 return false;
580 }
581 }
582 if (flags.testFlag(AdditionalWaylandInterface::AppMenu)) {
583 s_waylandConnection.appMenu = registry->createAppMenuManager(registry->interface(KWayland::Client::Registry::Interface::AppMenu).name, registry->interface(KWayland::Client::Registry::Interface::AppMenu).version);
584 if (!s_waylandConnection.appMenu->isValid()) {
585 return false;
586 }
587 }
589 s_waylandConnection.textInputManager = registry->createTextInputManager(registry->interface(KWayland::Client::Registry::Interface::TextInputManagerUnstableV2).name, registry->interface(KWayland::Client::Registry::Interface::TextInputManagerUnstableV2).version);
590 if (!s_waylandConnection.textInputManager->isValid()) {
591 return false;
592 }
593 }
594
595 return true;
596}
597
599{
600 delete s_waylandConnection.compositor;
601 s_waylandConnection.compositor = nullptr;
602 delete s_waylandConnection.subCompositor;
603 s_waylandConnection.subCompositor = nullptr;
604 delete s_waylandConnection.windowManagement;
605 s_waylandConnection.windowManagement = nullptr;
606 delete s_waylandConnection.plasmaShell;
607 s_waylandConnection.plasmaShell = nullptr;
608 delete s_waylandConnection.seat;
609 s_waylandConnection.seat = nullptr;
610 delete s_waylandConnection.pointerConstraints;
611 s_waylandConnection.pointerConstraints = nullptr;
612 delete s_waylandConnection.xdgShell;
613 s_waylandConnection.xdgShell = nullptr;
614 delete s_waylandConnection.shadowManager;
615 s_waylandConnection.shadowManager = nullptr;
616 delete s_waylandConnection.idleInhibitManagerV1;
617 s_waylandConnection.idleInhibitManagerV1 = nullptr;
618 delete s_waylandConnection.shm;
619 s_waylandConnection.shm = nullptr;
620 delete s_waylandConnection.registry;
621 s_waylandConnection.registry = nullptr;
622 delete s_waylandConnection.appMenu;
623 s_waylandConnection.appMenu = nullptr;
624 delete s_waylandConnection.xdgDecorationManagerV1;
625 s_waylandConnection.xdgDecorationManagerV1 = nullptr;
626 delete s_waylandConnection.textInputManager;
627 s_waylandConnection.textInputManager = nullptr;
628 delete s_waylandConnection.inputPanelV1;
629 s_waylandConnection.inputPanelV1 = nullptr;
630 delete s_waylandConnection.layerShellV1;
631 s_waylandConnection.layerShellV1 = nullptr;
632 delete s_waylandConnection.outputManagementV2;
633 s_waylandConnection.outputManagementV2 = nullptr;
634 delete s_waylandConnection.fractionalScaleManagerV1;
635 s_waylandConnection.fractionalScaleManagerV1 = nullptr;
636 delete s_waylandConnection.screencastingV1;
637 s_waylandConnection.screencastingV1 = nullptr;
638 delete s_waylandConnection.screenEdgeManagerV1;
639 s_waylandConnection.screenEdgeManagerV1 = nullptr;
640 delete s_waylandConnection.cursorShapeManagerV1;
641 s_waylandConnection.cursorShapeManagerV1 = nullptr;
642 delete s_waylandConnection.fakeInput;
643 s_waylandConnection.fakeInput = nullptr;
644 delete s_waylandConnection.securityContextManagerV1;
645 s_waylandConnection.securityContextManagerV1 = nullptr;
646
647 delete s_waylandConnection.queue; // Must be destroyed last
648 s_waylandConnection.queue = nullptr;
649
650 if (s_waylandConnection.thread) {
651 s_waylandConnection.connection->deleteLater();
652 s_waylandConnection.thread->quit();
653 s_waylandConnection.thread->wait();
654 delete s_waylandConnection.thread;
655 s_waylandConnection.thread = nullptr;
656 s_waylandConnection.connection = nullptr;
657 }
658 s_waylandConnection.outputs.clear();
659 s_waylandConnection.outputDevicesV2.clear();
660}
661
662KWayland::Client::ConnectionThread *waylandConnection()
663{
664 return s_waylandConnection.connection;
665}
666
667KWayland::Client::Compositor *waylandCompositor()
668{
669 return s_waylandConnection.compositor;
670}
671
672KWayland::Client::SubCompositor *waylandSubCompositor()
673{
674 return s_waylandConnection.subCompositor;
675}
676
677KWayland::Client::ShadowManager *waylandShadowManager()
678{
679 return s_waylandConnection.shadowManager;
680}
681
682KWayland::Client::ShmPool *waylandShmPool()
683{
684 return s_waylandConnection.shm;
685}
686
687KWayland::Client::Seat *waylandSeat()
688{
689 return s_waylandConnection.seat;
690}
691
692KWayland::Client::PlasmaShell *waylandPlasmaShell()
693{
694 return s_waylandConnection.plasmaShell;
695}
696
697KWayland::Client::PlasmaWindowManagement *waylandWindowManagement()
698{
699 return s_waylandConnection.windowManagement;
700}
701
702KWayland::Client::PointerConstraints *waylandPointerConstraints()
703{
704 return s_waylandConnection.pointerConstraints;
705}
706
707KWayland::Client::AppMenuManager *waylandAppMenuManager()
708{
709 return s_waylandConnection.appMenu;
710}
711
713{
714 return s_waylandConnection.outputManagementV2;
715}
716
717KWayland::Client::TextInputManager *waylandTextInputManager()
718{
719 return s_waylandConnection.textInputManager;
720}
721
723{
724 return s_waylandConnection.textInputManagerV3;
725}
726
727QList<KWayland::Client::Output *> waylandOutputs()
728{
729 return s_waylandConnection.outputs;
730}
731
732KWayland::Client::Output *waylandOutput(const QString &name)
733{
734 for (KWayland::Client::Output *output : std::as_const(s_waylandConnection.outputs)) {
735 if (output->name() == name) {
736 return output;
737 }
738 }
739 return nullptr;
740}
741
743{
744 return s_waylandConnection.screencastingV1;
745}
746
747QList<KWin::Test::WaylandOutputDeviceV2 *> waylandOutputDevicesV2()
748{
749 return s_waylandConnection.outputDevicesV2;
750}
751
753{
754 return s_waylandConnection.fakeInput;
755}
756
758{
759 return s_waylandConnection.securityContextManagerV1;
760}
761
763{
764 if (window->surface()) {
765 return true;
766 }
767 QSignalSpy surfaceChangedSpy(window, &Window::surfaceChanged);
768 return surfaceChangedSpy.wait();
769}
770
772{
773 if (!s_waylandConnection.seat) {
774 return false;
775 }
776 QSignalSpy hasPointerSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasPointerChanged);
777 if (!hasPointerSpy.isValid()) {
778 return false;
779 }
780 return hasPointerSpy.wait();
781}
782
784{
785 if (!s_waylandConnection.seat) {
786 return false;
787 }
788 QSignalSpy hasTouchSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasTouchChanged);
789 if (!hasTouchSpy.isValid()) {
790 return false;
791 }
792 return hasTouchSpy.wait();
793}
794
796{
797 if (!s_waylandConnection.seat) {
798 return false;
799 }
800 QSignalSpy hasKeyboardSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasKeyboardChanged);
801 if (!hasKeyboardSpy.isValid()) {
802 return false;
803 }
804 return hasKeyboardSpy.wait();
805}
806
807void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format)
808{
809 QImage img(size, format);
810 img.fill(color);
811 render(surface, img);
812}
813
814void render(KWayland::Client::Surface *surface, const QImage &img)
815{
816 surface->attachBuffer(s_waylandConnection.shm->createBuffer(img));
817 surface->damage(QRect(QPoint(0, 0), img.size()));
818 surface->commit(KWayland::Client::Surface::CommitFlag::None);
819}
820
822{
823 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
824 if (!windowAddedSpy.isValid()) {
825 return nullptr;
826 }
827 if (!windowAddedSpy.wait(timeout)) {
828 return nullptr;
829 }
830 return windowAddedSpy.first().first().value<Window *>();
831}
832
833Window *renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format, int timeout)
834{
835 QImage img(size, format);
836 img.fill(color);
837 return renderAndWaitForShown(surface, img, timeout);
838}
839
840Window *renderAndWaitForShown(KWayland::Client::Surface *surface, const QImage &img, int timeout)
841{
842 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
843 if (!windowAddedSpy.isValid()) {
844 return nullptr;
845 }
846 render(surface, img);
848 if (!windowAddedSpy.wait(timeout)) {
849 return nullptr;
850 }
851 return windowAddedSpy.first().first().value<Window *>();
852}
853
855{
856 if (s_waylandConnection.connection) {
857 s_waylandConnection.connection->flush();
858 }
859}
860
861class WaylandSyncPoint : public QObject
862{
863 Q_OBJECT
864
865public:
866 explicit WaylandSyncPoint(KWayland::Client::ConnectionThread *connection, KWayland::Client::EventQueue *eventQueue)
867 {
868 static const wl_callback_listener listener = {
869 .done = [](void *data, wl_callback *callback, uint32_t callback_data) {
870 auto syncPoint = static_cast<WaylandSyncPoint *>(data);
871 Q_EMIT syncPoint->done();
872 },
873 };
874
875 m_callback = wl_display_sync(connection->display());
876 eventQueue->addProxy(m_callback);
877 wl_callback_add_listener(m_callback, &listener, this);
878 }
879
881 {
882 wl_callback_destroy(m_callback);
883 }
884
885Q_SIGNALS:
886 void done();
887
888private:
889 wl_callback *m_callback;
890};
891
893{
894 WaylandSyncPoint syncPoint(s_waylandConnection.connection, s_waylandConnection.queue);
895 QSignalSpy doneSpy(&syncPoint, &WaylandSyncPoint::done);
896 return doneSpy.wait();
897}
898
899std::unique_ptr<KWayland::Client::Surface> createSurface()
900{
901 if (!s_waylandConnection.compositor) {
902 return nullptr;
903 }
904 std::unique_ptr<KWayland::Client::Surface> s{s_waylandConnection.compositor->createSurface()};
905 return s->isValid() ? std::move(s) : nullptr;
906}
907
908KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface, QObject *parent)
909{
910 if (!s_waylandConnection.subCompositor) {
911 return nullptr;
912 }
913 auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent);
914 if (!s->isValid()) {
915 delete s;
916 return nullptr;
917 }
918 return s;
919}
920
921LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output, LayerShellV1::layer layer)
922{
923 LayerShellV1 *shell = s_waylandConnection.layerShellV1;
924 if (!shell) {
925 qWarning() << "Could not create a layer surface because the layer shell global is not bound";
926 return nullptr;
927 }
928
929 struct ::wl_output *nativeOutput = nullptr;
930 if (output) {
931 nativeOutput = *output;
932 }
933
934 LayerSurfaceV1 *shellSurface = new LayerSurfaceV1();
935 shellSurface->init(shell->get_layer_surface(*surface, nativeOutput, layer, scope));
936
937 return shellSurface;
938}
939
940QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface, KWayland::Client::Output *output, MockInputMethod::Mode mode)
941{
942 if (!s_waylandConnection.inputPanelV1) {
943 qWarning() << "Unable to create the input panel surface. The interface input_panel global is not bound";
944 return nullptr;
945 }
946 QtWayland::zwp_input_panel_surface_v1 *s = new QtWayland::zwp_input_panel_surface_v1(s_waylandConnection.inputPanelV1->get_input_panel_surface(*surface));
947
948 if (!s->isInitialized()) {
949 delete s;
950 return nullptr;
951 }
952
953 switch (mode) {
955 s->set_toplevel(output->output(), QtWayland::zwp_input_panel_surface_v1::position_center_bottom);
956 break;
958 s->set_overlay_panel();
959 break;
960 }
961
962 return s;
963}
964
965FractionalScaleV1 *createFractionalScaleV1(KWayland::Client::Surface *surface)
966{
967 if (!s_waylandConnection.fractionalScaleManagerV1) {
968 qWarning() << "Unable to create fractional scale surface. The global is not bound";
969 return nullptr;
970 }
971 auto scale = new FractionalScaleV1();
972 scale->init(s_waylandConnection.fractionalScaleManagerV1->get_fractional_scale(*surface));
973
974 return scale;
975}
976
977static void waitForConfigured(XdgSurface *shellSurface)
978{
979 QSignalSpy surfaceConfigureRequestedSpy(shellSurface, &XdgSurface::configureRequested);
980
981 shellSurface->surface()->commit(KWayland::Client::Surface::CommitFlag::None);
982 QVERIFY(surfaceConfigureRequestedSpy.wait());
983
984 shellSurface->ack_configure(surfaceConfigureRequestedSpy.last().first().toUInt());
985}
986
987XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent)
988{
990}
991
992XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode, QObject *parent)
993{
994 XdgShell *shell = s_waylandConnection.xdgShell;
995
996 if (!shell) {
997 qWarning() << "Could not create an xdg_toplevel surface because xdg_wm_base global is not bound";
998 return nullptr;
999 }
1000
1001 XdgSurface *xdgSurface = new XdgSurface(shell, surface);
1002 XdgToplevel *xdgToplevel = new XdgToplevel(xdgSurface, parent);
1003
1004 if (configureMode == CreationSetup::CreateAndConfigure) {
1005 waitForConfigured(xdgSurface);
1006 }
1007
1008 return xdgToplevel;
1009}
1010
1012{
1013 XdgShell *shell = s_waylandConnection.xdgShell;
1014
1015 if (!shell) {
1016 qWarning() << "Could not create an xdg_positioner object because xdg_wm_base global is not bound";
1017 return nullptr;
1018 }
1019
1020 return new XdgPositioner(shell);
1021}
1022
1023XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner,
1024 CreationSetup configureMode, QObject *parent)
1025{
1026 XdgShell *shell = s_waylandConnection.xdgShell;
1027
1028 if (!shell) {
1029 qWarning() << "Could not create an xdg_popup surface because xdg_wm_base global is not bound";
1030 return nullptr;
1031 }
1032
1033 XdgSurface *xdgSurface = new XdgSurface(shell, surface);
1034 XdgPopup *xdgPopup = new XdgPopup(xdgSurface, parentSurface, positioner, parent);
1035
1036 if (configureMode == CreationSetup::CreateAndConfigure) {
1037 waitForConfigured(xdgSurface);
1038 }
1039
1040 return xdgPopup;
1041}
1042
1044{
1045 XdgDecorationManagerV1 *manager = s_waylandConnection.xdgDecorationManagerV1;
1046
1047 if (!manager) {
1048 qWarning() << "Could not create an xdg_toplevel_decoration_v1 because xdg_decoration_manager_v1 global is not bound";
1049 return nullptr;
1050 }
1051
1052 return new XdgToplevelDecorationV1(manager, toplevel, parent);
1053}
1054
1055IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface)
1056{
1057 IdleInhibitManagerV1 *manager = s_waylandConnection.idleInhibitManagerV1;
1058 if (!manager) {
1059 qWarning() << "Could not create an idle_inhibitor_v1 because idle_inhibit_manager_v1 global is not bound";
1060 return nullptr;
1061 }
1062
1063 return new IdleInhibitorV1(manager, surface);
1064}
1065
1066AutoHideScreenEdgeV1 *createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border)
1067{
1068 ScreenEdgeManagerV1 *manager = s_waylandConnection.screenEdgeManagerV1;
1069 if (!manager) {
1070 qWarning() << "Could not create an kde_auto_hide_screen_edge_v1 because kde_screen_edge_manager_v1 global is not bound";
1071 return nullptr;
1072 }
1073
1074 return new AutoHideScreenEdgeV1(manager, surface, border);
1075}
1076
1077CursorShapeDeviceV1 *createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer)
1078{
1079 CursorShapeManagerV1 *manager = s_waylandConnection.cursorShapeManagerV1;
1080 if (!manager) {
1081 qWarning() << "Could not create a wp_cursor_shape_device_v1 because wp_cursor_shape_manager_v1 global is not bound";
1082 return nullptr;
1083 }
1084
1085 return new CursorShapeDeviceV1(manager, pointer);
1086}
1087
1089{
1090 QSignalSpy closedSpy(window, &Window::closed);
1091 if (!closedSpy.isValid()) {
1092 return false;
1093 }
1094 return closedSpy.wait();
1095}
1096
1097#if KWIN_BUILD_SCREENLOCKER
1098bool lockScreen()
1099{
1100 if (waylandServer()->isScreenLocked()) {
1101 return false;
1102 }
1103 QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
1104 if (!lockStateChangedSpy.isValid()) {
1105 return false;
1106 }
1107 ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate);
1108 if (lockStateChangedSpy.count() != 1) {
1109 return false;
1110 }
1111 if (!waylandServer()->isScreenLocked()) {
1112 return false;
1113 }
1114 if (!kwinApp()->screenLockerWatcher()->isLocked()) {
1115 QSignalSpy lockedSpy(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked);
1116 if (!lockedSpy.isValid()) {
1117 return false;
1118 }
1119 if (!lockedSpy.wait()) {
1120 return false;
1121 }
1122 if (!kwinApp()->screenLockerWatcher()->isLocked()) {
1123 return false;
1124 }
1125 }
1126 return true;
1127}
1128
1129bool unlockScreen()
1130{
1131 QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged);
1132 if (!lockStateChangedSpy.isValid()) {
1133 return false;
1134 }
1135 using namespace ScreenLocker;
1136 const auto children = KSldApp::self()->children();
1137 for (auto it = children.begin(); it != children.end(); ++it) {
1138 if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) {
1139 continue;
1140 }
1141 QMetaObject::invokeMethod(*it, "requestUnlock");
1142 break;
1143 }
1144 if (waylandServer()->isScreenLocked()) {
1145 lockStateChangedSpy.wait();
1146 }
1147 if (waylandServer()->isScreenLocked()) {
1148 return true;
1149 }
1150 if (kwinApp()->screenLockerWatcher()->isLocked()) {
1151 QSignalSpy lockedSpy(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked);
1152 if (!lockedSpy.isValid()) {
1153 return false;
1154 }
1155 if (!lockedSpy.wait()) {
1156 return false;
1157 }
1158 if (kwinApp()->screenLockerWatcher()->isLocked()) {
1159 return false;
1160 }
1161 }
1162 return true;
1163}
1164#endif // KWIN_BUILD_LOCKSCREEN
1165
1167{
1168 const int deviceCount = drmGetDevices2(0, nullptr, 0);
1169 if (deviceCount <= 0) {
1170 return false;
1171 }
1172
1173 QList<drmDevice *> devices(deviceCount);
1174 if (drmGetDevices2(0, devices.data(), devices.size()) < 0) {
1175 return false;
1176 }
1177 auto deviceCleanup = qScopeGuard([&devices]() {
1178 drmFreeDevices(devices.data(), devices.size());
1179 });
1180
1181 return std::any_of(devices.constBegin(), devices.constEnd(), [](drmDevice *device) {
1182 return device->available_nodes & (1 << DRM_NODE_RENDER);
1183 });
1184}
1185
1186void XcbConnectionDeleter::operator()(xcb_connection_t *pointer)
1187{
1188 xcb_disconnect(pointer);
1189};
1190
1192{
1194 QEventLoop e;
1195 e.connect(&watcher, &QFutureWatcher<xcb_connection_t *>::finished, &e, &QEventLoop::quit);
1196 QFuture<xcb_connection_t *> future = QtConcurrent::run([]() {
1197 return xcb_connect(nullptr, nullptr);
1198 });
1199 watcher.setFuture(future);
1200 e.exec();
1201 return Test::XcbConnectionPtr(future.result());
1202}
1203
1205 : QObject()
1206 , QtWayland::kde_output_management_v2()
1207{
1208 init(registry, id, version);
1209}
1210
1215
1216WaylandOutputConfigurationV2::WaylandOutputConfigurationV2(struct ::kde_output_configuration_v2 *object)
1217 : QObject()
1218 , QtWayland::kde_output_configuration_v2()
1219{
1220 init(object);
1221}
1222
1231
1232WaylandOutputDeviceV2Mode::WaylandOutputDeviceV2Mode(struct ::kde_output_device_mode_v2 *object)
1233 : QtWayland::kde_output_device_mode_v2(object)
1234{
1235}
1236
1238{
1239 kde_output_device_mode_v2_destroy(object());
1240}
1241
1243{
1244 m_size = QSize(width, height);
1245}
1246
1248{
1249 m_refreshRate = refresh;
1250}
1251
1253{
1254 m_preferred = true;
1255}
1256
1261
1263{
1264 return m_refreshRate;
1265}
1266
1268{
1269 return m_size;
1270}
1271
1273{
1274 return m_preferred;
1275}
1276
1278{
1279 return m_size == other.m_size && m_refreshRate == other.m_refreshRate && m_preferred == other.m_preferred;
1280}
1281
1282WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2Mode::get(struct ::kde_output_device_mode_v2 *object)
1283{
1284 auto mode = QtWayland::kde_output_device_mode_v2::fromObject(object);
1285 return static_cast<WaylandOutputDeviceV2Mode *>(mode);
1286}
1287
1289 : QObject()
1290 , kde_output_device_v2()
1291 , m_id(id)
1292{
1293}
1294
1296{
1297 qDeleteAll(m_modes);
1298
1299 kde_output_device_v2_destroy(object());
1300}
1301
1303 int32_t y,
1304 int32_t physical_width,
1305 int32_t physical_height,
1306 int32_t subpixel,
1307 const QString &make,
1308 const QString &model,
1309 int32_t transform)
1310{
1311 m_pos = QPoint(x, y);
1312 m_physicalSize = QSize(physical_width, physical_height);
1313 m_subpixel = subpixel;
1314 m_manufacturer = make;
1315 m_model = model;
1316 m_transform = transform;
1317}
1318
1319void WaylandOutputDeviceV2::kde_output_device_v2_current_mode(struct ::kde_output_device_mode_v2 *mode)
1320{
1321 auto m = WaylandOutputDeviceV2Mode::get(mode);
1322
1323 if (*m == *m_mode) {
1324 // unchanged
1325 return;
1326 }
1327 m_mode = m;
1328}
1329
1330void WaylandOutputDeviceV2::kde_output_device_v2_mode(struct ::kde_output_device_mode_v2 *mode)
1331{
1333 // last mode sent is the current one
1334 m_mode = m;
1335 m_modes.append(m);
1336
1337 connect(m, &WaylandOutputDeviceV2Mode::removed, this, [this, m]() {
1338 m_modes.removeOne(m);
1339 if (m_mode == m) {
1340 if (!m_modes.isEmpty()) {
1341 m_mode = m_modes.first();
1342 } else {
1343 // was last mode
1344 qFatal("KWaylandBackend: no output modes available anymore, this seems like a compositor bug");
1345 }
1346 }
1347
1348 delete m;
1349 });
1350}
1351
1353{
1354 return QString::number(m_modes.indexOf(m_mode));
1355}
1356
1357WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2::deviceModeFromId(const int modeId) const
1358{
1359 return m_modes.at(modeId);
1360}
1361
1362QString WaylandOutputDeviceV2::modeName(const WaylandOutputDeviceV2Mode *m) const
1363{
1364 return QString::number(m->size().width()) + QLatin1Char('x') + QString::number(m->size().height()) + QLatin1Char('@')
1365 + QString::number(qRound(m->refreshRate() / 1000.0));
1366}
1367
1369{
1370 return QStringLiteral("%1 %2").arg(m_manufacturer, m_model);
1371}
1372
1373QDebug operator<<(QDebug dbg, const WaylandOutputDeviceV2 *output)
1374{
1375 dbg << "WaylandOutput(Id:" << output->id() << ", Name:" << QString(output->manufacturer() + QLatin1Char(' ') + output->model()) << ")";
1376 return dbg;
1377}
1378
1383
1385{
1386 m_factor = wl_fixed_to_double(factor);
1387}
1388
1390{
1391 m_edid = QByteArray::fromBase64(edid.toUtf8());
1392}
1393
1395{
1396 if (m_enabled != enabled) {
1397 m_enabled = enabled;
1398 Q_EMIT enabledChanged();
1399 }
1400}
1401
1403{
1404 m_uuid = uuid;
1405}
1406
1408{
1409 m_serialNumber = serialNumber;
1410}
1411
1413{
1414 m_eisaId = eisaId;
1415}
1416
1418{
1419 m_flags = flags;
1420}
1421
1423{
1424 m_overscan = overscan;
1425}
1426
1428{
1429 m_vrr_policy = vrr_policy;
1430}
1431
1433{
1434 m_rgbRange = rgb_range;
1435}
1436
1438{
1439 return m_edid;
1440}
1441
1443{
1444 return m_enabled;
1445}
1446
1448{
1449 return m_id;
1450}
1451
1453{
1454 return m_factor;
1455}
1456
1458{
1459 return m_manufacturer;
1460}
1461
1463{
1464 return m_model;
1465}
1466
1468{
1469 return m_pos;
1470}
1471
1473{
1474 return m_mode->size();
1475}
1476
1478{
1479 return m_mode->refreshRate();
1480}
1481
1483{
1484 return m_vrr_policy;
1485}
1486
1488{
1489 return m_overscan;
1490}
1491
1493{
1494 return m_flags;
1495}
1496
1498{
1499 return m_rgbRange;
1500}
1501
1503 : InputDevice(parent)
1504{
1505}
1506
1508{
1509 m_pointer = set;
1510}
1511
1513{
1514 m_keyboard = set;
1515}
1516
1518{
1519 m_touch = set;
1520}
1521
1523{
1524 m_lidSwitch = set;
1525}
1526
1527void VirtualInputDevice::setName(const QString &name)
1528{
1529 m_name = name;
1530}
1531
1533{
1534 return QString();
1535}
1536
1538{
1539 return m_name;
1540}
1541
1543{
1544 return true;
1545}
1546
1548{
1549}
1550
1552{
1553 return LEDs();
1554}
1555
1557{
1558}
1559
1561{
1562 return m_keyboard;
1563}
1564
1566{
1567 return m_pointer;
1568}
1569
1571{
1572 return false;
1573}
1574
1576{
1577 return m_touch;
1578}
1579
1581{
1582 return false;
1583}
1584
1586{
1587 return false;
1588}
1589
1591{
1592 return false;
1593}
1594
1596{
1597 return m_lidSwitch;
1598}
1599
1600void keyboardKeyPressed(quint32 key, quint32 time)
1601{
1602 auto virtualKeyboard = static_cast<WaylandTestApplication *>(kwinApp())->virtualKeyboard();
1603 Q_EMIT virtualKeyboard->keyChanged(key, InputRedirection::KeyboardKeyState::KeyboardKeyPressed, std::chrono::milliseconds(time), virtualKeyboard);
1604}
1605
1606void keyboardKeyReleased(quint32 key, quint32 time)
1607{
1608 auto virtualKeyboard = static_cast<WaylandTestApplication *>(kwinApp())->virtualKeyboard();
1609 Q_EMIT virtualKeyboard->keyChanged(key, InputRedirection::KeyboardKeyState::KeyboardKeyReleased, std::chrono::milliseconds(time), virtualKeyboard);
1610}
1611
1612void pointerAxisHorizontal(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source)
1613{
1614 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1615 Q_EMIT virtualPointer->pointerAxisChanged(InputRedirection::PointerAxis::PointerAxisHorizontal, delta, discreteDelta, source, std::chrono::milliseconds(time), virtualPointer);
1616 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1617}
1618
1619void pointerAxisVertical(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source)
1620{
1621 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1622 Q_EMIT virtualPointer->pointerAxisChanged(InputRedirection::PointerAxis::PointerAxisVertical, delta, discreteDelta, source, std::chrono::milliseconds(time), virtualPointer);
1623 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1624}
1625
1626void pointerButtonPressed(quint32 button, quint32 time)
1627{
1628 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1629 Q_EMIT virtualPointer->pointerButtonChanged(button, InputRedirection::PointerButtonState::PointerButtonPressed, std::chrono::milliseconds(time), virtualPointer);
1630 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1631}
1632
1633void pointerButtonReleased(quint32 button, quint32 time)
1634{
1635 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1636 Q_EMIT virtualPointer->pointerButtonChanged(button, InputRedirection::PointerButtonState::PointerButtonReleased, std::chrono::milliseconds(time), virtualPointer);
1637 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1638}
1639
1640void pointerMotion(const QPointF &position, quint32 time)
1641{
1642 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1643 Q_EMIT virtualPointer->pointerMotionAbsolute(position, std::chrono::milliseconds(time), virtualPointer);
1644 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1645}
1646
1647void pointerMotionRelative(const QPointF &delta, quint32 time)
1648{
1649 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer();
1650 Q_EMIT virtualPointer->pointerMotion(delta, delta, std::chrono::milliseconds(time), virtualPointer);
1651 Q_EMIT virtualPointer->pointerFrame(virtualPointer);
1652}
1653
1655{
1656 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch();
1657 Q_EMIT virtualTouch->touchCanceled(virtualTouch);
1658}
1659
1660void touchDown(qint32 id, const QPointF &pos, quint32 time)
1661{
1662 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch();
1663 Q_EMIT virtualTouch->touchDown(id, pos, std::chrono::milliseconds(time), virtualTouch);
1664}
1665
1666void touchMotion(qint32 id, const QPointF &pos, quint32 time)
1667{
1668 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch();
1669 Q_EMIT virtualTouch->touchMotion(id, pos, std::chrono::milliseconds(time), virtualTouch);
1670}
1671
1672void touchUp(qint32 id, quint32 time)
1673{
1674 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch();
1675 Q_EMIT virtualTouch->touchUp(id, std::chrono::milliseconds(time), virtualTouch);
1676}
1677}
1678}
1679
1680#include "test_helpers.moc"
ClientConnection * createClient(int fd)
Definition display.cpp:228
void locked(bool locked)
AutoHideScreenEdgeV1(ScreenEdgeManagerV1 *manager, KWayland::Client::Surface *surface, uint32_t border)
CursorShapeDeviceV1(CursorShapeManagerV1 *manager, KWayland::Client::Pointer *pointer)
IdleInhibitorV1(IdleInhibitManagerV1 *manager, KWayland::Client::Surface *surface)
void zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) override
void zwlr_layer_surface_v1_closed() override
void configureRequested(quint32 serial, const QSize &size)
void zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context) override
MockInputMethod(struct wl_registry *registry, int id, int version)
void zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context) override
QString sysName() const override
bool isTouchpad() const override
void setName(const QString &name)
bool isTabletModeSwitch() const override
VirtualInputDevice(QObject *parent=nullptr)
bool isTabletTool() const override
bool isKeyboard() const override
bool isPointer() const override
bool isTouch() const override
QString name() const override
void setLeds(LEDs leds) override
void setEnabled(bool enabled) override
bool isEnabled() const override
bool isTabletPad() const override
bool isLidSwitch() const override
WaylandOutputConfigurationV2(struct ::kde_output_configuration_v2 *object)
void kde_output_device_v2_uuid(const QString &uuid) override
void kde_output_device_v2_eisa_id(const QString &eisaId) override
void kde_output_device_v2_scale(wl_fixed_t factor) override
void kde_output_device_v2_capabilities(uint32_t flags) override
void 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) override
void kde_output_device_v2_mode(struct ::kde_output_device_mode_v2 *mode) override
void kde_output_device_v2_overscan(uint32_t overscan) override
void kde_output_device_v2_enabled(int32_t enabled) override
void kde_output_device_v2_edid(const QString &raw) override
void kde_output_device_v2_rgb_range(uint32_t rgb_range) override
void kde_output_device_v2_serial_number(const QString &serialNumber) override
void kde_output_device_v2_vrr_policy(uint32_t vrr_policy) override
void kde_output_device_v2_current_mode(struct ::kde_output_device_mode_v2 *mode) override
WaylandOutputDeviceV2Mode(struct ::kde_output_device_mode_v2 *object)
bool operator==(const WaylandOutputDeviceV2Mode &other) const
void kde_output_device_mode_v2_refresh(int32_t refresh) override
void kde_output_device_mode_v2_size(int32_t width, int32_t height) override
static WaylandOutputDeviceV2Mode * get(struct ::kde_output_device_mode_v2 *object)
WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version)
WaylandOutputConfigurationV2 * createConfiguration()
WaylandSyncPoint(KWayland::Client::ConnectionThread *connection, KWayland::Client::EventQueue *eventQueue)
XdgPopup(XdgSurface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, QObject *parent=nullptr)
void configureRequested(const QRect &rect)
void xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height) override
XdgSurface * xdgSurface() const
void xdg_popup_popup_done() override
void xdg_surface_configure(uint32_t serial) override
KWayland::Client::Surface * surface() const
void configureRequested(quint32 serial)
XdgSurface(XdgShell *shell, KWayland::Client::Surface *surface, QObject *parent=nullptr)
void configureRequested(QtWayland::zxdg_toplevel_decoration_v1::mode mode)
XdgToplevelDecorationV1(XdgDecorationManagerV1 *manager, XdgToplevel *toplevel, QObject *parent=nullptr)
void zxdg_toplevel_decoration_v1_configure(uint32_t mode) override
XdgSurface * xdgSurface() const
void xdg_toplevel_close() override
void xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states) override
void configureRequested(const QSize &size, KWin::Test::XdgToplevel::States states)
XdgToplevel(XdgSurface *surface, QObject *parent=nullptr)
Display * display() const
SurfaceInterface * surface() const
Definition window.cpp:342
void surfaceChanged()
void windowAdded(KWin::Window *)
WaylandOutputManagementV2 * outputManagementV2
WaylandOutputManagementV2 * waylandOutputManagementV2()
XdgPositioner * createXdgPositioner()
Window * renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32, int timeout=5000)
void keyboardKeyReleased(quint32 key, quint32 time)
XdgPopup * createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, CreationSetup configureMode=CreationSetup::CreateAndConfigure, QObject *parent=nullptr)
void destroyWaylandConnection()
KWayland::Client::Seat * seat
KWayland::Client::ShmPool * shm
KWayland::Client::EventQueue * queue
SecurityContextManagerV1 * securityContextManagerV1
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void pointerAxisVertical(qreal delta, quint32 time, qint32 discreteDelta=0, InputRedirection::PointerAxisSource source=InputRedirection::PointerAxisSourceUnknown)
void keyboardKeyPressed(quint32 key, quint32 time)
FakeInput * fakeInput
TextInputManagerV3 * waylandTextInputManagerV3()
QtWayland::zwp_input_panel_surface_v1 * createInputPanelSurfaceV1(KWayland::Client::Surface *surface, KWayland::Client::Output *output, MockInputMethod::Mode mode)
bool waitForWaylandKeyboard()
QtWayland::zwp_input_panel_v1 * inputPanelV1
QList< WaylandOutputDeviceV2 * > waylandOutputDevicesV2()
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
KWayland::Client::PlasmaWindowManagement * waylandWindowManagement()
KWayland::Client::PlasmaWindowManagement * windowManagement
KWayland::Client::Compositor * waylandCompositor()
KWayland::Client::ShadowManager * shadowManager
FractionalScaleManagerV1 * fractionalScaleManagerV1
ScreencastingV1 * screencastingV1
KWayland::Client::SubCompositor * waylandSubCompositor()
MockInputMethod * inputMethodV1
KWayland::Client::PointerConstraints * waylandPointerConstraints()
void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32_Premultiplied)
KWayland::Client::PlasmaShell * plasmaShell
KWayland::Client::SubCompositor * subCompositor
bool waitForWaylandSurface(Window *window)
void pointerAxisHorizontal(qreal delta, quint32 time, qint32 discreteDelta=0, InputRedirection::PointerAxisSource source=InputRedirection::PointerAxisSourceUnknown)
KWayland::Client::Seat * waylandSeat()
LayerSurfaceV1 * createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output=nullptr, LayerShellV1::layer layer=LayerShellV1::layer_top)
SecurityContextManagerV1 * waylandSecurityContextManagerV1()
KWayland::Client::Registry * registry
ScreencastingV1 * screencasting()
Window * waitForWaylandWindowShown(int timeout=5000)
XdgShell * xdgShell
bool waitForWaylandTouch()
AutoHideScreenEdgeV1 * createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border)
KWayland::Client::TextInputManager * textInputManager
MockInputMethod * inputMethod()
KWayland::Client::AppMenuManager * appMenu
QList< KWayland::Client::Output * > waylandOutputs()
KWayland::Client::Surface * inputPanelSurface()
void pointerButtonPressed(quint32 button, quint32 time)
bool unlockScreen()
QThread * thread
KWayland::Client::ShadowManager * waylandShadowManager()
XcbConnectionPtr createX11Connection()
QList< KWayland::Client::Output * > outputs
void pointerMotion(const QPointF &position, quint32 time)
CursorShapeManagerV1 * cursorShapeManagerV1
bool renderNodeAvailable()
QList< WaylandOutputDeviceV2 * > outputDevicesV2
KWayland::Client::PointerConstraints * pointerConstraints
std::unique_ptr< KWayland::Client::Surface > createSurface()
KWayland::Client::ShmPool * waylandShmPool()
void pointerMotionRelative(const QPointF &delta, quint32 time)
LayerShellV1 * layerShellV1
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
IdleInhibitManagerV1 * idleInhibitManagerV1
IdleInhibitorV1 * createIdleInhibitorV1(KWayland::Client::Surface *surface)
XdgToplevelDecorationV1 * createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent=nullptr)
KWayland::Client::AppMenuManager * waylandAppMenuManager()
FractionalScaleV1 * createFractionalScaleV1(KWayland::Client::Surface *surface)
KWayland::Client::SubSurface * createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface, QObject *parent=nullptr)
bool waylandSync()
bool waitForWaylandPointer()
bool lockScreen()
KWayland::Client::ConnectionThread * waylandConnection()
QtWayland::zwp_input_method_context_v1 * inputMethodContextV1
KWayland::Client::TextInputManager * waylandTextInputManager()
void pointerButtonReleased(quint32 button, quint32 time)
void touchUp(qint32 id, quint32 time)
CursorShapeDeviceV1 * createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer)
ScreenEdgeManagerV1 * screenEdgeManagerV1
KWayland::Client::ConnectionThread * connection
QDebug operator<<(QDebug dbg, const WaylandOutputDeviceV2 *output)
void flushWaylandConnection()
KWayland::Client::PlasmaShell * waylandPlasmaShell()
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
KWayland::Client::Compositor * compositor
bool waitForWindowClosed(Window *window)
TextInputManagerV3 * textInputManagerV3
KWayland::Client::Output * waylandOutput(const QString &name)
FakeInput * waylandFakeInput()
XdgDecorationManagerV1 * xdgDecorationManagerV1
constexpr int version
GLenum format
Definition gltexture.cpp:49
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
void operator()(xcb_connection_t *pointer)