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: 2019 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/plasmawindowmanagement.h>
0019 #include <KWayland/Client/surface.h>
0020 
0021 using namespace KWin;
0022 
0023 static const QString s_socketName = QStringLiteral("wayland_test_effects_minimize_animation-0");
0024 
0025 class MinimizeAnimationTest : public QObject
0026 {
0027     Q_OBJECT
0028 
0029 private Q_SLOTS:
0030     void initTestCase();
0031     void init();
0032     void cleanup();
0033 
0034     void testMinimizeUnminimize_data();
0035     void testMinimizeUnminimize();
0036 };
0037 
0038 void MinimizeAnimationTest::initTestCase()
0039 {
0040     if (!Test::renderNodeAvailable()) {
0041         QSKIP("no render node available");
0042         return;
0043     }
0044     qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
0045 
0046     qRegisterMetaType<KWin::Window *>();
0047     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0048     QVERIFY(waylandServer()->init(s_socketName));
0049     Test::setOutputConfig({
0050         QRect(0, 0, 1280, 1024),
0051         QRect(1280, 0, 1280, 1024),
0052     });
0053 
0054     auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
0055     KConfigGroup plugins(config, QStringLiteral("Plugins"));
0056     const auto builtinNames = EffectLoader().listOfKnownEffects();
0057     for (const QString &name : builtinNames) {
0058         plugins.writeEntry(name + QStringLiteral("Enabled"), false);
0059     }
0060     config->sync();
0061     kwinApp()->setConfig(config);
0062 
0063     qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
0064     qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", QByteArrayLiteral("1"));
0065 
0066     kwinApp()->start();
0067     QVERIFY(applicationStartedSpy.wait());
0068 }
0069 
0070 void MinimizeAnimationTest::init()
0071 {
0072     QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::LayerShellV1 | Test::AdditionalWaylandInterface::WindowManagement));
0073 }
0074 
0075 void MinimizeAnimationTest::cleanup()
0076 {
0077     QVERIFY(effects);
0078     effects->unloadAllEffects();
0079     QVERIFY(effects->loadedEffects().isEmpty());
0080 
0081     Test::destroyWaylandConnection();
0082 }
0083 
0084 void MinimizeAnimationTest::testMinimizeUnminimize_data()
0085 {
0086     QTest::addColumn<QString>("effectName");
0087 
0088     QTest::newRow("Magic Lamp") << QStringLiteral("magiclamp");
0089     QTest::newRow("Squash") << QStringLiteral("squash");
0090 }
0091 
0092 void MinimizeAnimationTest::testMinimizeUnminimize()
0093 {
0094     // This test verifies that a minimize effect tries to animate a window
0095     // when it's minimized or unminimized.
0096 
0097 
0098     // Create a panel at the top of the screen.
0099     const QRect panelRect = QRect(0, 0, 1280, 36);
0100     std::unique_ptr<KWayland::Client::Surface> panelSurface{Test::createSurface()};
0101     std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface{Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral("dock"))};
0102     panelShellSurface->set_size(panelRect.width(), panelRect.height());
0103     panelShellSurface->set_exclusive_zone(panelRect.height());
0104     panelShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_top);
0105     panelSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0106 
0107     QSignalSpy panelConfigureRequestedSpy(panelShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
0108     QVERIFY(panelConfigureRequestedSpy.wait());
0109     Window *panel = Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
0110     QVERIFY(panel);
0111     QVERIFY(panel->isDock());
0112     QCOMPARE(panel->frameGeometry(), panelRect);
0113 
0114     // Create the test window.
0115     QSignalSpy plasmaWindowCreatedSpy(Test::waylandWindowManagement(), &KWayland::Client::PlasmaWindowManagement::windowCreated);
0116     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0117     QVERIFY(surface != nullptr);
0118     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
0119     QVERIFY(shellSurface != nullptr);
0120     Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::red);
0121     QVERIFY(window);
0122     QVERIFY(plasmaWindowCreatedSpy.wait());
0123     QCOMPARE(plasmaWindowCreatedSpy.count(), 1);
0124 
0125     // We have to set the minimized geometry because the squash effect needs it,
0126     // otherwise it won't start animation.
0127     auto plasmaWindow = plasmaWindowCreatedSpy.last().first().value<KWayland::Client::PlasmaWindow *>();
0128     QVERIFY(plasmaWindow);
0129     const QRect iconRect = QRect(0, 0, 42, 36);
0130     plasmaWindow->setMinimizedGeometry(panelSurface.get(), iconRect);
0131     Test::flushWaylandConnection();
0132     QTRY_COMPARE(window->iconGeometry(), iconRect.translated(panel->frameGeometry().topLeft().toPoint()));
0133 
0134     // Load effect that will be tested.
0135     QFETCH(QString, effectName);
0136     QVERIFY(effects);
0137     QVERIFY(effects->loadEffect(effectName));
0138     QCOMPARE(effects->loadedEffects().count(), 1);
0139     QCOMPARE(effects->loadedEffects().first(), effectName);
0140     Effect *effect = effects->findEffect(effectName);
0141     QVERIFY(effect);
0142     QVERIFY(!effect->isActive());
0143 
0144     // Start the minimize animation.
0145     window->setMinimized(true);
0146     QVERIFY(effect->isActive());
0147 
0148     // Eventually, the animation will be complete.
0149     QTRY_VERIFY(!effect->isActive());
0150 
0151     // Start the unminimize animation.
0152     window->setMinimized(false);
0153     QVERIFY(effect->isActive());
0154 
0155     // Eventually, the animation will be complete.
0156     QTRY_VERIFY(!effect->isActive());
0157 
0158     // Destroy the panel.
0159     panelSurface.reset();
0160     QVERIFY(Test::waitForWindowClosed(panel));
0161 
0162     // Destroy the test window.
0163     surface.reset();
0164     QVERIFY(Test::waitForWindowClosed(window));
0165 }
0166 
0167 WAYLANDTEST_MAIN(MinimizeAnimationTest)
0168 #include "minimize_animation_test.moc"