File indexing completed on 2024-05-05 17:35:45

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 "composite.h"
0012 #include "core/output.h"
0013 #include "core/outputbackend.h"
0014 #include "core/renderbackend.h"
0015 #include "cursor.h"
0016 #include "wayland_server.h"
0017 #include "workspace.h"
0018 #include "x11window.h"
0019 #include <kwineffects.h>
0020 
0021 #include <KDecoration2/Decoration>
0022 
0023 #include <linux/input.h>
0024 
0025 namespace KWin
0026 {
0027 
0028 static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_empty_decoration-0");
0029 
0030 class DontCrashEmptyDecorationTest : public QObject
0031 {
0032     Q_OBJECT
0033 private Q_SLOTS:
0034     void initTestCase();
0035     void init();
0036     void testBug361551();
0037 };
0038 
0039 void DontCrashEmptyDecorationTest::initTestCase()
0040 {
0041     qRegisterMetaType<KWin::Window *>();
0042     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0043     QVERIFY(waylandServer()->init(s_socketName));
0044     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0045 
0046     // this test needs to enforce OpenGL compositing to get into the crashy condition
0047     qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
0048     kwinApp()->start();
0049     QVERIFY(applicationStartedSpy.wait());
0050     const auto outputs = workspace()->outputs();
0051     QCOMPARE(outputs.count(), 2);
0052     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0053     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0054     setenv("QT_QPA_PLATFORM", "wayland", true);
0055 
0056     QCOMPARE(Compositor::self()->backend()->compositingType(), KWin::OpenGLCompositing);
0057 }
0058 
0059 void DontCrashEmptyDecorationTest::init()
0060 {
0061     workspace()->setActiveOutput(QPoint(640, 512));
0062     Cursors::self()->mouse()->setPos(QPoint(640, 512));
0063 }
0064 
0065 void DontCrashEmptyDecorationTest::testBug361551()
0066 {
0067     // this test verifies that resizing an X11 window to an invalid size does not result in crash on unmap
0068     // when the DecorationRenderer gets copied to the Deleted
0069     // there a repaint is scheduled and the resulting texture is invalid if the window size is invalid
0070 
0071     // create an xcb window
0072     xcb_connection_t *c = xcb_connect(nullptr, nullptr);
0073     QVERIFY(!xcb_connection_has_error(c));
0074 
0075     xcb_window_t windowId = xcb_generate_id(c);
0076     xcb_create_window(c, XCB_COPY_FROM_PARENT, windowId, rootWindow(), 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
0077     xcb_map_window(c, windowId);
0078     xcb_flush(c);
0079 
0080     // we should get a window for it
0081     QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
0082     QVERIFY(windowCreatedSpy.wait());
0083     X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
0084     QVERIFY(window);
0085     QCOMPARE(window->window(), windowId);
0086     QVERIFY(window->isDecorated());
0087 
0088     // let's set a stupid geometry
0089     window->moveResize({0, 0, 0, 0});
0090     QCOMPARE(window->frameGeometry(), QRect(0, 0, 0, 0));
0091 
0092     // and destroy the window again
0093     xcb_unmap_window(c, windowId);
0094     xcb_destroy_window(c, windowId);
0095     xcb_flush(c);
0096     xcb_disconnect(c);
0097 
0098     QSignalSpy windowClosedSpy(window, &X11Window::windowClosed);
0099     QVERIFY(windowClosedSpy.wait());
0100 }
0101 
0102 }
0103 
0104 WAYLANDTEST_MAIN(KWin::DontCrashEmptyDecorationTest)
0105 #include "dont_crash_empty_deco.moc"