KWin
Loading...
Searching...
No Matches
desktop_window_x11_test.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: 2016 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "core/output.h"
12#include "pointer_input.h"
13#include "utils/xcbutils.h"
14#include "wayland_server.h"
15#include "window.h"
16#include "workspace.h"
17#include "x11window.h"
18
19#include <netwm.h>
20#include <xcb/xcb_icccm.h>
21
22namespace KWin
23{
24
25static const QString s_socketName = QStringLiteral("wayland_test_kwin_x11_desktop_window-0");
26
27class X11DesktopWindowTest : public QObject
28{
29 Q_OBJECT
30private Q_SLOTS:
31 void initTestCase();
32 void init();
33 void cleanup();
34 void testDesktopWindow();
35
36private:
37};
38
39void X11DesktopWindowTest::initTestCase()
40{
41 qRegisterMetaType<KWin::Window *>();
42 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
43 QVERIFY(waylandServer()->init(s_socketName));
45 QRect(0, 0, 1280, 1024),
46 QRect(1280, 0, 1280, 1024),
47 });
48
49 kwinApp()->start();
50 QVERIFY(applicationStartedSpy.wait());
51 const auto outputs = workspace()->outputs();
52 QCOMPARE(outputs.count(), 2);
53 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
54 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
55 setenv("QT_QPA_PLATFORM", "wayland", true);
56}
57
58void X11DesktopWindowTest::init()
59{
60 workspace()->setActiveOutput(QPoint(640, 512));
61 input()->pointer()->warp(QPoint(640, 512));
62}
63
64void X11DesktopWindowTest::cleanup()
65{
66}
67
68void X11DesktopWindowTest::testDesktopWindow()
69{
70 // this test creates a desktop window with an RGBA visual and verifies that it's only considered
71 // as an RGB (opaque) window in KWin
72
73 // create an xcb window
75 QVERIFY(!xcb_connection_has_error(c.get()));
76
77 xcb_window_t windowId = xcb_generate_id(c.get());
78 const QRect windowGeometry(0, 0, 1280, 1024);
79
80 // helper to find the visual
81 auto findDepth = [&c]() -> xcb_visualid_t {
82 // find a visual with 32 depth
83 const xcb_setup_t *setup = xcb_get_setup(c.get());
84
85 for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) {
86 for (auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) {
87 if (depth.data->depth != 32) {
88 continue;
89 }
90 const int len = xcb_depth_visuals_length(depth.data);
91 const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
92
93 for (int i = 0; i < len; i++) {
94 return visuals[0].visual_id;
95 }
96 }
97 }
98 return 0;
99 };
100 auto visualId = findDepth();
101 auto colormapId = xcb_generate_id(c.get());
102 auto cmCookie = xcb_create_colormap_checked(c.get(), XCB_COLORMAP_ALLOC_NONE, colormapId, rootWindow(), visualId);
103 QVERIFY(!xcb_request_check(c.get(), cmCookie));
104
105 const uint32_t values[] = {XCB_PIXMAP_NONE, Xcb::defaultScreen()->black_pixel, colormapId};
106 auto cookie = xcb_create_window_checked(c.get(), 32, windowId, rootWindow(),
107 windowGeometry.x(),
108 windowGeometry.y(),
109 windowGeometry.width(),
110 windowGeometry.height(),
111 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visualId, XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, values);
112 QVERIFY(!xcb_request_check(c.get(), cookie));
113 xcb_size_hints_t hints;
114 memset(&hints, 0, sizeof(hints));
115 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
116 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
117 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
118 NETWinInfo info(c.get(), windowId, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties);
119 info.setWindowType(NET::Desktop);
120 xcb_map_window(c.get(), windowId);
121 xcb_flush(c.get());
122
123 // verify through a geometry request that it's depth 32
124 Xcb::WindowGeometry geo(windowId);
125 QCOMPARE(geo->depth, uint8_t(32));
126
127 // we should get a window for it
128 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
129 QVERIFY(windowCreatedSpy.wait());
130 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
131 QVERIFY(window);
132 QCOMPARE(window->window(), windowId);
133 QVERIFY(!window->isDecorated());
134 QCOMPARE(window->windowType(), NET::Desktop);
135 QCOMPARE(window->frameGeometry(), windowGeometry);
136 QVERIFY(window->isDesktop());
137 QCOMPARE(window->depth(), 24);
138 QVERIFY(!window->hasAlpha());
139
140 // and destroy the window again
141 xcb_unmap_window(c.get(), windowId);
142 xcb_destroy_window(c.get(), windowId);
143 xcb_flush(c.get());
144 c.reset();
145
146 QSignalSpy windowClosedSpy(window, &X11Window::closed);
147 QVERIFY(windowClosedSpy.wait());
148}
149
150}
151
153#include "desktop_window_x11_test.moc"
PointerInputRedirection * pointer() const
Definition input.h:220
void warp(const QPointF &pos)
void windowAdded(KWin::Window *)
QList< Output * > outputs() const
Definition workspace.h:762
void setActiveOutput(Output *output)
#define WAYLANDTEST_MAIN(TestObject)
void setOutputConfig(const QList< QRect > &geometries)
XcbConnectionPtr createX11Connection()
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549