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 "compositor.h"
0013 #include "effect/effecthandler.h"
0014 #include "effect/effectloader.h"
0015 #include "scene/workspacescene.h"
0016 #include "wayland_server.h"
0017 #include "window.h"
0018 #include "workspace.h"
0019 
0020 #include <KWayland/Client/surface.h>
0021 
0022 using namespace KWin;
0023 
0024 static const QString s_socketName = QStringLiteral("wayland_test_effects_maximize_animation-0");
0025 
0026 class MaximizeAnimationTest : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 private Q_SLOTS:
0031     void initTestCase();
0032     void init();
0033     void cleanup();
0034 
0035     void testMaximizeRestore();
0036 };
0037 
0038 void MaximizeAnimationTest::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 MaximizeAnimationTest::init()
0071 {
0072     QVERIFY(Test::setupWaylandConnection());
0073 }
0074 
0075 void MaximizeAnimationTest::cleanup()
0076 {
0077     QVERIFY(effects);
0078     effects->unloadAllEffects();
0079     QVERIFY(effects->loadedEffects().isEmpty());
0080 
0081     Test::destroyWaylandConnection();
0082 }
0083 
0084 void MaximizeAnimationTest::testMaximizeRestore()
0085 {
0086     // This test verifies that the maximize effect animates a window
0087     // when it's maximized or restored.
0088 
0089     // Create the test window.
0090     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0091     QVERIFY(surface != nullptr);
0092 
0093     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly));
0094 
0095     // Wait for the initial configure event.
0096     Test::XdgToplevel::States states;
0097     QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
0098     QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
0099 
0100     surface->commit(KWayland::Client::Surface::CommitFlag::None);
0101 
0102     QVERIFY(surfaceConfigureRequestedSpy.wait());
0103     QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
0104     QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(0, 0));
0105     states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
0106     QVERIFY(!states.testFlag(Test::XdgToplevel::State::Activated));
0107     QVERIFY(!states.testFlag(Test::XdgToplevel::State::Maximized));
0108 
0109     // Draw contents of the surface.
0110     shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
0111     Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
0112     QVERIFY(window);
0113     QVERIFY(window->isActive());
0114     QCOMPARE(window->maximizeMode(), MaximizeMode::MaximizeRestore);
0115 
0116     // We should receive a configure event when the window becomes active.
0117     QVERIFY(surfaceConfigureRequestedSpy.wait());
0118     QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
0119     states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
0120     QVERIFY(states.testFlag(Test::XdgToplevel::State::Activated));
0121     QVERIFY(!states.testFlag(Test::XdgToplevel::State::Maximized));
0122 
0123     // Load effect that will be tested.
0124     const QString effectName = QStringLiteral("maximize");
0125     QVERIFY(effects);
0126     QVERIFY(effects->loadEffect(effectName));
0127     QCOMPARE(effects->loadedEffects().count(), 1);
0128     QCOMPARE(effects->loadedEffects().first(), effectName);
0129     Effect *effect = effects->findEffect(effectName);
0130     QVERIFY(effect);
0131     QVERIFY(!effect->isActive());
0132 
0133     // Maximize the window.
0134     QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
0135     QSignalSpy maximizeChangedSpy(window, &Window::maximizedChanged);
0136 
0137     workspace()->slotWindowMaximize();
0138     QVERIFY(surfaceConfigureRequestedSpy.wait());
0139     QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
0140     QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280, 1024));
0141     states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
0142     QVERIFY(states.testFlag(Test::XdgToplevel::State::Activated));
0143     QVERIFY(states.testFlag(Test::XdgToplevel::State::Maximized));
0144 
0145     // Draw contents of the maximized window.
0146     shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
0147     Test::render(surface.get(), QSize(1280, 1024), Qt::red);
0148     QVERIFY(frameGeometryChangedSpy.wait());
0149     QCOMPARE(frameGeometryChangedSpy.count(), 1);
0150     QCOMPARE(maximizeChangedSpy.count(), 1);
0151     QCOMPARE(window->maximizeMode(), MaximizeMode::MaximizeFull);
0152     QVERIFY(effect->isActive());
0153 
0154     // Eventually, the animation will be complete.
0155     QTRY_VERIFY(!effect->isActive());
0156 
0157     // Restore the window.
0158     workspace()->slotWindowMaximize();
0159     QVERIFY(surfaceConfigureRequestedSpy.wait());
0160     QCOMPARE(surfaceConfigureRequestedSpy.count(), 4);
0161     QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(100, 50));
0162     states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
0163     QVERIFY(states.testFlag(Test::XdgToplevel::State::Activated));
0164     QVERIFY(!states.testFlag(Test::XdgToplevel::State::Maximized));
0165 
0166     // Draw contents of the restored window.
0167     shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
0168     Test::render(surface.get(), QSize(100, 50), Qt::blue);
0169     QVERIFY(frameGeometryChangedSpy.wait());
0170     QCOMPARE(frameGeometryChangedSpy.count(), 2);
0171     QCOMPARE(maximizeChangedSpy.count(), 2);
0172     QCOMPARE(window->maximizeMode(), MaximizeMode::MaximizeRestore);
0173     QVERIFY(effect->isActive());
0174 
0175     // Eventually, the animation will be complete.
0176     QTRY_VERIFY(!effect->isActive());
0177 
0178     // Destroy the test window.
0179     surface.reset();
0180     QVERIFY(Test::waitForWindowClosed(window));
0181 }
0182 
0183 WAYLANDTEST_MAIN(MaximizeAnimationTest)
0184 #include "maximize_animation_test.moc"