File indexing completed on 2025-03-23 13:47:56
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2015 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/outputbackend.h" 0012 #include "deleted.h" 0013 #include "wayland_server.h" 0014 #include "window.h" 0015 #include "workspace.h" 0016 #include "x11window.h" 0017 0018 #include <KDecoration2/Decoration> 0019 0020 namespace KWin 0021 { 0022 0023 static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_glxgears-0"); 0024 0025 class DontCrashGlxgearsTest : public QObject 0026 { 0027 Q_OBJECT 0028 private Q_SLOTS: 0029 void initTestCase(); 0030 void testGlxgears(); 0031 }; 0032 0033 void DontCrashGlxgearsTest::initTestCase() 0034 { 0035 qRegisterMetaType<KWin::Deleted *>(); 0036 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0037 QVERIFY(waylandServer()->init(s_socketName)); 0038 QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024))); 0039 kwinApp()->start(); 0040 QVERIFY(applicationStartedSpy.wait()); 0041 } 0042 0043 void DontCrashGlxgearsTest::testGlxgears() 0044 { 0045 // closing a glxgears window through Aurorae themes used to crash KWin 0046 // Let's make sure that doesn't happen anymore 0047 0048 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); 0049 0050 QProcess glxgears; 0051 glxgears.setProgram(QStringLiteral("glxgears")); 0052 glxgears.start(); 0053 QVERIFY(glxgears.waitForStarted()); 0054 0055 QVERIFY(windowAddedSpy.wait()); 0056 QCOMPARE(windowAddedSpy.count(), 1); 0057 QCOMPARE(workspace()->clientList().count(), 1); 0058 X11Window *glxgearsWindow = workspace()->clientList().first(); 0059 QVERIFY(glxgearsWindow->isDecorated()); 0060 QSignalSpy closedSpy(glxgearsWindow, &X11Window::windowClosed); 0061 KDecoration2::Decoration *decoration = glxgearsWindow->decoration(); 0062 QVERIFY(decoration); 0063 0064 // send a mouse event to the position of the close button 0065 // TODO: position is dependent on the decoration in use. We should use a static target instead, a fake deco for autotests. 0066 QPointF pos = decoration->rect().topRight() + QPointF(-decoration->borderTop() / 2, decoration->borderTop() / 2); 0067 QHoverEvent event(QEvent::HoverMove, pos, pos); 0068 QCoreApplication::instance()->sendEvent(decoration, &event); 0069 // mouse press 0070 QMouseEvent mousePressevent(QEvent::MouseButtonPress, pos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); 0071 mousePressevent.setAccepted(false); 0072 QCoreApplication::sendEvent(decoration, &mousePressevent); 0073 QVERIFY(mousePressevent.isAccepted()); 0074 // mouse Release 0075 QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, pos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); 0076 mouseReleaseEvent.setAccepted(false); 0077 QCoreApplication::sendEvent(decoration, &mouseReleaseEvent); 0078 QVERIFY(mouseReleaseEvent.isAccepted()); 0079 0080 QVERIFY(closedSpy.wait()); 0081 QCOMPARE(closedSpy.count(), 1); 0082 xcb_flush(connection()); 0083 0084 if (glxgears.state() == QProcess::Running) { 0085 QVERIFY(glxgears.waitForFinished()); 0086 } 0087 } 0088 0089 } 0090 0091 WAYLANDTEST_MAIN(KWin::DontCrashGlxgearsTest) 0092 #include "dont_crash_glxgears.moc"