File indexing completed on 2024-05-05 05:31:28

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