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"