KWin
Loading...
Searching...
No Matches
screenedge_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: 2016 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "effect/effectloader.h"
12#include "pointer_input.h"
13#include "scripting/scripting.h"
14#include "wayland_server.h"
15#include "workspace.h"
16
17#define private public
18#include "screenedge.h"
19#undef private
20
21#include <KConfigGroup>
22
24
25using namespace KWin;
26
27static const QString s_socketName = QStringLiteral("wayland_test_kwin_scripting_screenedge-0");
28
29class ScreenEdgeTest : public QObject
30{
31 Q_OBJECT
32private Q_SLOTS:
33 void initTestCase();
34 void init();
35 void cleanup();
36
37 void testEdge_data();
38 void testEdge();
39 void testTouchEdge_data();
40 void testTouchEdge();
41 void testEdgeUnregister();
42 void testDeclarativeTouchEdge();
43
44private:
45 void triggerConfigReload();
46};
47
48void ScreenEdgeTest::initTestCase()
49{
50 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
51 QVERIFY(waylandServer()->init(s_socketName));
52 Test::setOutputConfig({QRect(0, 0, 1280, 1024)});
53
54 // empty config to have defaults
55 auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
56
57 // disable all effects to prevent them grabbing edges
58 KConfigGroup plugins(config, QStringLiteral("Plugins"));
59 const auto builtinNames = EffectLoader().listOfKnownEffects();
60 for (QString name : builtinNames) {
61 plugins.writeEntry(name + QStringLiteral("Enabled"), false);
62 }
63
64 // disable electric border pushback
65 config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderPushbackPixels", 0);
66 config->group(QStringLiteral("TabBox")).writeEntry("TouchBorderActivate", int(ElectricNone));
67
68 config->sync();
69 kwinApp()->setConfig(config);
70
71 kwinApp()->start();
72 QVERIFY(applicationStartedSpy.wait());
73 QVERIFY(Scripting::self());
74
75 workspace()->screenEdges()->setTimeThreshold(0);
76 workspace()->screenEdges()->setReActivationThreshold(0);
77}
78
79void ScreenEdgeTest::init()
80{
81 KWin::input()->pointer()->warp(QPointF(640, 512));
82 if (workspace()->showingDesktop()) {
84 }
85 QVERIFY(!workspace()->showingDesktop());
86}
87
88void ScreenEdgeTest::cleanup()
89{
90 // try to unload the script
91 const QStringList scripts = {QFINDTESTDATA("./scripts/screenedge.js"), QFINDTESTDATA("./scripts/screenedgeunregister.js"), QFINDTESTDATA("./scripts/touchScreenedge.js")};
92 for (const QString &script : scripts) {
93 if (!script.isEmpty()) {
94 if (Scripting::self()->isScriptLoaded(script)) {
95 QVERIFY(Scripting::self()->unloadScript(script));
96 QTRY_VERIFY(!Scripting::self()->isScriptLoaded(script));
97 }
98 }
99 }
100}
101
102void ScreenEdgeTest::testEdge_data()
103{
104 QTest::addColumn<KWin::ElectricBorder>("edge");
105 QTest::addColumn<QPoint>("triggerPos");
106
107 QTest::newRow("Top") << KWin::ElectricTop << QPoint(512, 0);
108 QTest::newRow("TopRight") << KWin::ElectricTopRight << QPoint(1279, 0);
109 QTest::newRow("Right") << KWin::ElectricRight << QPoint(1279, 512);
110 QTest::newRow("BottomRight") << KWin::ElectricBottomRight << QPoint(1279, 1023);
111 QTest::newRow("Bottom") << KWin::ElectricBottom << QPoint(512, 1023);
112 QTest::newRow("BottomLeft") << KWin::ElectricBottomLeft << QPoint(0, 1023);
113 QTest::newRow("Left") << KWin::ElectricLeft << QPoint(0, 512);
114 QTest::newRow("TopLeft") << KWin::ElectricTopLeft << QPoint(0, 0);
115
116 // repeat a row to show previously unloading and re-registering works
117 QTest::newRow("Top") << KWin::ElectricTop << QPoint(512, 0);
118}
119
120void ScreenEdgeTest::testEdge()
121{
122 const QString scriptToLoad = QFINDTESTDATA("./scripts/screenedge.js");
123 QVERIFY(!scriptToLoad.isEmpty());
124
125 // mock the config
126 auto config = kwinApp()->config();
127 QFETCH(KWin::ElectricBorder, edge);
128 config->group(QLatin1String("Script-") + scriptToLoad).writeEntry("Edge", int(edge));
129 config->sync();
130
131 QVERIFY(!Scripting::self()->isScriptLoaded(scriptToLoad));
132 const int id = Scripting::self()->loadScript(scriptToLoad);
133 QVERIFY(id != -1);
134 QVERIFY(Scripting::self()->isScriptLoaded(scriptToLoad));
135 auto s = Scripting::self()->findScript(scriptToLoad);
136 QVERIFY(s);
137 QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
138 s->run();
139 QVERIFY(runningChangedSpy.wait());
140 QCOMPARE(runningChangedSpy.count(), 1);
141 QCOMPARE(runningChangedSpy.first().first().toBool(), true);
142 // triggering the edge will result in show desktop being triggered
143 QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged);
144
145 // trigger the edge
146 QFETCH(QPoint, triggerPos);
147 KWin::input()->pointer()->warp(triggerPos);
148 QCOMPARE(showDesktopSpy.count(), 1);
149 QVERIFY(workspace()->showingDesktop());
150}
151
152void ScreenEdgeTest::testTouchEdge_data()
153{
154 QTest::addColumn<KWin::ElectricBorder>("edge");
155 QTest::addColumn<QPoint>("triggerPos");
156 QTest::addColumn<QPoint>("motionPos");
157
158 QTest::newRow("Top") << KWin::ElectricTop << QPoint(50, 0) << QPoint(50, 500);
159 QTest::newRow("Right") << KWin::ElectricRight << QPoint(1279, 50) << QPoint(500, 50);
160 QTest::newRow("Bottom") << KWin::ElectricBottom << QPoint(512, 1023) << QPoint(512, 500);
161 QTest::newRow("Left") << KWin::ElectricLeft << QPoint(0, 50) << QPoint(500, 50);
162
163 // repeat a row to show previously unloading and re-registering works
164 QTest::newRow("Top") << KWin::ElectricTop << QPoint(512, 0) << QPoint(512, 500);
165}
166
167void ScreenEdgeTest::testTouchEdge()
168{
169 const QString scriptToLoad = QFINDTESTDATA("./scripts/touchScreenedge.js");
170 QVERIFY(!scriptToLoad.isEmpty());
171
172 // mock the config
173 auto config = kwinApp()->config();
174 QFETCH(KWin::ElectricBorder, edge);
175 config->group(QLatin1String("Script-") + scriptToLoad).writeEntry("Edge", int(edge));
176 config->sync();
177
178 QVERIFY(!Scripting::self()->isScriptLoaded(scriptToLoad));
179 const int id = Scripting::self()->loadScript(scriptToLoad);
180 QVERIFY(id != -1);
181 QVERIFY(Scripting::self()->isScriptLoaded(scriptToLoad));
182 auto s = Scripting::self()->findScript(scriptToLoad);
183 QVERIFY(s);
184 QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
185 s->run();
186 QVERIFY(runningChangedSpy.wait());
187 QCOMPARE(runningChangedSpy.count(), 1);
188 QCOMPARE(runningChangedSpy.first().first().toBool(), true);
189 // triggering the edge will result in show desktop being triggered
190 QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged);
191
192 // trigger the edge
193 QFETCH(QPoint, triggerPos);
194 quint32 timestamp = 0;
195 Test::touchDown(0, triggerPos, timestamp++);
196 QFETCH(QPoint, motionPos);
197 Test::touchMotion(0, motionPos, timestamp++);
198 Test::touchUp(0, timestamp++);
199 QVERIFY(showDesktopSpy.wait());
200 QCOMPARE(showDesktopSpy.count(), 1);
201 QVERIFY(workspace()->showingDesktop());
202}
203
204void ScreenEdgeTest::triggerConfigReload()
205{
207}
208
209void ScreenEdgeTest::testEdgeUnregister()
210{
211 const QString scriptToLoad = QFINDTESTDATA("./scripts/screenedgeunregister.js");
212 QVERIFY(!scriptToLoad.isEmpty());
213
214 Scripting::self()->loadScript(scriptToLoad);
215 auto s = Scripting::self()->findScript(scriptToLoad);
216 auto configGroup = s->config();
217 configGroup.writeEntry("Edge", int(KWin::ElectricLeft));
218 configGroup.sync();
219 const QPoint triggerPos = QPoint(0, 512);
220
221 QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
222 s->run();
223 QVERIFY(runningChangedSpy.wait());
224
225 QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged);
226
227 // trigger the edge
228 KWin::input()->pointer()->warp(triggerPos);
229 QCOMPARE(showDesktopSpy.count(), 1);
230
231 // reset
232 KWin::input()->pointer()->warp(QPointF(500, 500));
234 showDesktopSpy.clear();
235
236 // trigger again, to show that retriggering works
237 KWin::input()->pointer()->warp(triggerPos);
238 QCOMPARE(showDesktopSpy.count(), 1);
239
240 // reset
241 KWin::input()->pointer()->warp(QPointF(500, 500));
243 showDesktopSpy.clear();
244
245 // make the script unregister the edge
246 configGroup.writeEntry("mode", "unregister");
247 triggerConfigReload();
248 KWin::input()->pointer()->warp(triggerPos);
249 QCOMPARE(showDesktopSpy.count(), 0); // not triggered
250
251 // force the script to unregister a non-registered edge to prove it doesn't explode
252 triggerConfigReload();
253}
254
255void ScreenEdgeTest::testDeclarativeTouchEdge()
256{
257 const QString scriptToLoad = QFINDTESTDATA("./scripts/screenedgetouch.qml");
258 QVERIFY(!scriptToLoad.isEmpty());
259 QVERIFY(Scripting::self()->loadDeclarativeScript(scriptToLoad) != -1);
260 QVERIFY(Scripting::self()->isScriptLoaded(scriptToLoad));
261
262 auto s = Scripting::self()->findScript(scriptToLoad);
263 QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
264 s->run();
265 QTRY_COMPARE(runningChangedSpy.count(), 1);
266
267 QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged);
268
269 // Trigger the edge through touch
270 quint32 timestamp = 0;
271 Test::touchDown(0, QPointF(0, 50), timestamp++);
272 Test::touchMotion(0, QPointF(500, 50), timestamp++);
273 Test::touchUp(0, timestamp++);
274
275 QVERIFY(showDesktopSpy.wait());
276}
277
279#include "screenedge_test.moc"
void runningChanged(bool)
KConfigGroup config() const
QStringList listOfKnownEffects() const override
All the Effects this loader knows of.
PointerInputRedirection * pointer() const
Definition input.h:220
void warp(const QPointF &pos)
AbstractScript * findScript(const QString &pluginName) const
Q_SCRIPTABLE Q_INVOKABLE int loadScript(const QString &filePath, const QString &pluginName=QString())
static Scripting * self()
Definition scripting.h:393
void slotToggleShowDesktop()
ScreenEdges * screenEdges() const
void showingDesktopChanged(bool showing, bool animated)
void slotReconfigure()
Q_DECLARE_METATYPE(KWin::SwitchEvent::State)
#define WAYLANDTEST_MAIN(TestObject)
void setOutputConfig(const QList< QRect > &geometries)
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
void touchUp(qint32 id, quint32 time)
ElectricBorder
Definition globals.h:60
@ ElectricNone
Definition globals.h:70
@ ElectricTopLeft
Definition globals.h:68
@ ElectricBottomLeft
Definition globals.h:66
@ ElectricBottom
Definition globals.h:65
@ ElectricTopRight
Definition globals.h:62
@ ElectricTop
Definition globals.h:61
@ ElectricRight
Definition globals.h:63
@ ElectricBottomRight
Definition globals.h:64
@ ElectricLeft
Definition globals.h:67
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549