File indexing completed on 2024-11-10 04:55:58
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "kwin_wayland_test.h" 0011 0012 #include "compositor.h" 0013 #include "core/output.h" 0014 #include "effect/effecthandler.h" 0015 #include "effect/effectloader.h" 0016 #include "wayland_server.h" 0017 #include "window.h" 0018 #include "workspace.h" 0019 0020 #include <KWayland/Client/surface.h> 0021 0022 namespace KWin 0023 { 0024 0025 static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_reinitialize_compositor-0"); 0026 0027 class DontCrashReinitializeCompositorTest : public QObject 0028 { 0029 Q_OBJECT 0030 0031 private Q_SLOTS: 0032 void initTestCase(); 0033 void init(); 0034 void cleanup(); 0035 0036 void testReinitializeCompositor_data(); 0037 void testReinitializeCompositor(); 0038 }; 0039 0040 void DontCrashReinitializeCompositorTest::initTestCase() 0041 { 0042 if (!Test::renderNodeAvailable()) { 0043 QSKIP("no render node available"); 0044 return; 0045 } 0046 qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8()); 0047 0048 qRegisterMetaType<KWin::Window *>(); 0049 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0050 QVERIFY(waylandServer()->init(s_socketName)); 0051 Test::setOutputConfig({ 0052 QRect(0, 0, 1280, 1024), 0053 QRect(1280, 0, 1280, 1024), 0054 }); 0055 0056 auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); 0057 KConfigGroup plugins(config, QStringLiteral("Plugins")); 0058 const auto builtinNames = EffectLoader().listOfKnownEffects(); 0059 for (const QString &name : builtinNames) { 0060 plugins.writeEntry(name + QStringLiteral("Enabled"), false); 0061 } 0062 config->sync(); 0063 kwinApp()->setConfig(config); 0064 0065 qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2")); 0066 qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", QByteArrayLiteral("1")); 0067 0068 kwinApp()->start(); 0069 QVERIFY(applicationStartedSpy.wait()); 0070 const auto outputs = workspace()->outputs(); 0071 QCOMPARE(outputs.count(), 2); 0072 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0073 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0074 } 0075 0076 void DontCrashReinitializeCompositorTest::init() 0077 { 0078 QVERIFY(Test::setupWaylandConnection()); 0079 } 0080 0081 void DontCrashReinitializeCompositorTest::cleanup() 0082 { 0083 // Unload all effects. 0084 effects->unloadAllEffects(); 0085 QVERIFY(effects->loadedEffects().isEmpty()); 0086 0087 Test::destroyWaylandConnection(); 0088 } 0089 0090 void DontCrashReinitializeCompositorTest::testReinitializeCompositor_data() 0091 { 0092 QTest::addColumn<QString>("effectName"); 0093 0094 QTest::newRow("Fade") << QStringLiteral("fade"); 0095 QTest::newRow("Glide") << QStringLiteral("glide"); 0096 QTest::newRow("Scale") << QStringLiteral("scale"); 0097 } 0098 0099 void DontCrashReinitializeCompositorTest::testReinitializeCompositor() 0100 { 0101 // This test verifies that KWin doesn't crash when the compositor settings 0102 // have been changed while a scripted effect animates the disappearing of 0103 // a window. 0104 0105 // Create the test window. 0106 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0107 QVERIFY(surface != nullptr); 0108 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0109 QVERIFY(shellSurface != nullptr); 0110 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0111 QVERIFY(window); 0112 0113 // Make sure that only the test effect is loaded. 0114 QFETCH(QString, effectName); 0115 QVERIFY(effects->loadEffect(effectName)); 0116 QCOMPARE(effects->loadedEffects().count(), 1); 0117 QCOMPARE(effects->loadedEffects().first(), effectName); 0118 Effect *effect = effects->findEffect(effectName); 0119 QVERIFY(effect); 0120 QVERIFY(!effect->isActive()); 0121 0122 // Close the test window. 0123 QSignalSpy windowClosedSpy(window, &Window::closed); 0124 shellSurface.reset(); 0125 surface.reset(); 0126 QVERIFY(windowClosedSpy.wait()); 0127 0128 // The test effect should start animating the test window. Is there a better 0129 // way to verify that the test effect actually animates the test window? 0130 QVERIFY(effect->isActive()); 0131 0132 // Re-initialize the compositor, effects will be destroyed and created again. 0133 Compositor::self()->reinitialize(); 0134 0135 // By this time, KWin should still be alive. 0136 } 0137 0138 } // namespace KWin 0139 0140 WAYLANDTEST_MAIN(KWin::DontCrashReinitializeCompositorTest) 0141 #include "dont_crash_reinitialize_compositor.moc"