KWin
Loading...
Searching...
No Matches
popup_open_close_animation_test.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "kwin_wayland_test.h"
11
13#include "effect/effectloader.h"
14#include "internalwindow.h"
15#include "useractions.h"
16#include "wayland_server.h"
17#include "window.h"
18#include "workspace.h"
19
21
22#include <KWayland/Client/surface.h>
23
24#include <linux/input.h>
25
26using namespace KWin;
27
28static const QString s_socketName = QStringLiteral("wayland_test_effects_popup_open_close_animation-0");
29
30class PopupOpenCloseAnimationTest : public QObject
31{
32 Q_OBJECT
33
34private Q_SLOTS:
35 void initTestCase();
36 void init();
37 void cleanup();
38
39 void testAnimatePopups();
40 void testAnimateUserActionsPopup();
41 void testAnimateDecorationTooltips();
42};
43
44void PopupOpenCloseAnimationTest::initTestCase()
45{
46 qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
47
48 qRegisterMetaType<KWin::Window *>();
49 qRegisterMetaType<KWin::InternalWindow *>();
50 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
51 QVERIFY(waylandServer()->init(s_socketName));
53 QRect(0, 0, 1280, 1024),
54 QRect(1280, 0, 1280, 1024),
55 });
56
57 auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
58 KConfigGroup plugins(config, QStringLiteral("Plugins"));
59 const auto builtinNames = EffectLoader().listOfKnownEffects();
60 for (const QString &name : builtinNames) {
61 plugins.writeEntry(name + QStringLiteral("Enabled"), false);
62 }
63 config->sync();
64 kwinApp()->setConfig(config);
65
66 qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", QByteArrayLiteral("1"));
67
68 kwinApp()->start();
69 QVERIFY(applicationStartedSpy.wait());
70}
71
72void PopupOpenCloseAnimationTest::init()
73{
74 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::XdgDecorationV1));
75}
76
77void PopupOpenCloseAnimationTest::cleanup()
78{
79 QVERIFY(effects);
81 QVERIFY(effects->loadedEffects().isEmpty());
82
84}
85
86void PopupOpenCloseAnimationTest::testAnimatePopups()
87{
88 // This test verifies that popup open/close animation effects try
89 // to animate popups(e.g. popup menus, tooltips, etc).
90
91 // Create the main window.
92 std::unique_ptr<KWayland::Client::Surface> mainWindowSurface(Test::createSurface());
93 QVERIFY(mainWindowSurface != nullptr);
94 std::unique_ptr<Test::XdgToplevel> mainWindowShellSurface(Test::createXdgToplevelSurface(mainWindowSurface.get()));
95 QVERIFY(mainWindowShellSurface != nullptr);
96 Window *mainWindow = Test::renderAndWaitForShown(mainWindowSurface.get(), QSize(100, 50), Qt::blue);
97 QVERIFY(mainWindow);
98
99 // Load effect that will be tested.
100 const QString effectName = QStringLiteral("fadingpopups");
101 QVERIFY(effects->loadEffect(effectName));
102 QCOMPARE(effects->loadedEffects().count(), 1);
103 QCOMPARE(effects->loadedEffects().first(), effectName);
104 Effect *effect = effects->findEffect(effectName);
105 QVERIFY(effect);
106 QVERIFY(!effect->isActive());
107
108 // Create a popup, it should be animated.
109 std::unique_ptr<KWayland::Client::Surface> popupSurface(Test::createSurface());
110 QVERIFY(popupSurface != nullptr);
111 std::unique_ptr<Test::XdgPositioner> positioner(Test::createXdgPositioner());
112 positioner->set_size(20, 20);
113 positioner->set_anchor_rect(0, 0, 10, 10);
114 positioner->set_gravity(Test::XdgPositioner::gravity_bottom_right);
115 positioner->set_anchor(Test::XdgPositioner::anchor_bottom_left);
116 std::unique_ptr<Test::XdgPopup> popupShellSurface(Test::createXdgPopupSurface(popupSurface.get(), mainWindowShellSurface->xdgSurface(), positioner.get()));
117 QVERIFY(popupShellSurface != nullptr);
118 Window *popup = Test::renderAndWaitForShown(popupSurface.get(), QSize(20, 20), Qt::red);
119 QVERIFY(popup);
120 QVERIFY(popup->isPopupWindow());
121 QCOMPARE(popup->transientFor(), mainWindow);
122 QVERIFY(effect->isActive());
123
124 // Eventually, the animation will be complete.
125 QTRY_VERIFY(!effect->isActive());
126
127 // Destroy the popup, it should not be animated.
128 QSignalSpy popupClosedSpy(popup, &Window::closed);
129 popupShellSurface.reset();
130 popupSurface.reset();
131 QVERIFY(popupClosedSpy.wait());
132 QVERIFY(effect->isActive());
133
134 // Eventually, the animation will be complete.
135 QTRY_VERIFY(!effect->isActive());
136
137 // Destroy the main window.
138 mainWindowSurface.reset();
139 QVERIFY(Test::waitForWindowClosed(mainWindow));
140}
141
142void PopupOpenCloseAnimationTest::testAnimateUserActionsPopup()
143{
144 // This test verifies that popup open/close animation effects try
145 // to animate the user actions popup.
146
147 // Create the test window.
148 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
149 QVERIFY(surface != nullptr);
150 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
151 QVERIFY(shellSurface != nullptr);
152 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
153 QVERIFY(window);
154
155 // Load effect that will be tested.
156 const QString effectName = QStringLiteral("fadingpopups");
157 QVERIFY(effects->loadEffect(effectName));
158 QCOMPARE(effects->loadedEffects().count(), 1);
159 QCOMPARE(effects->loadedEffects().first(), effectName);
160 Effect *effect = effects->findEffect(effectName);
161 QVERIFY(effect);
162 QVERIFY(!effect->isActive());
163
164 // Show the user actions popup.
165 workspace()->showWindowMenu(QRect(), window);
166 auto userActionsMenu = workspace()->userActionsMenu();
167 QTRY_VERIFY(userActionsMenu->isShown());
168 QVERIFY(userActionsMenu->hasWindow());
169 QVERIFY(effect->isActive());
170
171 // Eventually, the animation will be complete.
172 QTRY_VERIFY(!effect->isActive());
173
174 // Close the user actions popup.
175 Test::keyboardKeyPressed(KEY_ESC, 0);
176 Test::keyboardKeyReleased(KEY_ESC, 1);
177 QTRY_VERIFY(!userActionsMenu->isShown());
178 QVERIFY(!userActionsMenu->hasWindow());
179 QVERIFY(effect->isActive());
180
181 // Eventually, the animation will be complete.
182 QTRY_VERIFY(!effect->isActive());
183
184 // Destroy the test window.
185 surface.reset();
186 QVERIFY(Test::waitForWindowClosed(window));
187}
188
189void PopupOpenCloseAnimationTest::testAnimateDecorationTooltips()
190{
191 // This test verifies that popup open/close animation effects try
192 // to animate decoration tooltips.
193
194 // Create the test window.
195 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
196 QVERIFY(surface != nullptr);
197 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly));
198 QVERIFY(shellSurface != nullptr);
199 std::unique_ptr<Test::XdgToplevelDecorationV1> deco(Test::createXdgToplevelDecorationV1(shellSurface.get()));
200 QVERIFY(deco != nullptr);
201
202 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
203 deco->set_mode(Test::XdgToplevelDecorationV1::mode_server_side);
204 surface->commit(KWayland::Client::Surface::CommitFlag::None);
205 QVERIFY(surfaceConfigureRequestedSpy.wait());
206
207 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
208 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
209 QVERIFY(window);
210 QVERIFY(window->isDecorated());
211
212 // Load effect that will be tested.
213 const QString effectName = QStringLiteral("fadingpopups");
214 QVERIFY(effects->loadEffect(effectName));
215 QCOMPARE(effects->loadedEffects().count(), 1);
216 QCOMPARE(effects->loadedEffects().first(), effectName);
217 Effect *effect = effects->findEffect(effectName);
218 QVERIFY(effect);
219 QVERIFY(!effect->isActive());
220
221 // Show a decoration tooltip.
222 QSignalSpy tooltipAddedSpy(workspace(), &Workspace::windowAdded);
223 window->decoratedClient()->requestShowToolTip(QStringLiteral("KWin rocks!"));
224 QVERIFY(tooltipAddedSpy.wait());
225 InternalWindow *tooltip = tooltipAddedSpy.first().first().value<InternalWindow *>();
226 QVERIFY(tooltip->isInternal());
227 QVERIFY(tooltip->isPopupWindow());
228 QVERIFY(tooltip->handle()->flags().testFlag(Qt::ToolTip));
229 QVERIFY(effect->isActive());
230
231 // Eventually, the animation will be complete.
232 QTRY_VERIFY(!effect->isActive());
233
234 // Hide the decoration tooltip.
235 QSignalSpy tooltipClosedSpy(tooltip, &InternalWindow::closed);
236 window->decoratedClient()->requestHideToolTip();
237 QVERIFY(tooltipClosedSpy.wait());
238 QVERIFY(effect->isActive());
239
240 // Eventually, the animation will be complete.
241 QTRY_VERIFY(!effect->isActive());
242
243 // Destroy the test window.
244 surface.reset();
245 QVERIFY(Test::waitForWindowClosed(window));
246}
247
249#include "popup_open_close_animation_test.moc"
Base class for all KWin effects.
Definition effect.h:535
QStringList listOfKnownEffects() const override
All the Effects this loader knows of.
QStringList loadedEffects
Q_SCRIPTABLE bool loadEffect(const QString &name)
Effect * findEffect(const QString &name) const
QWindow * handle() const
bool isInternal() const override
bool isPopupWindow() const override
void configureRequested(quint32 serial)
void showWindowMenu(const QRect &pos, Window *cl)
void windowAdded(KWin::Window *)
UserActionsMenu * userActionsMenu() const
Definition workspace.h:310
virtual bool isActive() const
Definition effect.cpp:447
#define WAYLANDTEST_MAIN(TestObject)
XdgPositioner * createXdgPositioner()
Window * renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32, int timeout=5000)
void keyboardKeyReleased(quint32 key, quint32 time)
XdgPopup * createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, CreationSetup configureMode=CreationSetup::CreateAndConfigure, QObject *parent=nullptr)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
void keyboardKeyPressed(quint32 key, quint32 time)
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
XdgToplevelDecorationV1 * createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent=nullptr)
bool waitForWindowClosed(Window *window)
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
EffectsHandler * effects