File indexing completed on 2024-04-21 16:14:42

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "testutils.h"
0010 // KWin
0011 #include "utils/xcbutils.h"
0012 // Qt
0013 #include <QApplication>
0014 #include <QtTest>
0015 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0016 #include <private/qtx11extras_p.h>
0017 #else
0018 #include <QX11Info>
0019 #endif
0020 // xcb
0021 #include <xcb/xcb.h>
0022 
0023 using namespace KWin;
0024 
0025 class TestXcbWindow : public QObject
0026 {
0027     Q_OBJECT
0028 private Q_SLOTS:
0029     void initTestCase();
0030     void defaultCtor();
0031     void ctor();
0032     void classCtor();
0033     void create();
0034     void mapUnmap();
0035     void geometry();
0036     void destroy();
0037     void destroyNotManaged();
0038 };
0039 
0040 void TestXcbWindow::initTestCase()
0041 {
0042     qApp->setProperty("x11RootWindow", QVariant::fromValue<quint32>(QX11Info::appRootWindow()));
0043     qApp->setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
0044 }
0045 
0046 void TestXcbWindow::defaultCtor()
0047 {
0048     Xcb::Window window;
0049     QCOMPARE(window.isValid(), false);
0050     xcb_window_t wId = window;
0051     QCOMPARE(wId, noneWindow());
0052 
0053     xcb_window_t nativeWindow = createWindow();
0054     Xcb::Window window2(nativeWindow);
0055     QCOMPARE(window2.isValid(), true);
0056     wId = window2;
0057     QCOMPARE(wId, nativeWindow);
0058 }
0059 
0060 void TestXcbWindow::ctor()
0061 {
0062     const QRect geometry(0, 0, 10, 10);
0063     const uint32_t values[] = {true};
0064     Xcb::Window window(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
0065     QCOMPARE(window.isValid(), true);
0066     QVERIFY(window != XCB_WINDOW_NONE);
0067     Xcb::WindowGeometry windowGeometry(window);
0068     QCOMPARE(windowGeometry.isNull(), false);
0069     QCOMPARE(windowGeometry.rect(), geometry);
0070 }
0071 
0072 void TestXcbWindow::classCtor()
0073 {
0074     const QRect geometry(0, 0, 10, 10);
0075     const uint32_t values[] = {true};
0076     Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
0077     QCOMPARE(window.isValid(), true);
0078     QVERIFY(window != XCB_WINDOW_NONE);
0079     Xcb::WindowGeometry windowGeometry(window);
0080     QCOMPARE(windowGeometry.isNull(), false);
0081     QCOMPARE(windowGeometry.rect(), geometry);
0082 
0083     Xcb::WindowAttributes attribs(window);
0084     QCOMPARE(attribs.isNull(), false);
0085     QVERIFY(attribs->_class == XCB_WINDOW_CLASS_INPUT_ONLY);
0086 }
0087 
0088 void TestXcbWindow::create()
0089 {
0090     Xcb::Window window;
0091     QCOMPARE(window.isValid(), false);
0092     xcb_window_t wId = window;
0093     QCOMPARE(wId, noneWindow());
0094 
0095     const QRect geometry(0, 0, 10, 10);
0096     const uint32_t values[] = {true};
0097     window.create(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
0098     QCOMPARE(window.isValid(), true);
0099     QVERIFY(window != XCB_WINDOW_NONE);
0100     // and reset again
0101     window.reset();
0102     QCOMPARE(window.isValid(), false);
0103     QVERIFY(window == XCB_WINDOW_NONE);
0104 }
0105 
0106 void TestXcbWindow::mapUnmap()
0107 {
0108     const QRect geometry(0, 0, 10, 10);
0109     const uint32_t values[] = {true};
0110     Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
0111     Xcb::WindowAttributes attribs(window);
0112     QCOMPARE(attribs.isNull(), false);
0113     QVERIFY(attribs->map_state == XCB_MAP_STATE_UNMAPPED);
0114 
0115     window.map();
0116     Xcb::WindowAttributes attribs2(window);
0117     QCOMPARE(attribs2.isNull(), false);
0118     QVERIFY(attribs2->map_state != XCB_MAP_STATE_UNMAPPED);
0119 
0120     window.unmap();
0121     Xcb::WindowAttributes attribs3(window);
0122     QCOMPARE(attribs3.isNull(), false);
0123     QVERIFY(attribs3->map_state == XCB_MAP_STATE_UNMAPPED);
0124 
0125     // map, unmap shouldn't fail for an invalid window, it's just ignored
0126     window.reset();
0127     window.map();
0128     window.unmap();
0129 }
0130 
0131 void TestXcbWindow::geometry()
0132 {
0133     const QRect geometry(0, 0, 10, 10);
0134     const uint32_t values[] = {true};
0135     Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
0136     Xcb::WindowGeometry windowGeometry(window);
0137     QCOMPARE(windowGeometry.isNull(), false);
0138     QCOMPARE(windowGeometry.rect(), geometry);
0139 
0140     const QRect geometry2(10, 20, 100, 200);
0141     window.setGeometry(geometry2);
0142     Xcb::WindowGeometry windowGeometry2(window);
0143     QCOMPARE(windowGeometry2.isNull(), false);
0144     QCOMPARE(windowGeometry2.rect(), geometry2);
0145 
0146     // setting a geometry on an invalid window should be ignored
0147     window.reset();
0148     window.setGeometry(geometry2);
0149     Xcb::WindowGeometry windowGeometry3(window);
0150     QCOMPARE(windowGeometry3.isNull(), true);
0151 }
0152 
0153 void TestXcbWindow::destroy()
0154 {
0155     const QRect geometry(0, 0, 10, 10);
0156     const uint32_t values[] = {true};
0157     Xcb::Window window(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
0158     QCOMPARE(window.isValid(), true);
0159     xcb_window_t wId = window;
0160 
0161     window.create(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
0162     // wId should now be invalid
0163     xcb_generic_error_t *error = nullptr;
0164     UniqueCPtr<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(
0165         connection(),
0166         xcb_get_window_attributes(connection(), wId),
0167         &error));
0168     QVERIFY(!attribs);
0169     QCOMPARE(error->error_code, uint8_t(3));
0170     QCOMPARE(error->resource_id, wId);
0171     free(error);
0172 
0173     // test the same for the dtor
0174     {
0175         Xcb::Window scopedWindow(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
0176         QVERIFY(scopedWindow.isValid());
0177         wId = scopedWindow;
0178     }
0179     error = nullptr;
0180     UniqueCPtr<xcb_get_window_attributes_reply_t> attribs2(xcb_get_window_attributes_reply(
0181         connection(),
0182         xcb_get_window_attributes(connection(), wId),
0183         &error));
0184     QVERIFY(!attribs2);
0185     QCOMPARE(error->error_code, uint8_t(3));
0186     QCOMPARE(error->resource_id, wId);
0187     free(error);
0188 }
0189 
0190 void TestXcbWindow::destroyNotManaged()
0191 {
0192     Xcb::Window window;
0193     // just destroy the non-existing window
0194     window.reset();
0195 
0196     // now let's add a window
0197     window.reset(createWindow(), false);
0198     xcb_window_t w = window;
0199     window.reset();
0200     Xcb::WindowAttributes attribs(w);
0201     QVERIFY(attribs);
0202 }
0203 
0204 Q_CONSTRUCTOR_FUNCTION(forceXcb)
0205 QTEST_MAIN(TestXcbWindow)
0206 #include "test_xcb_window.moc"