File indexing completed on 2025-02-02 05:19:00
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 #ifndef KWIN_WAYLAND_TEST_H 0010 #define KWIN_WAYLAND_TEST_H 0011 0012 #include "core/inputdevice.h" 0013 #include "main.h" 0014 #include "window.h" 0015 0016 // Qt 0017 #include <QSignalSpy> 0018 #include <QTest> 0019 0020 #include <KWayland/Client/surface.h> 0021 #include <optional> 0022 0023 #include "qwayland-cursor-shape-v1.h" 0024 #include "qwayland-fake-input.h" 0025 #include "qwayland-fractional-scale-v1.h" 0026 #include "qwayland-idle-inhibit-unstable-v1.h" 0027 #include "qwayland-input-method-unstable-v1.h" 0028 #include "qwayland-kde-output-device-v2.h" 0029 #include "qwayland-kde-output-management-v2.h" 0030 #include "qwayland-kde-screen-edge-v1.h" 0031 #include "qwayland-security-context-v1.h" 0032 #include "qwayland-text-input-unstable-v3.h" 0033 #include "qwayland-wlr-layer-shell-unstable-v1.h" 0034 #include "qwayland-xdg-decoration-unstable-v1.h" 0035 #include "qwayland-xdg-shell.h" 0036 #include "qwayland-zkde-screencast-unstable-v1.h" 0037 0038 namespace KWayland 0039 { 0040 namespace Client 0041 { 0042 class AppMenuManager; 0043 class ConnectionThread; 0044 class Compositor; 0045 class Output; 0046 class PlasmaShell; 0047 class PlasmaWindowManagement; 0048 class Pointer; 0049 class PointerConstraints; 0050 class Seat; 0051 class ShadowManager; 0052 class ShmPool; 0053 class SubCompositor; 0054 class SubSurface; 0055 class Surface; 0056 class TextInputManager; 0057 } 0058 } 0059 0060 namespace QtWayland 0061 { 0062 class zwp_input_panel_surface_v1; 0063 class zwp_text_input_v3; 0064 class zwp_text_input_manager_v3; 0065 } 0066 0067 class ScreencastingV1; 0068 0069 namespace KWin 0070 { 0071 namespace Xwl 0072 { 0073 class Xwayland; 0074 } 0075 0076 namespace Test 0077 { 0078 class VirtualInputDevice; 0079 } 0080 0081 class WaylandTestApplication : public Application 0082 { 0083 Q_OBJECT 0084 public: 0085 WaylandTestApplication(OperationMode mode, int &argc, char **argv); 0086 ~WaylandTestApplication() override; 0087 0088 void setInputMethodServerToStart(const QString &inputMethodServer) 0089 { 0090 m_inputMethodServerToStart = inputMethodServer; 0091 } 0092 0093 Test::VirtualInputDevice *virtualPointer() const; 0094 Test::VirtualInputDevice *virtualKeyboard() const; 0095 Test::VirtualInputDevice *virtualTouch() const; 0096 XwaylandInterface *xwayland() const override; 0097 0098 protected: 0099 void performStartup() override; 0100 0101 private: 0102 void continueStartupWithScene(); 0103 void finalizeStartup(); 0104 0105 void createVirtualInputDevices(); 0106 void destroyVirtualInputDevices(); 0107 0108 std::unique_ptr<Xwl::Xwayland> m_xwayland; 0109 QString m_inputMethodServerToStart; 0110 0111 std::unique_ptr<Test::VirtualInputDevice> m_virtualPointer; 0112 std::unique_ptr<Test::VirtualInputDevice> m_virtualKeyboard; 0113 std::unique_ptr<Test::VirtualInputDevice> m_virtualTouch; 0114 }; 0115 0116 namespace Test 0117 { 0118 0119 class ScreencastingV1; 0120 class MockInputMethod; 0121 0122 class TextInputManagerV3 : public QtWayland::zwp_text_input_manager_v3 0123 { 0124 public: 0125 ~TextInputManagerV3() override 0126 { 0127 destroy(); 0128 } 0129 }; 0130 0131 class TextInputV3 : public QObject, public QtWayland::zwp_text_input_v3 0132 { 0133 Q_OBJECT 0134 public: 0135 ~TextInputV3() override 0136 { 0137 destroy(); 0138 } 0139 0140 Q_SIGNALS: 0141 void preeditString(const QString &text, int cursor_begin, int cursor_end); 0142 0143 protected: 0144 void zwp_text_input_v3_preedit_string(const QString &text, int32_t cursor_begin, int32_t cursor_end) override 0145 { 0146 Q_EMIT preeditString(text, cursor_begin, cursor_end); 0147 } 0148 }; 0149 0150 class LayerShellV1 : public QtWayland::zwlr_layer_shell_v1 0151 { 0152 public: 0153 ~LayerShellV1() override; 0154 }; 0155 0156 class LayerSurfaceV1 : public QObject, public QtWayland::zwlr_layer_surface_v1 0157 { 0158 Q_OBJECT 0159 0160 public: 0161 ~LayerSurfaceV1() override; 0162 0163 protected: 0164 void zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) override; 0165 void zwlr_layer_surface_v1_closed() override; 0166 0167 Q_SIGNALS: 0168 void closeRequested(); 0169 void configureRequested(quint32 serial, const QSize &size); 0170 }; 0171 0172 /** 0173 * The XdgShell class represents the @c xdg_wm_base global. 0174 */ 0175 class XdgShell : public QtWayland::xdg_wm_base 0176 { 0177 public: 0178 ~XdgShell() override; 0179 void xdg_wm_base_ping(uint32_t serial) override 0180 { 0181 pong(serial); 0182 } 0183 }; 0184 0185 /** 0186 * The XdgSurface class represents an xdg_surface object. 0187 */ 0188 class XdgSurface : public QObject, public QtWayland::xdg_surface 0189 { 0190 Q_OBJECT 0191 0192 public: 0193 explicit XdgSurface(XdgShell *shell, KWayland::Client::Surface *surface, QObject *parent = nullptr); 0194 ~XdgSurface() override; 0195 0196 KWayland::Client::Surface *surface() const; 0197 0198 Q_SIGNALS: 0199 void configureRequested(quint32 serial); 0200 0201 protected: 0202 void xdg_surface_configure(uint32_t serial) override; 0203 0204 private: 0205 KWayland::Client::Surface *m_surface; 0206 }; 0207 0208 /** 0209 * The XdgToplevel class represents an xdg_toplevel surface. Note that the XdgToplevel surface 0210 * takes the ownership of the underlying XdgSurface object. 0211 */ 0212 class XdgToplevel : public QObject, public QtWayland::xdg_toplevel 0213 { 0214 Q_OBJECT 0215 0216 public: 0217 enum class State { 0218 Maximized = 1 << 0, 0219 Fullscreen = 1 << 1, 0220 Resizing = 1 << 2, 0221 Activated = 1 << 3 0222 }; 0223 Q_DECLARE_FLAGS(States, State) 0224 0225 explicit XdgToplevel(XdgSurface *surface, QObject *parent = nullptr); 0226 ~XdgToplevel() override; 0227 0228 XdgSurface *xdgSurface() const; 0229 0230 Q_SIGNALS: 0231 void configureRequested(const QSize &size, KWin::Test::XdgToplevel::States states); 0232 void closeRequested(); 0233 0234 protected: 0235 void xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states) override; 0236 void xdg_toplevel_close() override; 0237 0238 private: 0239 std::unique_ptr<XdgSurface> m_xdgSurface; 0240 }; 0241 0242 /** 0243 * The XdgPositioner class represents an xdg_positioner object. 0244 */ 0245 class XdgPositioner : public QtWayland::xdg_positioner 0246 { 0247 public: 0248 explicit XdgPositioner(XdgShell *shell); 0249 ~XdgPositioner() override; 0250 }; 0251 0252 /** 0253 * The XdgPopup class represents an xdg_popup surface. Note that the XdgPopup surface takes 0254 * the ownership of the underlying XdgSurface object. 0255 */ 0256 class XdgPopup : public QObject, public QtWayland::xdg_popup 0257 { 0258 Q_OBJECT 0259 0260 public: 0261 XdgPopup(XdgSurface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, QObject *parent = nullptr); 0262 ~XdgPopup() override; 0263 0264 XdgSurface *xdgSurface() const; 0265 0266 Q_SIGNALS: 0267 void configureRequested(const QRect &rect); 0268 void doneReceived(); 0269 0270 protected: 0271 void xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height) override; 0272 void xdg_popup_popup_done() override; 0273 0274 private: 0275 std::unique_ptr<XdgSurface> m_xdgSurface; 0276 }; 0277 0278 class XdgDecorationManagerV1 : public QtWayland::zxdg_decoration_manager_v1 0279 { 0280 public: 0281 ~XdgDecorationManagerV1() override; 0282 }; 0283 0284 class XdgToplevelDecorationV1 : public QObject, public QtWayland::zxdg_toplevel_decoration_v1 0285 { 0286 Q_OBJECT 0287 0288 public: 0289 XdgToplevelDecorationV1(XdgDecorationManagerV1 *manager, XdgToplevel *toplevel, QObject *parent = nullptr); 0290 ~XdgToplevelDecorationV1() override; 0291 0292 Q_SIGNALS: 0293 void configureRequested(QtWayland::zxdg_toplevel_decoration_v1::mode mode); 0294 0295 protected: 0296 void zxdg_toplevel_decoration_v1_configure(uint32_t mode) override; 0297 }; 0298 0299 class IdleInhibitManagerV1 : public QtWayland::zwp_idle_inhibit_manager_v1 0300 { 0301 public: 0302 ~IdleInhibitManagerV1() override; 0303 }; 0304 0305 class IdleInhibitorV1 : public QtWayland::zwp_idle_inhibitor_v1 0306 { 0307 public: 0308 IdleInhibitorV1(IdleInhibitManagerV1 *manager, KWayland::Client::Surface *surface); 0309 ~IdleInhibitorV1() override; 0310 }; 0311 0312 class WaylandOutputConfigurationV2 : public QObject, public QtWayland::kde_output_configuration_v2 0313 { 0314 Q_OBJECT 0315 public: 0316 WaylandOutputConfigurationV2(struct ::kde_output_configuration_v2 *object); 0317 0318 Q_SIGNALS: 0319 void applied(); 0320 void failed(); 0321 0322 protected: 0323 void kde_output_configuration_v2_applied() override; 0324 void kde_output_configuration_v2_failed() override; 0325 }; 0326 0327 class WaylandOutputManagementV2 : public QObject, public QtWayland::kde_output_management_v2 0328 { 0329 Q_OBJECT 0330 public: 0331 WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version); 0332 0333 WaylandOutputConfigurationV2 *createConfiguration(); 0334 }; 0335 0336 class WaylandOutputDeviceV2Mode : public QObject, public QtWayland::kde_output_device_mode_v2 0337 { 0338 Q_OBJECT 0339 0340 public: 0341 WaylandOutputDeviceV2Mode(struct ::kde_output_device_mode_v2 *object); 0342 ~WaylandOutputDeviceV2Mode() override; 0343 0344 int refreshRate() const; 0345 QSize size() const; 0346 bool preferred() const; 0347 0348 bool operator==(const WaylandOutputDeviceV2Mode &other) const; 0349 0350 static WaylandOutputDeviceV2Mode *get(struct ::kde_output_device_mode_v2 *object); 0351 0352 Q_SIGNALS: 0353 void removed(); 0354 0355 protected: 0356 void kde_output_device_mode_v2_size(int32_t width, int32_t height) override; 0357 void kde_output_device_mode_v2_refresh(int32_t refresh) override; 0358 void kde_output_device_mode_v2_preferred() override; 0359 void kde_output_device_mode_v2_removed() override; 0360 0361 private: 0362 int m_refreshRate = 60000; 0363 QSize m_size; 0364 bool m_preferred = false; 0365 }; 0366 0367 class WaylandOutputDeviceV2 : public QObject, public QtWayland::kde_output_device_v2 0368 { 0369 Q_OBJECT 0370 0371 public: 0372 WaylandOutputDeviceV2(int id); 0373 ~WaylandOutputDeviceV2() override; 0374 0375 QByteArray edid() const; 0376 bool enabled() const; 0377 int id() const; 0378 QString name() const; 0379 QString model() const; 0380 QString manufacturer() const; 0381 qreal scale() const; 0382 QPoint globalPosition() const; 0383 QSize pixelSize() const; 0384 int refreshRate() const; 0385 uint32_t vrrPolicy() const; 0386 uint32_t overscan() const; 0387 uint32_t capabilities() const; 0388 uint32_t rgbRange() const; 0389 0390 QString modeId() const; 0391 0392 Q_SIGNALS: 0393 void enabledChanged(); 0394 void done(); 0395 0396 protected: 0397 void kde_output_device_v2_geometry(int32_t x, 0398 int32_t y, 0399 int32_t physical_width, 0400 int32_t physical_height, 0401 int32_t subpixel, 0402 const QString &make, 0403 const QString &model, 0404 int32_t transform) override; 0405 void kde_output_device_v2_current_mode(struct ::kde_output_device_mode_v2 *mode) override; 0406 void kde_output_device_v2_mode(struct ::kde_output_device_mode_v2 *mode) override; 0407 void kde_output_device_v2_done() override; 0408 void kde_output_device_v2_scale(wl_fixed_t factor) override; 0409 void kde_output_device_v2_edid(const QString &raw) override; 0410 void kde_output_device_v2_enabled(int32_t enabled) override; 0411 void kde_output_device_v2_uuid(const QString &uuid) override; 0412 void kde_output_device_v2_serial_number(const QString &serialNumber) override; 0413 void kde_output_device_v2_eisa_id(const QString &eisaId) override; 0414 void kde_output_device_v2_capabilities(uint32_t flags) override; 0415 void kde_output_device_v2_overscan(uint32_t overscan) override; 0416 void kde_output_device_v2_vrr_policy(uint32_t vrr_policy) override; 0417 void kde_output_device_v2_rgb_range(uint32_t rgb_range) override; 0418 0419 private: 0420 QString modeName(const WaylandOutputDeviceV2Mode *m) const; 0421 WaylandOutputDeviceV2Mode *deviceModeFromId(const int modeId) const; 0422 0423 WaylandOutputDeviceV2Mode *m_mode; 0424 QList<WaylandOutputDeviceV2Mode *> m_modes; 0425 0426 int m_id; 0427 QPoint m_pos; 0428 QSize m_physicalSize; 0429 int32_t m_subpixel; 0430 QString m_manufacturer; 0431 QString m_model; 0432 int32_t m_transform; 0433 qreal m_factor; 0434 QByteArray m_edid; 0435 int32_t m_enabled; 0436 QString m_uuid; 0437 QString m_serialNumber; 0438 QString m_eisaId; 0439 uint32_t m_flags; 0440 uint32_t m_overscan; 0441 uint32_t m_vrr_policy; 0442 uint32_t m_rgbRange; 0443 }; 0444 0445 class MockInputMethod : public QObject, QtWayland::zwp_input_method_v1 0446 { 0447 Q_OBJECT 0448 public: 0449 enum class Mode { 0450 TopLevel, 0451 Overlay, 0452 }; 0453 0454 MockInputMethod(struct wl_registry *registry, int id, int version); 0455 ~MockInputMethod(); 0456 0457 KWayland::Client::Surface *inputPanelSurface() const 0458 { 0459 return m_inputSurface.get(); 0460 } 0461 auto *context() const 0462 { 0463 return m_context; 0464 } 0465 0466 void setMode(Mode mode); 0467 0468 Q_SIGNALS: 0469 void activate(); 0470 0471 protected: 0472 void zwp_input_method_v1_activate(struct ::zwp_input_method_context_v1 *context) override; 0473 void zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context) override; 0474 0475 private: 0476 std::unique_ptr<KWayland::Client::Surface> m_inputSurface; 0477 QtWayland::zwp_input_panel_surface_v1 *m_inputMethodSurface = nullptr; 0478 struct ::zwp_input_method_context_v1 *m_context = nullptr; 0479 Mode m_mode = Mode::TopLevel; 0480 }; 0481 0482 class FractionalScaleManagerV1 : public QObject, public QtWayland::wp_fractional_scale_manager_v1 0483 { 0484 Q_OBJECT 0485 public: 0486 ~FractionalScaleManagerV1() override; 0487 }; 0488 0489 class FractionalScaleV1 : public QObject, public QtWayland::wp_fractional_scale_v1 0490 { 0491 Q_OBJECT 0492 public: 0493 ~FractionalScaleV1() override; 0494 int preferredScale(); 0495 0496 protected: 0497 void wp_fractional_scale_v1_preferred_scale(uint32_t scale) override; 0498 0499 private: 0500 int m_preferredScale = 120; 0501 }; 0502 0503 class ScreenEdgeManagerV1 : public QObject, public QtWayland::kde_screen_edge_manager_v1 0504 { 0505 Q_OBJECT 0506 public: 0507 ~ScreenEdgeManagerV1() override; 0508 }; 0509 0510 class AutoHideScreenEdgeV1 : public QObject, public QtWayland::kde_auto_hide_screen_edge_v1 0511 { 0512 Q_OBJECT 0513 public: 0514 AutoHideScreenEdgeV1(ScreenEdgeManagerV1 *manager, KWayland::Client::Surface *surface, uint32_t border); 0515 ~AutoHideScreenEdgeV1() override; 0516 }; 0517 0518 class CursorShapeManagerV1 : public QObject, public QtWayland::wp_cursor_shape_manager_v1 0519 { 0520 Q_OBJECT 0521 public: 0522 ~CursorShapeManagerV1() override; 0523 }; 0524 0525 class CursorShapeDeviceV1 : public QObject, public QtWayland::wp_cursor_shape_device_v1 0526 { 0527 Q_OBJECT 0528 public: 0529 CursorShapeDeviceV1(CursorShapeManagerV1 *manager, KWayland::Client::Pointer *pointer); 0530 ~CursorShapeDeviceV1() override; 0531 }; 0532 0533 class FakeInput : public QtWayland::org_kde_kwin_fake_input 0534 { 0535 public: 0536 ~FakeInput() override; 0537 }; 0538 0539 class SecurityContextManagerV1 : public QtWayland::wp_security_context_manager_v1 0540 { 0541 public: 0542 ~SecurityContextManagerV1() override; 0543 }; 0544 0545 enum class AdditionalWaylandInterface { 0546 Seat = 1 << 0, 0547 PlasmaShell = 1 << 2, 0548 WindowManagement = 1 << 3, 0549 PointerConstraints = 1 << 4, 0550 IdleInhibitV1 = 1 << 5, 0551 AppMenu = 1 << 6, 0552 ShadowManager = 1 << 7, 0553 XdgDecorationV1 = 1 << 8, 0554 OutputManagementV2 = 1 << 9, 0555 TextInputManagerV2 = 1 << 10, 0556 InputMethodV1 = 1 << 11, 0557 LayerShellV1 = 1 << 12, 0558 TextInputManagerV3 = 1 << 13, 0559 OutputDeviceV2 = 1 << 14, 0560 FractionalScaleManagerV1 = 1 << 15, 0561 ScreencastingV1 = 1 << 16, 0562 ScreenEdgeV1 = 1 << 17, 0563 CursorShapeV1 = 1 << 18, 0564 FakeInput = 1 << 19, 0565 SecurityContextManagerV1 = 1 << 20, 0566 }; 0567 Q_DECLARE_FLAGS(AdditionalWaylandInterfaces, AdditionalWaylandInterface) 0568 0569 class VirtualInputDevice : public InputDevice 0570 { 0571 Q_OBJECT 0572 0573 public: 0574 explicit VirtualInputDevice(QObject *parent = nullptr); 0575 0576 void setPointer(bool set); 0577 void setKeyboard(bool set); 0578 void setTouch(bool set); 0579 void setLidSwitch(bool set); 0580 void setName(const QString &name); 0581 0582 QString sysName() const override; 0583 QString name() const override; 0584 0585 bool isEnabled() const override; 0586 void setEnabled(bool enabled) override; 0587 0588 LEDs leds() const override; 0589 void setLeds(LEDs leds) override; 0590 0591 bool isKeyboard() const override; 0592 bool isAlphaNumericKeyboard() const override; 0593 bool isPointer() const override; 0594 bool isTouchpad() const override; 0595 bool isTouch() const override; 0596 bool isTabletTool() const override; 0597 bool isTabletPad() const override; 0598 bool isTabletModeSwitch() const override; 0599 bool isLidSwitch() const override; 0600 0601 private: 0602 QString m_name; 0603 bool m_pointer = false; 0604 bool m_keyboard = false; 0605 bool m_touch = false; 0606 bool m_lidSwitch = false; 0607 }; 0608 0609 void keyboardKeyPressed(quint32 key, quint32 time); 0610 void keyboardKeyReleased(quint32 key, quint32 time); 0611 void pointerAxisHorizontal(qreal delta, 0612 quint32 time, 0613 qint32 discreteDelta = 0, 0614 InputRedirection::PointerAxisSource source = InputRedirection::PointerAxisSourceUnknown); 0615 void pointerAxisVertical(qreal delta, 0616 quint32 time, 0617 qint32 discreteDelta = 0, 0618 InputRedirection::PointerAxisSource source = InputRedirection::PointerAxisSourceUnknown); 0619 void pointerButtonPressed(quint32 button, quint32 time); 0620 void pointerButtonReleased(quint32 button, quint32 time); 0621 void pointerMotion(const QPointF &position, quint32 time); 0622 void pointerMotionRelative(const QPointF &delta, quint32 time); 0623 void touchCancel(); 0624 void touchDown(qint32 id, const QPointF &pos, quint32 time); 0625 void touchMotion(qint32 id, const QPointF &pos, quint32 time); 0626 void touchUp(qint32 id, quint32 time); 0627 0628 /** 0629 * Creates a Wayland Connection in a dedicated thread and creates various 0630 * client side objects which can be used to create windows. 0631 * @returns @c true if created successfully, @c false if there was an error 0632 * @see destroyWaylandConnection 0633 */ 0634 bool setupWaylandConnection(AdditionalWaylandInterfaces flags = AdditionalWaylandInterfaces()); 0635 0636 /** 0637 * Destroys the Wayland Connection created with @link{setupWaylandConnection}. 0638 * This can be called from cleanup in order to ensure that no Wayland Connection 0639 * leaks into the next test method. 0640 * @see setupWaylandConnection 0641 */ 0642 void destroyWaylandConnection(); 0643 0644 KWayland::Client::ConnectionThread *waylandConnection(); 0645 KWayland::Client::Compositor *waylandCompositor(); 0646 KWayland::Client::SubCompositor *waylandSubCompositor(); 0647 KWayland::Client::ShadowManager *waylandShadowManager(); 0648 KWayland::Client::ShmPool *waylandShmPool(); 0649 KWayland::Client::Seat *waylandSeat(); 0650 KWayland::Client::PlasmaShell *waylandPlasmaShell(); 0651 KWayland::Client::PlasmaWindowManagement *waylandWindowManagement(); 0652 KWayland::Client::PointerConstraints *waylandPointerConstraints(); 0653 KWayland::Client::AppMenuManager *waylandAppMenuManager(); 0654 WaylandOutputManagementV2 *waylandOutputManagementV2(); 0655 KWayland::Client::TextInputManager *waylandTextInputManager(); 0656 QList<KWayland::Client::Output *> waylandOutputs(); 0657 KWayland::Client::Output *waylandOutput(const QString &name); 0658 ScreencastingV1 *screencasting(); 0659 QList<WaylandOutputDeviceV2 *> waylandOutputDevicesV2(); 0660 FakeInput *waylandFakeInput(); 0661 SecurityContextManagerV1 *waylandSecurityContextManagerV1(); 0662 0663 bool waitForWaylandSurface(Window *window); 0664 0665 bool waitForWaylandPointer(); 0666 bool waitForWaylandTouch(); 0667 bool waitForWaylandKeyboard(); 0668 0669 void flushWaylandConnection(); 0670 0671 /** 0672 * Ensures that all client requests are processed by the compositor and all events 0673 * sent by the compositor are seen by the client. 0674 */ 0675 bool waylandSync(); 0676 0677 std::unique_ptr<KWayland::Client::Surface> createSurface(); 0678 KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface, 0679 KWayland::Client::Surface *parentSurface, QObject *parent = nullptr); 0680 0681 LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, 0682 const QString &scope, 0683 KWayland::Client::Output *output = nullptr, 0684 LayerShellV1::layer layer = LayerShellV1::layer_top); 0685 0686 TextInputManagerV3 *waylandTextInputManagerV3(); 0687 0688 enum class CreationSetup { 0689 CreateOnly, 0690 CreateAndConfigure, /// commit and wait for the configure event, making this surface ready to commit buffers 0691 }; 0692 0693 QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface, 0694 KWayland::Client::Output *output, 0695 MockInputMethod::Mode mode); 0696 0697 FractionalScaleV1 *createFractionalScaleV1(KWayland::Client::Surface *surface); 0698 0699 XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent = nullptr); 0700 XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, 0701 CreationSetup configureMode, 0702 QObject *parent = nullptr); 0703 0704 XdgPositioner *createXdgPositioner(); 0705 0706 XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, 0707 XdgPositioner *positioner, 0708 CreationSetup configureMode = CreationSetup::CreateAndConfigure, 0709 QObject *parent = nullptr); 0710 0711 XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent = nullptr); 0712 IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface); 0713 AutoHideScreenEdgeV1 *createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border); 0714 CursorShapeDeviceV1 *createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer); 0715 0716 /** 0717 * Creates a shared memory buffer of @p size in @p color and attaches it to the @p surface. 0718 * The @p surface gets damaged and committed, thus it's rendered. 0719 */ 0720 void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format = QImage::Format_ARGB32_Premultiplied); 0721 0722 /** 0723 * Creates a shared memory buffer using the supplied image @p img and attaches it to the @p surface 0724 */ 0725 void render(KWayland::Client::Surface *surface, const QImage &img); 0726 0727 /** 0728 * Waits till a new Window is shown and returns the created Window. 0729 * If no Window gets shown during @p timeout @c null is returned. 0730 */ 0731 Window *waitForWaylandWindowShown(int timeout = 5000); 0732 0733 /** 0734 * Combination of @link{render} and @link{waitForWaylandWindowShown}. 0735 */ 0736 Window *renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format = QImage::Format_ARGB32, int timeout = 5000); 0737 0738 Window *renderAndWaitForShown(KWayland::Client::Surface *surface, const QImage &img, int timeout = 5000); 0739 0740 /** 0741 * Waits for the @p window to be destroyed. 0742 */ 0743 bool waitForWindowClosed(Window *window); 0744 0745 /** 0746 * Locks the screen and waits till the screen is locked. 0747 * @returns @c true if the screen could be locked, @c false otherwise 0748 */ 0749 bool lockScreen(); 0750 0751 /** 0752 * Unlocks the screen and waits till the screen is unlocked. 0753 * @returns @c true if the screen could be unlocked, @c false otherwise 0754 */ 0755 bool unlockScreen(); 0756 0757 /** 0758 * Returns @c true if the system has at least one render node; otherwise returns @c false. 0759 * 0760 * This can be used to test whether the system is capable of allocating and sharing prime buffers, etc. 0761 */ 0762 bool renderNodeAvailable(); 0763 0764 /** 0765 * Creates an X11 connection 0766 * Internally a nested event loop is spawned whilst we connect to avoid a deadlock 0767 * with X on demand 0768 */ 0769 0770 struct XcbConnectionDeleter 0771 { 0772 void operator()(xcb_connection_t *pointer); 0773 }; 0774 0775 typedef std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> XcbConnectionPtr; 0776 XcbConnectionPtr createX11Connection(); 0777 0778 MockInputMethod *inputMethod(); 0779 KWayland::Client::Surface *inputPanelSurface(); 0780 0781 class ScreencastingStreamV1 : public QObject, public QtWayland::zkde_screencast_stream_unstable_v1 0782 { 0783 Q_OBJECT 0784 friend class ScreencastingV1; 0785 0786 public: 0787 ScreencastingStreamV1(QObject *parent) 0788 : QObject(parent) 0789 { 0790 } 0791 0792 ~ScreencastingStreamV1() override 0793 { 0794 if (isInitialized()) { 0795 close(); 0796 } 0797 } 0798 0799 quint32 nodeId() const 0800 { 0801 Q_ASSERT(m_nodeId.has_value()); 0802 return *m_nodeId; 0803 } 0804 0805 void zkde_screencast_stream_unstable_v1_created(uint32_t node) override 0806 { 0807 m_nodeId = node; 0808 Q_EMIT created(node); 0809 } 0810 0811 void zkde_screencast_stream_unstable_v1_closed() override 0812 { 0813 Q_EMIT closed(); 0814 } 0815 0816 void zkde_screencast_stream_unstable_v1_failed(const QString &error) override 0817 { 0818 Q_EMIT failed(error); 0819 } 0820 0821 Q_SIGNALS: 0822 void created(quint32 nodeid); 0823 void failed(const QString &error); 0824 void closed(); 0825 0826 private: 0827 std::optional<uint> m_nodeId; 0828 }; 0829 0830 class ScreencastingV1 : public QObject, public QtWayland::zkde_screencast_unstable_v1 0831 { 0832 Q_OBJECT 0833 public: 0834 explicit ScreencastingV1(QObject *parent = nullptr) 0835 : QObject(parent) 0836 { 0837 } 0838 0839 ScreencastingStreamV1 *createOutputStream(wl_output *output, pointer mode) 0840 { 0841 auto stream = new ScreencastingStreamV1(this); 0842 stream->init(stream_output(output, mode)); 0843 return stream; 0844 } 0845 0846 ScreencastingStreamV1 *createWindowStream(const QString &uuid, pointer mode) 0847 { 0848 auto stream = new ScreencastingStreamV1(this); 0849 stream->init(stream_window(uuid, mode)); 0850 return stream; 0851 } 0852 }; 0853 0854 struct OutputInfo 0855 { 0856 QRect geometry; 0857 double scale = 1; 0858 bool internal = false; 0859 }; 0860 void setOutputConfig(const QList<QRect> &geometries); 0861 void setOutputConfig(const QList<OutputInfo> &infos); 0862 } 0863 0864 } 0865 0866 Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::Test::AdditionalWaylandInterfaces) 0867 Q_DECLARE_METATYPE(KWin::Test::XdgToplevel::States) 0868 Q_DECLARE_METATYPE(QtWayland::zxdg_toplevel_decoration_v1::mode) 0869 0870 #define WAYLANDTEST_MAIN(TestObject) \ 0871 int main(int argc, char *argv[]) \ 0872 { \ 0873 setenv("QT_QPA_PLATFORM", "wayland-org.kde.kwin.qpa", true); \ 0874 setenv("QT_QPA_PLATFORM_PLUGIN_PATH", QFileInfo(QString::fromLocal8Bit(argv[0])).absolutePath().toLocal8Bit().constData(), true); \ 0875 setenv("KWIN_FORCE_OWN_QPA", "1", true); \ 0876 qunsetenv("KDE_FULL_SESSION"); \ 0877 qunsetenv("KDE_SESSION_VERSION"); \ 0878 qunsetenv("XDG_SESSION_DESKTOP"); \ 0879 qunsetenv("XDG_CURRENT_DESKTOP"); \ 0880 KWin::WaylandTestApplication app(KWin::Application::OperationModeXwayland, argc, argv); \ 0881 app.setAttribute(Qt::AA_Use96Dpi, true); \ 0882 TestObject tc; \ 0883 return QTest::qExec(&tc, argc, argv); \ 0884 } 0885 0886 #endif