File indexing completed on 2024-11-10 04:55:57
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "kwin_wayland_test.h" 0010 0011 #include "core/output.h" 0012 #include "pointer_input.h" 0013 #include "utils/xcbutils.h" 0014 #include "wayland_server.h" 0015 #include "window.h" 0016 #include "workspace.h" 0017 #include "x11window.h" 0018 0019 #include <netwm.h> 0020 #include <xcb/xcb_icccm.h> 0021 0022 namespace KWin 0023 { 0024 0025 static const QString s_socketName = QStringLiteral("wayland_test_kwin_x11_desktop_window-0"); 0026 0027 class X11DesktopWindowTest : public QObject 0028 { 0029 Q_OBJECT 0030 private Q_SLOTS: 0031 void initTestCase(); 0032 void init(); 0033 void cleanup(); 0034 void testDesktopWindow(); 0035 0036 private: 0037 }; 0038 0039 void X11DesktopWindowTest::initTestCase() 0040 { 0041 qRegisterMetaType<KWin::Window *>(); 0042 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0043 QVERIFY(waylandServer()->init(s_socketName)); 0044 Test::setOutputConfig({ 0045 QRect(0, 0, 1280, 1024), 0046 QRect(1280, 0, 1280, 1024), 0047 }); 0048 0049 kwinApp()->start(); 0050 QVERIFY(applicationStartedSpy.wait()); 0051 const auto outputs = workspace()->outputs(); 0052 QCOMPARE(outputs.count(), 2); 0053 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0054 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0055 setenv("QT_QPA_PLATFORM", "wayland", true); 0056 } 0057 0058 void X11DesktopWindowTest::init() 0059 { 0060 workspace()->setActiveOutput(QPoint(640, 512)); 0061 input()->pointer()->warp(QPoint(640, 512)); 0062 } 0063 0064 void X11DesktopWindowTest::cleanup() 0065 { 0066 } 0067 0068 void X11DesktopWindowTest::testDesktopWindow() 0069 { 0070 // this test creates a desktop window with an RGBA visual and verifies that it's only considered 0071 // as an RGB (opaque) window in KWin 0072 0073 // create an xcb window 0074 Test::XcbConnectionPtr c = Test::createX11Connection(); 0075 QVERIFY(!xcb_connection_has_error(c.get())); 0076 0077 xcb_window_t windowId = xcb_generate_id(c.get()); 0078 const QRect windowGeometry(0, 0, 1280, 1024); 0079 0080 // helper to find the visual 0081 auto findDepth = [&c]() -> xcb_visualid_t { 0082 // find a visual with 32 depth 0083 const xcb_setup_t *setup = xcb_get_setup(c.get()); 0084 0085 for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) { 0086 for (auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) { 0087 if (depth.data->depth != 32) { 0088 continue; 0089 } 0090 const int len = xcb_depth_visuals_length(depth.data); 0091 const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data); 0092 0093 for (int i = 0; i < len; i++) { 0094 return visuals[0].visual_id; 0095 } 0096 } 0097 } 0098 return 0; 0099 }; 0100 auto visualId = findDepth(); 0101 auto colormapId = xcb_generate_id(c.get()); 0102 auto cmCookie = xcb_create_colormap_checked(c.get(), XCB_COLORMAP_ALLOC_NONE, colormapId, rootWindow(), visualId); 0103 QVERIFY(!xcb_request_check(c.get(), cmCookie)); 0104 0105 const uint32_t values[] = {XCB_PIXMAP_NONE, Xcb::defaultScreen()->black_pixel, colormapId}; 0106 auto cookie = xcb_create_window_checked(c.get(), 32, windowId, rootWindow(), 0107 windowGeometry.x(), 0108 windowGeometry.y(), 0109 windowGeometry.width(), 0110 windowGeometry.height(), 0111 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visualId, XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, values); 0112 QVERIFY(!xcb_request_check(c.get(), cookie)); 0113 xcb_size_hints_t hints; 0114 memset(&hints, 0, sizeof(hints)); 0115 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); 0116 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); 0117 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints); 0118 NETWinInfo info(c.get(), windowId, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties); 0119 info.setWindowType(NET::Desktop); 0120 xcb_map_window(c.get(), windowId); 0121 xcb_flush(c.get()); 0122 0123 // verify through a geometry request that it's depth 32 0124 Xcb::WindowGeometry geo(windowId); 0125 QCOMPARE(geo->depth, uint8_t(32)); 0126 0127 // we should get a window for it 0128 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded); 0129 QVERIFY(windowCreatedSpy.wait()); 0130 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>(); 0131 QVERIFY(window); 0132 QCOMPARE(window->window(), windowId); 0133 QVERIFY(!window->isDecorated()); 0134 QCOMPARE(window->windowType(), NET::Desktop); 0135 QCOMPARE(window->frameGeometry(), windowGeometry); 0136 QVERIFY(window->isDesktop()); 0137 QCOMPARE(window->depth(), 24); 0138 QVERIFY(!window->hasAlpha()); 0139 0140 // and destroy the window again 0141 xcb_unmap_window(c.get(), windowId); 0142 xcb_destroy_window(c.get(), windowId); 0143 xcb_flush(c.get()); 0144 c.reset(); 0145 0146 QSignalSpy windowClosedSpy(window, &X11Window::closed); 0147 QVERIFY(windowClosedSpy.wait()); 0148 } 0149 0150 } 0151 0152 WAYLANDTEST_MAIN(KWin::X11DesktopWindowTest) 0153 #include "desktop_window_x11_test.moc"