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: 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"