File indexing completed on 2024-11-10 04:55:55
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 "effect/effecthandler.h" 0013 #include "effect/effectloader.h" 0014 #include "wayland_server.h" 0015 #include "window.h" 0016 #include "workspace.h" 0017 0018 #include <KWayland/Client/surface.h> 0019 0020 using namespace KWin; 0021 0022 static const QString s_socketName = QStringLiteral("wayland_test_effects_toplevel_open_close_animation-0"); 0023 0024 class ToplevelOpenCloseAnimationTest : public QObject 0025 { 0026 Q_OBJECT 0027 0028 private Q_SLOTS: 0029 void initTestCase(); 0030 void init(); 0031 void cleanup(); 0032 0033 void testAnimateToplevels_data(); 0034 void testAnimateToplevels(); 0035 void testDontAnimatePopups_data(); 0036 void testDontAnimatePopups(); 0037 }; 0038 0039 void ToplevelOpenCloseAnimationTest::initTestCase() 0040 { 0041 if (!Test::renderNodeAvailable()) { 0042 QSKIP("no render node available"); 0043 return; 0044 } 0045 qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8()); 0046 0047 qRegisterMetaType<KWin::Window *>(); 0048 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0049 QVERIFY(waylandServer()->init(s_socketName)); 0050 Test::setOutputConfig({ 0051 QRect(0, 0, 1280, 1024), 0052 QRect(1280, 0, 1280, 1024), 0053 }); 0054 0055 auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); 0056 KConfigGroup plugins(config, QStringLiteral("Plugins")); 0057 const auto builtinNames = EffectLoader().listOfKnownEffects(); 0058 for (const QString &name : builtinNames) { 0059 plugins.writeEntry(name + QStringLiteral("Enabled"), false); 0060 } 0061 config->sync(); 0062 kwinApp()->setConfig(config); 0063 0064 qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2")); 0065 qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", QByteArrayLiteral("1")); 0066 0067 kwinApp()->start(); 0068 QVERIFY(applicationStartedSpy.wait()); 0069 } 0070 0071 void ToplevelOpenCloseAnimationTest::init() 0072 { 0073 QVERIFY(Test::setupWaylandConnection()); 0074 } 0075 0076 void ToplevelOpenCloseAnimationTest::cleanup() 0077 { 0078 effects->unloadAllEffects(); 0079 QVERIFY(effects->loadedEffects().isEmpty()); 0080 0081 Test::destroyWaylandConnection(); 0082 } 0083 0084 void ToplevelOpenCloseAnimationTest::testAnimateToplevels_data() 0085 { 0086 QTest::addColumn<QString>("effectName"); 0087 0088 QTest::newRow("Fade") << QStringLiteral("fade"); 0089 QTest::newRow("Glide") << QStringLiteral("glide"); 0090 QTest::newRow("Scale") << QStringLiteral("scale"); 0091 } 0092 0093 void ToplevelOpenCloseAnimationTest::testAnimateToplevels() 0094 { 0095 // This test verifies that window open/close animation effects try to 0096 // animate the appearing and the disappearing of toplevel windows. 0097 0098 // Load effect that will be tested. 0099 QFETCH(QString, effectName); 0100 QVERIFY(effects->loadEffect(effectName)); 0101 QCOMPARE(effects->loadedEffects().count(), 1); 0102 QCOMPARE(effects->loadedEffects().first(), effectName); 0103 Effect *effect = effects->findEffect(effectName); 0104 QVERIFY(effect); 0105 QVERIFY(!effect->isActive()); 0106 0107 // Create the test window. 0108 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0109 QVERIFY(surface != nullptr); 0110 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0111 QVERIFY(shellSurface != nullptr); 0112 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0113 QVERIFY(window); 0114 QVERIFY(effect->isActive()); 0115 0116 // Eventually, the animation will be complete. 0117 QTRY_VERIFY(!effect->isActive()); 0118 0119 // Close the test window, the effect should start animating the disappearing 0120 // of the window. 0121 QSignalSpy windowClosedSpy(window, &Window::closed); 0122 shellSurface.reset(); 0123 surface.reset(); 0124 QVERIFY(windowClosedSpy.wait()); 0125 QVERIFY(effect->isActive()); 0126 0127 // Eventually, the animation will be complete. 0128 QTRY_VERIFY(!effect->isActive()); 0129 } 0130 0131 void ToplevelOpenCloseAnimationTest::testDontAnimatePopups_data() 0132 { 0133 QTest::addColumn<QString>("effectName"); 0134 0135 QTest::newRow("Fade") << QStringLiteral("fade"); 0136 QTest::newRow("Glide") << QStringLiteral("glide"); 0137 QTest::newRow("Scale") << QStringLiteral("scale"); 0138 } 0139 0140 void ToplevelOpenCloseAnimationTest::testDontAnimatePopups() 0141 { 0142 // This test verifies that window open/close animation effects don't try 0143 // to animate popups(e.g. popup menus, tooltips, etc). 0144 0145 // Create the main window. 0146 std::unique_ptr<KWayland::Client::Surface> mainWindowSurface(Test::createSurface()); 0147 QVERIFY(mainWindowSurface != nullptr); 0148 std::unique_ptr<Test::XdgToplevel> mainWindowShellSurface(Test::createXdgToplevelSurface(mainWindowSurface.get())); 0149 QVERIFY(mainWindowShellSurface != nullptr); 0150 Window *mainWindow = Test::renderAndWaitForShown(mainWindowSurface.get(), QSize(100, 50), Qt::blue); 0151 QVERIFY(mainWindow); 0152 0153 // Load effect that will be tested. 0154 QFETCH(QString, effectName); 0155 QVERIFY(effects->loadEffect(effectName)); 0156 QCOMPARE(effects->loadedEffects().count(), 1); 0157 QCOMPARE(effects->loadedEffects().first(), effectName); 0158 Effect *effect = effects->findEffect(effectName); 0159 QVERIFY(effect); 0160 QVERIFY(!effect->isActive()); 0161 0162 // Create a popup, it should not be animated. 0163 std::unique_ptr<KWayland::Client::Surface> popupSurface(Test::createSurface()); 0164 QVERIFY(popupSurface != nullptr); 0165 std::unique_ptr<Test::XdgPositioner> positioner(Test::createXdgPositioner()); 0166 QVERIFY(positioner); 0167 positioner->set_size(20, 20); 0168 positioner->set_anchor_rect(0, 0, 10, 10); 0169 positioner->set_gravity(Test::XdgPositioner::gravity_bottom_right); 0170 positioner->set_anchor(Test::XdgPositioner::anchor_bottom_left); 0171 std::unique_ptr<Test::XdgPopup> popupShellSurface(Test::createXdgPopupSurface(popupSurface.get(), mainWindowShellSurface->xdgSurface(), positioner.get())); 0172 QVERIFY(popupShellSurface != nullptr); 0173 Window *popup = Test::renderAndWaitForShown(popupSurface.get(), QSize(20, 20), Qt::red); 0174 QVERIFY(popup); 0175 QVERIFY(popup->isPopupWindow()); 0176 QCOMPARE(popup->transientFor(), mainWindow); 0177 QVERIFY(!effect->isActive()); 0178 0179 // Destroy the popup, it should not be animated. 0180 QSignalSpy popupClosedSpy(popup, &Window::closed); 0181 popupShellSurface.reset(); 0182 popupSurface.reset(); 0183 QVERIFY(popupClosedSpy.wait()); 0184 QVERIFY(!effect->isActive()); 0185 0186 // Destroy the main window. 0187 mainWindowSurface.reset(); 0188 QVERIFY(Test::waitForWindowClosed(mainWindow)); 0189 } 0190 0191 WAYLANDTEST_MAIN(ToplevelOpenCloseAnimationTest) 0192 #include "toplevel_open_close_animation_test.moc"