Warning, file /plasma/kwin/autotests/integration/test_helpers.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include <config-kwin.h> 0010 0011 #include "kwin_wayland_test.h" 0012 0013 #if KWIN_BUILD_SCREENLOCKER 0014 #include "screenlockerwatcher.h" 0015 #endif 0016 #include "inputmethod.h" 0017 #include "wayland/display.h" 0018 #include "wayland_server.h" 0019 #include "workspace.h" 0020 0021 #include <KWayland/Client/appmenu.h> 0022 #include <KWayland/Client/compositor.h> 0023 #include <KWayland/Client/connection_thread.h> 0024 #include <KWayland/Client/event_queue.h> 0025 #include <KWayland/Client/output.h> 0026 #include <KWayland/Client/plasmashell.h> 0027 #include <KWayland/Client/plasmawindowmanagement.h> 0028 #include <KWayland/Client/pointerconstraints.h> 0029 #include <KWayland/Client/registry.h> 0030 #include <KWayland/Client/seat.h> 0031 #include <KWayland/Client/server_decoration.h> 0032 #include <KWayland/Client/shadow.h> 0033 #include <KWayland/Client/shm_pool.h> 0034 #include <KWayland/Client/subcompositor.h> 0035 #include <KWayland/Client/subsurface.h> 0036 #include <KWayland/Client/surface.h> 0037 #include <KWayland/Client/textinput.h> 0038 0039 // screenlocker 0040 #if KWIN_BUILD_SCREENLOCKER 0041 #include <KScreenLocker/KsldApp> 0042 #endif 0043 0044 #include <QThread> 0045 0046 // system 0047 #include <sys/socket.h> 0048 #include <sys/types.h> 0049 #include <unistd.h> 0050 0051 namespace KWin 0052 { 0053 namespace Test 0054 { 0055 0056 LayerShellV1::~LayerShellV1() 0057 { 0058 destroy(); 0059 } 0060 0061 LayerSurfaceV1::~LayerSurfaceV1() 0062 { 0063 destroy(); 0064 } 0065 0066 void LayerSurfaceV1::zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) 0067 { 0068 Q_EMIT configureRequested(serial, QSize(width, height)); 0069 } 0070 0071 void LayerSurfaceV1::zwlr_layer_surface_v1_closed() 0072 { 0073 Q_EMIT closeRequested(); 0074 } 0075 0076 XdgShell::~XdgShell() 0077 { 0078 destroy(); 0079 } 0080 0081 XdgSurface::XdgSurface(XdgShell *shell, KWayland::Client::Surface *surface, QObject *parent) 0082 : QObject(parent) 0083 , QtWayland::xdg_surface(shell->get_xdg_surface(*surface)) 0084 , m_surface(surface) 0085 { 0086 } 0087 0088 XdgSurface::~XdgSurface() 0089 { 0090 destroy(); 0091 } 0092 0093 KWayland::Client::Surface *XdgSurface::surface() const 0094 { 0095 return m_surface; 0096 } 0097 0098 void XdgSurface::xdg_surface_configure(uint32_t serial) 0099 { 0100 Q_EMIT configureRequested(serial); 0101 } 0102 0103 XdgToplevel::XdgToplevel(XdgSurface *surface, QObject *parent) 0104 : QObject(parent) 0105 , QtWayland::xdg_toplevel(surface->get_toplevel()) 0106 , m_xdgSurface(surface) 0107 { 0108 } 0109 0110 XdgToplevel::~XdgToplevel() 0111 { 0112 destroy(); 0113 } 0114 0115 XdgSurface *XdgToplevel::xdgSurface() const 0116 { 0117 return m_xdgSurface.get(); 0118 } 0119 0120 void XdgToplevel::xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states) 0121 { 0122 States requestedStates; 0123 0124 const uint32_t *stateData = static_cast<const uint32_t *>(states->data); 0125 const size_t stateCount = states->size / sizeof(uint32_t); 0126 0127 for (size_t i = 0; i < stateCount; ++i) { 0128 switch (stateData[i]) { 0129 case QtWayland::xdg_toplevel::state_maximized: 0130 requestedStates |= State::Maximized; 0131 break; 0132 case QtWayland::xdg_toplevel::state_fullscreen: 0133 requestedStates |= State::Fullscreen; 0134 break; 0135 case QtWayland::xdg_toplevel::state_resizing: 0136 requestedStates |= State::Resizing; 0137 break; 0138 case QtWayland::xdg_toplevel::state_activated: 0139 requestedStates |= State::Activated; 0140 break; 0141 } 0142 } 0143 0144 Q_EMIT configureRequested(QSize(width, height), requestedStates); 0145 } 0146 0147 void XdgToplevel::xdg_toplevel_close() 0148 { 0149 Q_EMIT closeRequested(); 0150 } 0151 0152 XdgPositioner::XdgPositioner(XdgShell *shell) 0153 : QtWayland::xdg_positioner(shell->create_positioner()) 0154 { 0155 } 0156 0157 XdgPositioner::~XdgPositioner() 0158 { 0159 destroy(); 0160 } 0161 0162 XdgPopup::XdgPopup(XdgSurface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, QObject *parent) 0163 : QObject(parent) 0164 , QtWayland::xdg_popup(surface->get_popup(parentSurface->object(), positioner->object())) 0165 , m_xdgSurface(surface) 0166 { 0167 } 0168 0169 XdgPopup::~XdgPopup() 0170 { 0171 destroy(); 0172 } 0173 0174 XdgSurface *XdgPopup::xdgSurface() const 0175 { 0176 return m_xdgSurface.get(); 0177 } 0178 0179 void XdgPopup::xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height) 0180 { 0181 Q_EMIT configureRequested(QRect(x, y, width, height)); 0182 } 0183 0184 void XdgPopup::xdg_popup_popup_done() 0185 { 0186 Q_EMIT doneReceived(); 0187 } 0188 0189 XdgDecorationManagerV1::~XdgDecorationManagerV1() 0190 { 0191 destroy(); 0192 } 0193 0194 XdgToplevelDecorationV1::XdgToplevelDecorationV1(XdgDecorationManagerV1 *manager, 0195 XdgToplevel *toplevel, QObject *parent) 0196 : QObject(parent) 0197 , QtWayland::zxdg_toplevel_decoration_v1(manager->get_toplevel_decoration(toplevel->object())) 0198 { 0199 } 0200 0201 XdgToplevelDecorationV1::~XdgToplevelDecorationV1() 0202 { 0203 destroy(); 0204 } 0205 0206 void XdgToplevelDecorationV1::zxdg_toplevel_decoration_v1_configure(uint32_t m) 0207 { 0208 Q_EMIT configureRequested(mode(m)); 0209 } 0210 0211 IdleInhibitManagerV1::~IdleInhibitManagerV1() 0212 { 0213 destroy(); 0214 } 0215 0216 IdleInhibitorV1::IdleInhibitorV1(IdleInhibitManagerV1 *manager, KWayland::Client::Surface *surface) 0217 : QtWayland::zwp_idle_inhibitor_v1(manager->create_inhibitor(*surface)) 0218 { 0219 } 0220 0221 IdleInhibitorV1::~IdleInhibitorV1() 0222 { 0223 destroy(); 0224 } 0225 0226 static struct 0227 { 0228 KWayland::Client::ConnectionThread *connection = nullptr; 0229 KWayland::Client::EventQueue *queue = nullptr; 0230 KWayland::Client::Compositor *compositor = nullptr; 0231 KWayland::Client::SubCompositor *subCompositor = nullptr; 0232 KWayland::Client::ServerSideDecorationManager *decoration = nullptr; 0233 KWayland::Client::ShadowManager *shadowManager = nullptr; 0234 XdgShell *xdgShell = nullptr; 0235 KWayland::Client::ShmPool *shm = nullptr; 0236 KWayland::Client::Seat *seat = nullptr; 0237 KWayland::Client::PlasmaShell *plasmaShell = nullptr; 0238 KWayland::Client::PlasmaWindowManagement *windowManagement = nullptr; 0239 KWayland::Client::PointerConstraints *pointerConstraints = nullptr; 0240 KWayland::Client::Registry *registry = nullptr; 0241 WaylandOutputManagementV2 *outputManagementV2 = nullptr; 0242 QThread *thread = nullptr; 0243 QVector<KWayland::Client::Output *> outputs; 0244 QVector<WaylandOutputDeviceV2 *> outputDevicesV2; 0245 IdleInhibitManagerV1 *idleInhibitManagerV1 = nullptr; 0246 KWayland::Client::AppMenuManager *appMenu = nullptr; 0247 XdgDecorationManagerV1 *xdgDecorationManagerV1 = nullptr; 0248 KWayland::Client::TextInputManager *textInputManager = nullptr; 0249 QtWayland::zwp_input_panel_v1 *inputPanelV1 = nullptr; 0250 MockInputMethod *inputMethodV1 = nullptr; 0251 QtWayland::zwp_input_method_context_v1 *inputMethodContextV1 = nullptr; 0252 LayerShellV1 *layerShellV1 = nullptr; 0253 TextInputManagerV3 *textInputManagerV3 = nullptr; 0254 FractionalScaleManagerV1 *fractionalScaleManagerV1 = nullptr; 0255 } s_waylandConnection; 0256 0257 MockInputMethod *inputMethod() 0258 { 0259 return s_waylandConnection.inputMethodV1; 0260 } 0261 0262 KWayland::Client::Surface *inputPanelSurface() 0263 { 0264 return s_waylandConnection.inputMethodV1->inputPanelSurface(); 0265 } 0266 0267 MockInputMethod::MockInputMethod(struct wl_registry *registry, int id, int version) 0268 : QtWayland::zwp_input_method_v1(registry, id, version) 0269 { 0270 } 0271 MockInputMethod::~MockInputMethod() 0272 { 0273 } 0274 0275 void MockInputMethod::zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context) 0276 { 0277 if (!m_inputSurface) { 0278 m_inputSurface = Test::createSurface(); 0279 m_inputMethodSurface = Test::createInputPanelSurfaceV1(m_inputSurface.get(), s_waylandConnection.outputs.first()); 0280 } 0281 m_context = context; 0282 Test::render(m_inputSurface.get(), QSize(1280, 400), Qt::blue); 0283 0284 Q_EMIT activate(); 0285 } 0286 0287 void MockInputMethod::zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context) 0288 { 0289 QCOMPARE(context, m_context); 0290 zwp_input_method_context_v1_destroy(context); 0291 m_context = nullptr; 0292 0293 if (m_inputSurface) { 0294 m_inputSurface->release(); 0295 m_inputSurface->destroy(); 0296 m_inputSurface.reset(); 0297 delete m_inputMethodSurface; 0298 m_inputMethodSurface = nullptr; 0299 } 0300 } 0301 0302 bool setupWaylandConnection(AdditionalWaylandInterfaces flags) 0303 { 0304 if (s_waylandConnection.connection) { 0305 return false; 0306 } 0307 0308 int sx[2]; 0309 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) { 0310 return false; 0311 } 0312 KWin::waylandServer()->display()->createClient(sx[0]); 0313 // setup connection 0314 s_waylandConnection.connection = new KWayland::Client::ConnectionThread; 0315 QSignalSpy connectedSpy(s_waylandConnection.connection, &KWayland::Client::ConnectionThread::connected); 0316 if (!connectedSpy.isValid()) { 0317 return false; 0318 } 0319 s_waylandConnection.connection->setSocketFd(sx[1]); 0320 0321 s_waylandConnection.thread = new QThread(kwinApp()); 0322 s_waylandConnection.connection->moveToThread(s_waylandConnection.thread); 0323 s_waylandConnection.thread->start(); 0324 0325 s_waylandConnection.connection->initConnection(); 0326 if (!connectedSpy.wait()) { 0327 return false; 0328 } 0329 0330 s_waylandConnection.queue = new KWayland::Client::EventQueue; 0331 s_waylandConnection.queue->setup(s_waylandConnection.connection); 0332 if (!s_waylandConnection.queue->isValid()) { 0333 return false; 0334 } 0335 0336 KWayland::Client::Registry *registry = new KWayland::Client::Registry; 0337 s_waylandConnection.registry = registry; 0338 registry->setEventQueue(s_waylandConnection.queue); 0339 0340 QObject::connect(registry, &KWayland::Client::Registry::outputAnnounced, [=](quint32 name, quint32 version) { 0341 KWayland::Client::Output *output = registry->createOutput(name, version, s_waylandConnection.registry); 0342 s_waylandConnection.outputs << output; 0343 QObject::connect(output, &KWayland::Client::Output::removed, [=]() { 0344 output->deleteLater(); 0345 s_waylandConnection.outputs.removeOne(output); 0346 }); 0347 QObject::connect(output, &KWayland::Client::Output::destroyed, [=]() { 0348 s_waylandConnection.outputs.removeOne(output); 0349 }); 0350 }); 0351 0352 QObject::connect(registry, &KWayland::Client::Registry::interfaceAnnounced, [=](const QByteArray &interface, quint32 name, quint32 version) { 0353 if (flags & AdditionalWaylandInterface::InputMethodV1) { 0354 if (interface == QByteArrayLiteral("zwp_input_method_v1")) { 0355 s_waylandConnection.inputMethodV1 = new MockInputMethod(*registry, name, version); 0356 } else if (interface == QByteArrayLiteral("zwp_input_panel_v1")) { 0357 s_waylandConnection.inputPanelV1 = new QtWayland::zwp_input_panel_v1(*registry, name, version); 0358 } 0359 } 0360 if (flags & AdditionalWaylandInterface::LayerShellV1) { 0361 if (interface == QByteArrayLiteral("zwlr_layer_shell_v1")) { 0362 s_waylandConnection.layerShellV1 = new LayerShellV1(); 0363 s_waylandConnection.layerShellV1->init(*registry, name, version); 0364 } 0365 } 0366 if (flags & AdditionalWaylandInterface::TextInputManagerV3) { 0367 // do something 0368 if (interface == QByteArrayLiteral("zwp_text_input_manager_v3")) { 0369 s_waylandConnection.textInputManagerV3 = new TextInputManagerV3(); 0370 s_waylandConnection.textInputManagerV3->init(*registry, name, version); 0371 } 0372 } 0373 if (interface == QByteArrayLiteral("xdg_wm_base")) { 0374 s_waylandConnection.xdgShell = new XdgShell(); 0375 s_waylandConnection.xdgShell->init(*registry, name, version); 0376 } 0377 if (flags & AdditionalWaylandInterface::XdgDecorationV1) { 0378 if (interface == zxdg_decoration_manager_v1_interface.name) { 0379 s_waylandConnection.xdgDecorationManagerV1 = new XdgDecorationManagerV1(); 0380 s_waylandConnection.xdgDecorationManagerV1->init(*registry, name, version); 0381 return; 0382 } 0383 } 0384 if (flags & AdditionalWaylandInterface::IdleInhibitV1) { 0385 if (interface == zwp_idle_inhibit_manager_v1_interface.name) { 0386 s_waylandConnection.idleInhibitManagerV1 = new IdleInhibitManagerV1(); 0387 s_waylandConnection.idleInhibitManagerV1->init(*registry, name, version); 0388 return; 0389 } 0390 } 0391 if (flags & AdditionalWaylandInterface::OutputDeviceV2) { 0392 if (interface == kde_output_device_v2_interface.name) { 0393 WaylandOutputDeviceV2 *device = new WaylandOutputDeviceV2(name); 0394 device->init(*registry, name, version); 0395 0396 s_waylandConnection.outputDevicesV2 << device; 0397 0398 QObject::connect(device, &WaylandOutputDeviceV2::destroyed, [=]() { 0399 s_waylandConnection.outputDevicesV2.removeOne(device); 0400 device->deleteLater(); 0401 }); 0402 0403 QObject::connect(registry, &KWayland::Client::Registry::interfaceRemoved, device, [name, device](const quint32 &interfaceName) { 0404 if (name == interfaceName) { 0405 s_waylandConnection.outputDevicesV2.removeOne(device); 0406 device->deleteLater(); 0407 } 0408 }); 0409 0410 return; 0411 } 0412 } 0413 if (flags & AdditionalWaylandInterface::OutputManagementV2) { 0414 if (interface == kde_output_management_v2_interface.name) { 0415 s_waylandConnection.outputManagementV2 = new WaylandOutputManagementV2(*registry, name, version); 0416 return; 0417 } 0418 } 0419 if (flags & AdditionalWaylandInterface::FractionalScaleManagerV1) { 0420 if (interface == wp_fractional_scale_manager_v1_interface.name) { 0421 s_waylandConnection.fractionalScaleManagerV1 = new FractionalScaleManagerV1(); 0422 s_waylandConnection.fractionalScaleManagerV1->init(*registry, name, version); 0423 return; 0424 } 0425 } 0426 }); 0427 0428 QSignalSpy allAnnounced(registry, &KWayland::Client::Registry::interfacesAnnounced); 0429 if (!allAnnounced.isValid()) { 0430 return false; 0431 } 0432 registry->create(s_waylandConnection.connection); 0433 if (!registry->isValid()) { 0434 return false; 0435 } 0436 registry->setup(); 0437 if (!allAnnounced.wait()) { 0438 return false; 0439 } 0440 0441 s_waylandConnection.compositor = registry->createCompositor(registry->interface(KWayland::Client::Registry::Interface::Compositor).name, registry->interface(KWayland::Client::Registry::Interface::Compositor).version); 0442 if (!s_waylandConnection.compositor->isValid()) { 0443 return false; 0444 } 0445 s_waylandConnection.subCompositor = registry->createSubCompositor(registry->interface(KWayland::Client::Registry::Interface::SubCompositor).name, registry->interface(KWayland::Client::Registry::Interface::SubCompositor).version); 0446 if (!s_waylandConnection.subCompositor->isValid()) { 0447 return false; 0448 } 0449 s_waylandConnection.shm = registry->createShmPool(registry->interface(KWayland::Client::Registry::Interface::Shm).name, registry->interface(KWayland::Client::Registry::Interface::Shm).version); 0450 if (!s_waylandConnection.shm->isValid()) { 0451 return false; 0452 } 0453 if (flags.testFlag(AdditionalWaylandInterface::Seat)) { 0454 s_waylandConnection.seat = registry->createSeat(registry->interface(KWayland::Client::Registry::Interface::Seat).name, registry->interface(KWayland::Client::Registry::Interface::Seat).version); 0455 if (!s_waylandConnection.seat->isValid()) { 0456 return false; 0457 } 0458 } 0459 if (flags.testFlag(AdditionalWaylandInterface::ShadowManager)) { 0460 s_waylandConnection.shadowManager = registry->createShadowManager(registry->interface(KWayland::Client::Registry::Interface::Shadow).name, 0461 registry->interface(KWayland::Client::Registry::Interface::Shadow).version); 0462 if (!s_waylandConnection.shadowManager->isValid()) { 0463 return false; 0464 } 0465 } 0466 if (flags.testFlag(AdditionalWaylandInterface::Decoration)) { 0467 s_waylandConnection.decoration = registry->createServerSideDecorationManager(registry->interface(KWayland::Client::Registry::Interface::ServerSideDecorationManager).name, 0468 registry->interface(KWayland::Client::Registry::Interface::ServerSideDecorationManager).version); 0469 if (!s_waylandConnection.decoration->isValid()) { 0470 return false; 0471 } 0472 } 0473 if (flags.testFlag(AdditionalWaylandInterface::PlasmaShell)) { 0474 s_waylandConnection.plasmaShell = registry->createPlasmaShell(registry->interface(KWayland::Client::Registry::Interface::PlasmaShell).name, 0475 registry->interface(KWayland::Client::Registry::Interface::PlasmaShell).version); 0476 if (!s_waylandConnection.plasmaShell->isValid()) { 0477 return false; 0478 } 0479 } 0480 if (flags.testFlag(AdditionalWaylandInterface::WindowManagement)) { 0481 s_waylandConnection.windowManagement = registry->createPlasmaWindowManagement(registry->interface(KWayland::Client::Registry::Interface::PlasmaWindowManagement).name, 0482 registry->interface(KWayland::Client::Registry::Interface::PlasmaWindowManagement).version); 0483 if (!s_waylandConnection.windowManagement->isValid()) { 0484 return false; 0485 } 0486 } 0487 if (flags.testFlag(AdditionalWaylandInterface::PointerConstraints)) { 0488 s_waylandConnection.pointerConstraints = registry->createPointerConstraints(registry->interface(KWayland::Client::Registry::Interface::PointerConstraintsUnstableV1).name, 0489 registry->interface(KWayland::Client::Registry::Interface::PointerConstraintsUnstableV1).version); 0490 if (!s_waylandConnection.pointerConstraints->isValid()) { 0491 return false; 0492 } 0493 } 0494 if (flags.testFlag(AdditionalWaylandInterface::AppMenu)) { 0495 s_waylandConnection.appMenu = registry->createAppMenuManager(registry->interface(KWayland::Client::Registry::Interface::AppMenu).name, registry->interface(KWayland::Client::Registry::Interface::AppMenu).version); 0496 if (!s_waylandConnection.appMenu->isValid()) { 0497 return false; 0498 } 0499 } 0500 if (flags.testFlag(AdditionalWaylandInterface::TextInputManagerV2)) { 0501 s_waylandConnection.textInputManager = registry->createTextInputManager(registry->interface(KWayland::Client::Registry::Interface::TextInputManagerUnstableV2).name, registry->interface(KWayland::Client::Registry::Interface::TextInputManagerUnstableV2).version); 0502 if (!s_waylandConnection.textInputManager->isValid()) { 0503 return false; 0504 } 0505 } 0506 0507 return true; 0508 } 0509 0510 void destroyWaylandConnection() 0511 { 0512 delete s_waylandConnection.compositor; 0513 s_waylandConnection.compositor = nullptr; 0514 delete s_waylandConnection.subCompositor; 0515 s_waylandConnection.subCompositor = nullptr; 0516 delete s_waylandConnection.windowManagement; 0517 s_waylandConnection.windowManagement = nullptr; 0518 delete s_waylandConnection.plasmaShell; 0519 s_waylandConnection.plasmaShell = nullptr; 0520 delete s_waylandConnection.decoration; 0521 s_waylandConnection.decoration = nullptr; 0522 delete s_waylandConnection.decoration; 0523 s_waylandConnection.decoration = nullptr; 0524 delete s_waylandConnection.seat; 0525 s_waylandConnection.seat = nullptr; 0526 delete s_waylandConnection.pointerConstraints; 0527 s_waylandConnection.pointerConstraints = nullptr; 0528 delete s_waylandConnection.xdgShell; 0529 s_waylandConnection.xdgShell = nullptr; 0530 delete s_waylandConnection.shadowManager; 0531 s_waylandConnection.shadowManager = nullptr; 0532 delete s_waylandConnection.idleInhibitManagerV1; 0533 s_waylandConnection.idleInhibitManagerV1 = nullptr; 0534 delete s_waylandConnection.shm; 0535 s_waylandConnection.shm = nullptr; 0536 delete s_waylandConnection.registry; 0537 s_waylandConnection.registry = nullptr; 0538 delete s_waylandConnection.appMenu; 0539 s_waylandConnection.appMenu = nullptr; 0540 delete s_waylandConnection.xdgDecorationManagerV1; 0541 s_waylandConnection.xdgDecorationManagerV1 = nullptr; 0542 delete s_waylandConnection.textInputManager; 0543 s_waylandConnection.textInputManager = nullptr; 0544 delete s_waylandConnection.inputPanelV1; 0545 s_waylandConnection.inputPanelV1 = nullptr; 0546 delete s_waylandConnection.layerShellV1; 0547 s_waylandConnection.layerShellV1 = nullptr; 0548 delete s_waylandConnection.outputManagementV2; 0549 s_waylandConnection.outputManagementV2 = nullptr; 0550 delete s_waylandConnection.fractionalScaleManagerV1; 0551 s_waylandConnection.fractionalScaleManagerV1 = nullptr; 0552 0553 delete s_waylandConnection.queue; // Must be destroyed last 0554 s_waylandConnection.queue = nullptr; 0555 0556 if (s_waylandConnection.thread) { 0557 s_waylandConnection.connection->deleteLater(); 0558 s_waylandConnection.thread->quit(); 0559 s_waylandConnection.thread->wait(); 0560 delete s_waylandConnection.thread; 0561 s_waylandConnection.thread = nullptr; 0562 s_waylandConnection.connection = nullptr; 0563 } 0564 s_waylandConnection.outputs.clear(); 0565 s_waylandConnection.outputDevicesV2.clear(); 0566 } 0567 0568 KWayland::Client::ConnectionThread *waylandConnection() 0569 { 0570 return s_waylandConnection.connection; 0571 } 0572 0573 KWayland::Client::Compositor *waylandCompositor() 0574 { 0575 return s_waylandConnection.compositor; 0576 } 0577 0578 KWayland::Client::SubCompositor *waylandSubCompositor() 0579 { 0580 return s_waylandConnection.subCompositor; 0581 } 0582 0583 KWayland::Client::ShadowManager *waylandShadowManager() 0584 { 0585 return s_waylandConnection.shadowManager; 0586 } 0587 0588 KWayland::Client::ShmPool *waylandShmPool() 0589 { 0590 return s_waylandConnection.shm; 0591 } 0592 0593 KWayland::Client::Seat *waylandSeat() 0594 { 0595 return s_waylandConnection.seat; 0596 } 0597 0598 KWayland::Client::ServerSideDecorationManager *waylandServerSideDecoration() 0599 { 0600 return s_waylandConnection.decoration; 0601 } 0602 0603 KWayland::Client::PlasmaShell *waylandPlasmaShell() 0604 { 0605 return s_waylandConnection.plasmaShell; 0606 } 0607 0608 KWayland::Client::PlasmaWindowManagement *waylandWindowManagement() 0609 { 0610 return s_waylandConnection.windowManagement; 0611 } 0612 0613 KWayland::Client::PointerConstraints *waylandPointerConstraints() 0614 { 0615 return s_waylandConnection.pointerConstraints; 0616 } 0617 0618 KWayland::Client::AppMenuManager *waylandAppMenuManager() 0619 { 0620 return s_waylandConnection.appMenu; 0621 } 0622 0623 KWin::Test::WaylandOutputManagementV2 *waylandOutputManagementV2() 0624 { 0625 return s_waylandConnection.outputManagementV2; 0626 } 0627 0628 KWayland::Client::TextInputManager *waylandTextInputManager() 0629 { 0630 return s_waylandConnection.textInputManager; 0631 } 0632 0633 TextInputManagerV3 *waylandTextInputManagerV3() 0634 { 0635 return s_waylandConnection.textInputManagerV3; 0636 } 0637 0638 QVector<KWayland::Client::Output *> waylandOutputs() 0639 { 0640 return s_waylandConnection.outputs; 0641 } 0642 0643 KWayland::Client::Output *waylandOutput(const QString &name) 0644 { 0645 for (KWayland::Client::Output *output : std::as_const(s_waylandConnection.outputs)) { 0646 if (output->name() == name) { 0647 return output; 0648 } 0649 } 0650 return nullptr; 0651 } 0652 0653 QVector<KWin::Test::WaylandOutputDeviceV2 *> waylandOutputDevicesV2() 0654 { 0655 return s_waylandConnection.outputDevicesV2; 0656 } 0657 0658 bool waitForWaylandSurface(Window *window) 0659 { 0660 if (window->surface()) { 0661 return true; 0662 } 0663 QSignalSpy surfaceChangedSpy(window, &Window::surfaceChanged); 0664 return surfaceChangedSpy.wait(); 0665 } 0666 0667 bool waitForWaylandPointer() 0668 { 0669 if (!s_waylandConnection.seat) { 0670 return false; 0671 } 0672 QSignalSpy hasPointerSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasPointerChanged); 0673 if (!hasPointerSpy.isValid()) { 0674 return false; 0675 } 0676 return hasPointerSpy.wait(); 0677 } 0678 0679 bool waitForWaylandTouch() 0680 { 0681 if (!s_waylandConnection.seat) { 0682 return false; 0683 } 0684 QSignalSpy hasTouchSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasTouchChanged); 0685 if (!hasTouchSpy.isValid()) { 0686 return false; 0687 } 0688 return hasTouchSpy.wait(); 0689 } 0690 0691 bool waitForWaylandKeyboard() 0692 { 0693 if (!s_waylandConnection.seat) { 0694 return false; 0695 } 0696 QSignalSpy hasKeyboardSpy(s_waylandConnection.seat, &KWayland::Client::Seat::hasKeyboardChanged); 0697 if (!hasKeyboardSpy.isValid()) { 0698 return false; 0699 } 0700 return hasKeyboardSpy.wait(); 0701 } 0702 0703 void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format) 0704 { 0705 QImage img(size, format); 0706 img.fill(color); 0707 render(surface, img); 0708 } 0709 0710 void render(KWayland::Client::Surface *surface, const QImage &img) 0711 { 0712 surface->attachBuffer(s_waylandConnection.shm->createBuffer(img)); 0713 surface->damage(QRect(QPoint(0, 0), img.size())); 0714 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0715 } 0716 0717 Window *waitForWaylandWindowShown(int timeout) 0718 { 0719 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); 0720 if (!windowAddedSpy.isValid()) { 0721 return nullptr; 0722 } 0723 if (!windowAddedSpy.wait(timeout)) { 0724 return nullptr; 0725 } 0726 return windowAddedSpy.first().first().value<Window *>(); 0727 } 0728 0729 Window *renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format, int timeout) 0730 { 0731 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); 0732 if (!windowAddedSpy.isValid()) { 0733 return nullptr; 0734 } 0735 render(surface, size, color, format); 0736 flushWaylandConnection(); 0737 if (!windowAddedSpy.wait(timeout)) { 0738 return nullptr; 0739 } 0740 return windowAddedSpy.first().first().value<Window *>(); 0741 } 0742 0743 void flushWaylandConnection() 0744 { 0745 if (s_waylandConnection.connection) { 0746 s_waylandConnection.connection->flush(); 0747 } 0748 } 0749 0750 std::unique_ptr<KWayland::Client::Surface> createSurface() 0751 { 0752 if (!s_waylandConnection.compositor) { 0753 return nullptr; 0754 } 0755 std::unique_ptr<KWayland::Client::Surface> s{s_waylandConnection.compositor->createSurface()}; 0756 return s->isValid() ? std::move(s) : nullptr; 0757 } 0758 0759 KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface, QObject *parent) 0760 { 0761 if (!s_waylandConnection.subCompositor) { 0762 return nullptr; 0763 } 0764 auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent); 0765 if (!s->isValid()) { 0766 delete s; 0767 return nullptr; 0768 } 0769 return s; 0770 } 0771 0772 LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output, LayerShellV1::layer layer) 0773 { 0774 LayerShellV1 *shell = s_waylandConnection.layerShellV1; 0775 if (!shell) { 0776 qWarning() << "Could not create a layer surface because the layer shell global is not bound"; 0777 return nullptr; 0778 } 0779 0780 struct ::wl_output *nativeOutput = nullptr; 0781 if (output) { 0782 nativeOutput = *output; 0783 } 0784 0785 LayerSurfaceV1 *shellSurface = new LayerSurfaceV1(); 0786 shellSurface->init(shell->get_layer_surface(*surface, nativeOutput, layer, scope)); 0787 0788 return shellSurface; 0789 } 0790 0791 QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface, KWayland::Client::Output *output) 0792 { 0793 if (!s_waylandConnection.inputPanelV1) { 0794 qWarning() << "Unable to create the input panel surface. The interface input_panel global is not bound"; 0795 return nullptr; 0796 } 0797 QtWayland::zwp_input_panel_surface_v1 *s = new QtWayland::zwp_input_panel_surface_v1(s_waylandConnection.inputPanelV1->get_input_panel_surface(*surface)); 0798 0799 if (!s->isInitialized()) { 0800 delete s; 0801 return nullptr; 0802 } 0803 0804 s->set_toplevel(output->output(), QtWayland::zwp_input_panel_surface_v1::position_center_bottom); 0805 0806 return s; 0807 } 0808 0809 FractionalScaleV1 *createFractionalScaleV1(KWayland::Client::Surface *surface) 0810 { 0811 if (!s_waylandConnection.fractionalScaleManagerV1) { 0812 qWarning() << "Unable to create fractional scale surface. The global is not bound"; 0813 return nullptr; 0814 } 0815 auto scale = new FractionalScaleV1(); 0816 scale->init(s_waylandConnection.fractionalScaleManagerV1->get_fractional_scale(*surface)); 0817 0818 return scale; 0819 } 0820 0821 static void waitForConfigured(XdgSurface *shellSurface) 0822 { 0823 QSignalSpy surfaceConfigureRequestedSpy(shellSurface, &XdgSurface::configureRequested); 0824 0825 shellSurface->surface()->commit(KWayland::Client::Surface::CommitFlag::None); 0826 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0827 0828 shellSurface->ack_configure(surfaceConfigureRequestedSpy.last().first().toUInt()); 0829 } 0830 0831 XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent) 0832 { 0833 return createXdgToplevelSurface(surface, CreationSetup::CreateAndConfigure, parent); 0834 } 0835 0836 XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode, QObject *parent) 0837 { 0838 XdgShell *shell = s_waylandConnection.xdgShell; 0839 0840 if (!shell) { 0841 qWarning() << "Could not create an xdg_toplevel surface because xdg_wm_base global is not bound"; 0842 return nullptr; 0843 } 0844 0845 XdgSurface *xdgSurface = new XdgSurface(shell, surface); 0846 XdgToplevel *xdgToplevel = new XdgToplevel(xdgSurface, parent); 0847 0848 if (configureMode == CreationSetup::CreateAndConfigure) { 0849 waitForConfigured(xdgSurface); 0850 } 0851 0852 return xdgToplevel; 0853 } 0854 0855 XdgPositioner *createXdgPositioner() 0856 { 0857 XdgShell *shell = s_waylandConnection.xdgShell; 0858 0859 if (!shell) { 0860 qWarning() << "Could not create an xdg_positioner object because xdg_wm_base global is not bound"; 0861 return nullptr; 0862 } 0863 0864 return new XdgPositioner(shell); 0865 } 0866 0867 XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, 0868 CreationSetup configureMode, QObject *parent) 0869 { 0870 XdgShell *shell = s_waylandConnection.xdgShell; 0871 0872 if (!shell) { 0873 qWarning() << "Could not create an xdg_popup surface because xdg_wm_base global is not bound"; 0874 return nullptr; 0875 } 0876 0877 XdgSurface *xdgSurface = new XdgSurface(shell, surface); 0878 XdgPopup *xdgPopup = new XdgPopup(xdgSurface, parentSurface, positioner, parent); 0879 0880 if (configureMode == CreationSetup::CreateAndConfigure) { 0881 waitForConfigured(xdgSurface); 0882 } 0883 0884 return xdgPopup; 0885 } 0886 0887 XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent) 0888 { 0889 XdgDecorationManagerV1 *manager = s_waylandConnection.xdgDecorationManagerV1; 0890 0891 if (!manager) { 0892 qWarning() << "Could not create an xdg_toplevel_decoration_v1 because xdg_decoration_manager_v1 global is not bound"; 0893 return nullptr; 0894 } 0895 0896 return new XdgToplevelDecorationV1(manager, toplevel, parent); 0897 } 0898 0899 IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface) 0900 { 0901 IdleInhibitManagerV1 *manager = s_waylandConnection.idleInhibitManagerV1; 0902 if (!manager) { 0903 qWarning() << "Could not create an idle_inhibitor_v1 because idle_inhibit_manager_v1 global is not bound"; 0904 return nullptr; 0905 } 0906 0907 return new IdleInhibitorV1(manager, surface); 0908 } 0909 0910 bool waitForWindowDestroyed(Window *window) 0911 { 0912 QSignalSpy destroyedSpy(window, &QObject::destroyed); 0913 if (!destroyedSpy.isValid()) { 0914 return false; 0915 } 0916 return destroyedSpy.wait(); 0917 } 0918 0919 #if KWIN_BUILD_SCREENLOCKER 0920 bool lockScreen() 0921 { 0922 if (waylandServer()->isScreenLocked()) { 0923 return false; 0924 } 0925 QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged); 0926 if (!lockStateChangedSpy.isValid()) { 0927 return false; 0928 } 0929 ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate); 0930 if (lockStateChangedSpy.count() != 1) { 0931 return false; 0932 } 0933 if (!waylandServer()->isScreenLocked()) { 0934 return false; 0935 } 0936 if (!kwinApp()->screenLockerWatcher()->isLocked()) { 0937 QSignalSpy lockedSpy(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked); 0938 if (!lockedSpy.isValid()) { 0939 return false; 0940 } 0941 if (!lockedSpy.wait()) { 0942 return false; 0943 } 0944 if (!kwinApp()->screenLockerWatcher()->isLocked()) { 0945 return false; 0946 } 0947 } 0948 return true; 0949 } 0950 0951 bool unlockScreen() 0952 { 0953 QSignalSpy lockStateChangedSpy(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged); 0954 if (!lockStateChangedSpy.isValid()) { 0955 return false; 0956 } 0957 using namespace ScreenLocker; 0958 const auto children = KSldApp::self()->children(); 0959 for (auto it = children.begin(); it != children.end(); ++it) { 0960 if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) { 0961 continue; 0962 } 0963 QMetaObject::invokeMethod(*it, "requestUnlock"); 0964 break; 0965 } 0966 if (waylandServer()->isScreenLocked()) { 0967 lockStateChangedSpy.wait(); 0968 } 0969 if (waylandServer()->isScreenLocked()) { 0970 return true; 0971 } 0972 if (kwinApp()->screenLockerWatcher()->isLocked()) { 0973 QSignalSpy lockedSpy(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::locked); 0974 if (!lockedSpy.isValid()) { 0975 return false; 0976 } 0977 if (!lockedSpy.wait()) { 0978 return false; 0979 } 0980 if (kwinApp()->screenLockerWatcher()->isLocked()) { 0981 return false; 0982 } 0983 } 0984 return true; 0985 } 0986 #endif // KWIN_BUILD_LOCKSCREEN 0987 0988 WaylandOutputManagementV2::WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version) 0989 : QObject() 0990 , QtWayland::kde_output_management_v2() 0991 { 0992 init(registry, id, version); 0993 } 0994 0995 WaylandOutputConfigurationV2 *WaylandOutputManagementV2::createConfiguration() 0996 { 0997 return new WaylandOutputConfigurationV2(create_configuration()); 0998 } 0999 1000 WaylandOutputConfigurationV2::WaylandOutputConfigurationV2(struct ::kde_output_configuration_v2 *object) 1001 : QObject() 1002 , QtWayland::kde_output_configuration_v2() 1003 { 1004 init(object); 1005 } 1006 1007 void WaylandOutputConfigurationV2::kde_output_configuration_v2_applied() 1008 { 1009 Q_EMIT applied(); 1010 } 1011 void WaylandOutputConfigurationV2::kde_output_configuration_v2_failed() 1012 { 1013 Q_EMIT failed(); 1014 } 1015 1016 WaylandOutputDeviceV2Mode::WaylandOutputDeviceV2Mode(struct ::kde_output_device_mode_v2 *object) 1017 : QtWayland::kde_output_device_mode_v2(object) 1018 { 1019 } 1020 1021 WaylandOutputDeviceV2Mode::~WaylandOutputDeviceV2Mode() 1022 { 1023 kde_output_device_mode_v2_destroy(object()); 1024 } 1025 1026 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_size(int32_t width, int32_t height) 1027 { 1028 m_size = QSize(width, height); 1029 } 1030 1031 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_refresh(int32_t refresh) 1032 { 1033 m_refreshRate = refresh; 1034 } 1035 1036 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_preferred() 1037 { 1038 m_preferred = true; 1039 } 1040 1041 void WaylandOutputDeviceV2Mode::kde_output_device_mode_v2_removed() 1042 { 1043 Q_EMIT removed(); 1044 } 1045 1046 int WaylandOutputDeviceV2Mode::refreshRate() const 1047 { 1048 return m_refreshRate; 1049 } 1050 1051 QSize WaylandOutputDeviceV2Mode::size() const 1052 { 1053 return m_size; 1054 } 1055 1056 bool WaylandOutputDeviceV2Mode::preferred() const 1057 { 1058 return m_preferred; 1059 } 1060 1061 bool WaylandOutputDeviceV2Mode::operator==(const WaylandOutputDeviceV2Mode &other) 1062 { 1063 return m_size == other.m_size && m_refreshRate == other.m_refreshRate && m_preferred == other.m_preferred; 1064 } 1065 1066 WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2Mode::get(struct ::kde_output_device_mode_v2 *object) 1067 { 1068 auto mode = QtWayland::kde_output_device_mode_v2::fromObject(object); 1069 return static_cast<WaylandOutputDeviceV2Mode *>(mode); 1070 } 1071 1072 WaylandOutputDeviceV2::WaylandOutputDeviceV2(int id) 1073 : QObject() 1074 , kde_output_device_v2() 1075 , m_id(id) 1076 { 1077 } 1078 1079 WaylandOutputDeviceV2::~WaylandOutputDeviceV2() 1080 { 1081 qDeleteAll(m_modes); 1082 1083 kde_output_device_v2_destroy(object()); 1084 } 1085 1086 void WaylandOutputDeviceV2::kde_output_device_v2_geometry(int32_t x, 1087 int32_t y, 1088 int32_t physical_width, 1089 int32_t physical_height, 1090 int32_t subpixel, 1091 const QString &make, 1092 const QString &model, 1093 int32_t transform) 1094 { 1095 m_pos = QPoint(x, y); 1096 m_physicalSize = QSize(physical_width, physical_height); 1097 m_subpixel = subpixel; 1098 m_manufacturer = make; 1099 m_model = model; 1100 m_transform = transform; 1101 } 1102 1103 void WaylandOutputDeviceV2::kde_output_device_v2_current_mode(struct ::kde_output_device_mode_v2 *mode) 1104 { 1105 auto m = WaylandOutputDeviceV2Mode::get(mode); 1106 1107 if (*m == *m_mode) { 1108 // unchanged 1109 return; 1110 } 1111 m_mode = m; 1112 } 1113 1114 void WaylandOutputDeviceV2::kde_output_device_v2_mode(struct ::kde_output_device_mode_v2 *mode) 1115 { 1116 WaylandOutputDeviceV2Mode *m = new WaylandOutputDeviceV2Mode(mode); 1117 // last mode sent is the current one 1118 m_mode = m; 1119 m_modes.append(m); 1120 1121 connect(m, &WaylandOutputDeviceV2Mode::removed, this, [this, m]() { 1122 m_modes.removeOne(m); 1123 if (m_mode == m) { 1124 if (!m_modes.isEmpty()) { 1125 m_mode = m_modes.first(); 1126 } else { 1127 // was last mode 1128 qFatal("KWaylandBackend: no output modes available anymore, this seems like a compositor bug"); 1129 } 1130 } 1131 1132 delete m; 1133 }); 1134 } 1135 1136 QString WaylandOutputDeviceV2::modeId() const 1137 { 1138 return QString::number(m_modes.indexOf(m_mode)); 1139 } 1140 1141 WaylandOutputDeviceV2Mode *WaylandOutputDeviceV2::deviceModeFromId(const int modeId) const 1142 { 1143 return m_modes.at(modeId); 1144 } 1145 1146 QString WaylandOutputDeviceV2::modeName(const WaylandOutputDeviceV2Mode *m) const 1147 { 1148 return QString::number(m->size().width()) + QLatin1Char('x') + QString::number(m->size().height()) + QLatin1Char('@') 1149 + QString::number(qRound(m->refreshRate() / 1000.0)); 1150 } 1151 1152 QString WaylandOutputDeviceV2::name() const 1153 { 1154 return QStringLiteral("%1 %2").arg(m_manufacturer, m_model); 1155 } 1156 1157 QDebug operator<<(QDebug dbg, const WaylandOutputDeviceV2 *output) 1158 { 1159 dbg << "WaylandOutput(Id:" << output->id() << ", Name:" << QString(output->manufacturer() + QLatin1Char(' ') + output->model()) << ")"; 1160 return dbg; 1161 } 1162 1163 void WaylandOutputDeviceV2::kde_output_device_v2_done() 1164 { 1165 Q_EMIT done(); 1166 } 1167 1168 void WaylandOutputDeviceV2::kde_output_device_v2_scale(wl_fixed_t factor) 1169 { 1170 m_factor = wl_fixed_to_double(factor); 1171 } 1172 1173 void WaylandOutputDeviceV2::kde_output_device_v2_edid(const QString &edid) 1174 { 1175 m_edid = QByteArray::fromBase64(edid.toUtf8()); 1176 } 1177 1178 void WaylandOutputDeviceV2::kde_output_device_v2_enabled(int32_t enabled) 1179 { 1180 if (m_enabled != enabled) { 1181 m_enabled = enabled; 1182 Q_EMIT enabledChanged(); 1183 } 1184 } 1185 1186 void WaylandOutputDeviceV2::kde_output_device_v2_uuid(const QString &uuid) 1187 { 1188 m_uuid = uuid; 1189 } 1190 1191 void WaylandOutputDeviceV2::kde_output_device_v2_serial_number(const QString &serialNumber) 1192 { 1193 m_serialNumber = serialNumber; 1194 } 1195 1196 void WaylandOutputDeviceV2::kde_output_device_v2_eisa_id(const QString &eisaId) 1197 { 1198 m_eisaId = eisaId; 1199 } 1200 1201 void WaylandOutputDeviceV2::kde_output_device_v2_capabilities(uint32_t flags) 1202 { 1203 m_flags = flags; 1204 } 1205 1206 void WaylandOutputDeviceV2::kde_output_device_v2_overscan(uint32_t overscan) 1207 { 1208 m_overscan = overscan; 1209 } 1210 1211 void WaylandOutputDeviceV2::kde_output_device_v2_vrr_policy(uint32_t vrr_policy) 1212 { 1213 m_vrr_policy = vrr_policy; 1214 } 1215 1216 void WaylandOutputDeviceV2::kde_output_device_v2_rgb_range(uint32_t rgb_range) 1217 { 1218 m_rgbRange = rgb_range; 1219 } 1220 1221 QByteArray WaylandOutputDeviceV2::edid() const 1222 { 1223 return m_edid; 1224 } 1225 1226 bool WaylandOutputDeviceV2::enabled() const 1227 { 1228 return m_enabled; 1229 } 1230 1231 int WaylandOutputDeviceV2::id() const 1232 { 1233 return m_id; 1234 } 1235 1236 qreal WaylandOutputDeviceV2::scale() const 1237 { 1238 return m_factor; 1239 } 1240 1241 QString WaylandOutputDeviceV2::manufacturer() const 1242 { 1243 return m_manufacturer; 1244 } 1245 1246 QString WaylandOutputDeviceV2::model() const 1247 { 1248 return m_model; 1249 } 1250 1251 QPoint WaylandOutputDeviceV2::globalPosition() const 1252 { 1253 return m_pos; 1254 } 1255 1256 QSize WaylandOutputDeviceV2::pixelSize() const 1257 { 1258 return m_mode->size(); 1259 } 1260 1261 int WaylandOutputDeviceV2::refreshRate() const 1262 { 1263 return m_mode->refreshRate(); 1264 } 1265 1266 uint32_t WaylandOutputDeviceV2::vrrPolicy() const 1267 { 1268 return m_vrr_policy; 1269 } 1270 1271 uint32_t WaylandOutputDeviceV2::overscan() const 1272 { 1273 return m_overscan; 1274 } 1275 1276 uint32_t WaylandOutputDeviceV2::capabilities() const 1277 { 1278 return m_flags; 1279 } 1280 1281 uint32_t WaylandOutputDeviceV2::rgbRange() const 1282 { 1283 return m_rgbRange; 1284 } 1285 1286 VirtualInputDevice::VirtualInputDevice(QObject *parent) 1287 : InputDevice(parent) 1288 { 1289 } 1290 1291 void VirtualInputDevice::setPointer(bool set) 1292 { 1293 m_pointer = set; 1294 } 1295 1296 void VirtualInputDevice::setKeyboard(bool set) 1297 { 1298 m_keyboard = set; 1299 } 1300 1301 void VirtualInputDevice::setTouch(bool set) 1302 { 1303 m_touch = set; 1304 } 1305 1306 void VirtualInputDevice::setName(const QString &name) 1307 { 1308 m_name = name; 1309 } 1310 1311 QString VirtualInputDevice::sysName() const 1312 { 1313 return QString(); 1314 } 1315 1316 QString VirtualInputDevice::name() const 1317 { 1318 return m_name; 1319 } 1320 1321 bool VirtualInputDevice::isEnabled() const 1322 { 1323 return true; 1324 } 1325 1326 void VirtualInputDevice::setEnabled(bool enabled) 1327 { 1328 } 1329 1330 LEDs VirtualInputDevice::leds() const 1331 { 1332 return LEDs(); 1333 } 1334 1335 void VirtualInputDevice::setLeds(LEDs leds) 1336 { 1337 } 1338 1339 bool VirtualInputDevice::isKeyboard() const 1340 { 1341 return m_keyboard; 1342 } 1343 1344 bool VirtualInputDevice::isAlphaNumericKeyboard() const 1345 { 1346 return m_keyboard; 1347 } 1348 1349 bool VirtualInputDevice::isPointer() const 1350 { 1351 return m_pointer; 1352 } 1353 1354 bool VirtualInputDevice::isTouchpad() const 1355 { 1356 return false; 1357 } 1358 1359 bool VirtualInputDevice::isTouch() const 1360 { 1361 return m_touch; 1362 } 1363 1364 bool VirtualInputDevice::isTabletTool() const 1365 { 1366 return false; 1367 } 1368 1369 bool VirtualInputDevice::isTabletPad() const 1370 { 1371 return false; 1372 } 1373 1374 bool VirtualInputDevice::isTabletModeSwitch() const 1375 { 1376 return false; 1377 } 1378 1379 bool VirtualInputDevice::isLidSwitch() const 1380 { 1381 return false; 1382 } 1383 1384 void keyboardKeyPressed(quint32 key, quint32 time) 1385 { 1386 auto virtualKeyboard = static_cast<WaylandTestApplication *>(kwinApp())->virtualKeyboard(); 1387 Q_EMIT virtualKeyboard->keyChanged(key, InputRedirection::KeyboardKeyState::KeyboardKeyPressed, std::chrono::milliseconds(time), virtualKeyboard); 1388 } 1389 1390 void keyboardKeyReleased(quint32 key, quint32 time) 1391 { 1392 auto virtualKeyboard = static_cast<WaylandTestApplication *>(kwinApp())->virtualKeyboard(); 1393 Q_EMIT virtualKeyboard->keyChanged(key, InputRedirection::KeyboardKeyState::KeyboardKeyReleased, std::chrono::milliseconds(time), virtualKeyboard); 1394 } 1395 1396 void pointerAxisHorizontal(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source) 1397 { 1398 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1399 Q_EMIT virtualPointer->pointerAxisChanged(InputRedirection::PointerAxis::PointerAxisHorizontal, delta, discreteDelta, source, std::chrono::milliseconds(time), virtualPointer); 1400 } 1401 1402 void pointerAxisVertical(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source) 1403 { 1404 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1405 Q_EMIT virtualPointer->pointerAxisChanged(InputRedirection::PointerAxis::PointerAxisVertical, delta, discreteDelta, source, std::chrono::milliseconds(time), virtualPointer); 1406 } 1407 1408 void pointerButtonPressed(quint32 button, quint32 time) 1409 { 1410 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1411 Q_EMIT virtualPointer->pointerButtonChanged(button, InputRedirection::PointerButtonState::PointerButtonPressed, std::chrono::milliseconds(time), virtualPointer); 1412 } 1413 1414 void pointerButtonReleased(quint32 button, quint32 time) 1415 { 1416 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1417 Q_EMIT virtualPointer->pointerButtonChanged(button, InputRedirection::PointerButtonState::PointerButtonReleased, std::chrono::milliseconds(time), virtualPointer); 1418 } 1419 1420 void pointerMotion(const QPointF &position, quint32 time) 1421 { 1422 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1423 Q_EMIT virtualPointer->pointerMotionAbsolute(position, std::chrono::milliseconds(time), virtualPointer); 1424 } 1425 1426 void pointerMotionRelative(const QPointF &delta, quint32 time) 1427 { 1428 auto virtualPointer = static_cast<WaylandTestApplication *>(kwinApp())->virtualPointer(); 1429 Q_EMIT virtualPointer->pointerMotion(delta, delta, std::chrono::milliseconds(time), virtualPointer); 1430 } 1431 1432 void touchCancel() 1433 { 1434 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch(); 1435 Q_EMIT virtualTouch->touchCanceled(virtualTouch); 1436 } 1437 1438 void touchDown(qint32 id, const QPointF &pos, quint32 time) 1439 { 1440 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch(); 1441 Q_EMIT virtualTouch->touchDown(id, pos, std::chrono::milliseconds(time), virtualTouch); 1442 } 1443 1444 void touchMotion(qint32 id, const QPointF &pos, quint32 time) 1445 { 1446 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch(); 1447 Q_EMIT virtualTouch->touchMotion(id, pos, std::chrono::milliseconds(time), virtualTouch); 1448 } 1449 1450 void touchUp(qint32 id, quint32 time) 1451 { 1452 auto virtualTouch = static_cast<WaylandTestApplication *>(kwinApp())->virtualTouch(); 1453 Q_EMIT virtualTouch->touchUp(id, std::chrono::milliseconds(time), virtualTouch); 1454 } 1455 } 1456 }