diff --git a/autotests/integration/scripting/screenedge_test.cpp b/autotests/integration/scripting/screenedge_test.cpp
index e828619320..7ca92b56ea 100644
--- a/autotests/integration/scripting/screenedge_test.cpp
+++ b/autotests/integration/scripting/screenedge_test.cpp
@@ -25,6 +25,11 @@ along with this program. If not, see .
#include "workspace.h"
#include "scripting/scripting.h"
#include "effect_builtins.h"
+#include "workspace.h"
+
+#define private public
+#include "screenedge.h"
+#undef private
#include
@@ -44,6 +49,10 @@ private Q_SLOTS:
void testEdge_data();
void testEdge();
+ void testEdgeUnregister();
+
+private:
+ void triggerConfigReload();
};
void ScreenEdgeTest::initTestCase()
@@ -64,7 +73,7 @@ void ScreenEdgeTest::initTestCase()
plugins.writeEntry(name + QStringLiteral("Enabled"), false);
}
- // disable electric border pushaback
+ // disable electric border pushback
config->group("Windows").writeEntry("ElectricBorderPushbackPixels", 0);
config->sync();
@@ -73,6 +82,9 @@ void ScreenEdgeTest::initTestCase()
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
QVERIFY(Scripting::self());
+
+ ScreenEdges::self()->setTimeThreshold(0);
+ ScreenEdges::self()->setReActivationThreshold(0);
}
void ScreenEdgeTest::init()
@@ -87,11 +99,13 @@ void ScreenEdgeTest::init()
void ScreenEdgeTest::cleanup()
{
// try to unload the script
- const QString scriptToLoad = QFINDTESTDATA("./scripts/screenedge.js");
- if (!scriptToLoad.isEmpty()) {
- if (Scripting::self()->isScriptLoaded(scriptToLoad)) {
- QVERIFY(Scripting::self()->unloadScript(scriptToLoad));
- QTRY_VERIFY(!Scripting::self()->isScriptLoaded(scriptToLoad));
+ const QStringList scripts = {QFINDTESTDATA("./scripts/screenedge.js"), QFINDTESTDATA("./scripts/screenedgeunregister.js")};
+ for (const QString &script: scripts) {
+ if (!script.isEmpty()) {
+ if (Scripting::self()->isScriptLoaded(script)) {
+ QVERIFY(Scripting::self()->unloadScript(script));
+ QTRY_VERIFY(!Scripting::self()->isScriptLoaded(script));
+ }
}
}
}
@@ -109,6 +123,9 @@ void ScreenEdgeTest::testEdge_data()
QTest::newRow("BottomLeft") << KWin::ElectricBottomLeft << QPoint(0, 1023);
QTest::newRow("Left") << KWin::ElectricLeft << QPoint(0, 512);
QTest::newRow("TopLeft") << KWin::ElectricTopLeft << QPoint(0, 0);
+
+ //repeat a row to show previously unloading and re-registering works
+ QTest::newRow("Top") << KWin::ElectricTop << QPoint(512, 0);
}
void ScreenEdgeTest::testEdge()
@@ -145,5 +162,56 @@ void ScreenEdgeTest::testEdge()
QVERIFY(workspace()->showingDesktop());
}
+void ScreenEdgeTest::triggerConfigReload() {
+ workspace()->slotReconfigure();
+}
+
+void ScreenEdgeTest::testEdgeUnregister()
+{
+ const QString scriptToLoad = QFINDTESTDATA("./scripts/screenedgeunregister.js");
+ QVERIFY(!scriptToLoad.isEmpty());
+
+ Scripting::self()->loadScript(scriptToLoad);
+ auto s = Scripting::self()->findScript(scriptToLoad);
+ auto configGroup = s->config();
+ configGroup.writeEntry("Edge", int(KWin::ElectricLeft));
+ configGroup.sync();
+ const QPoint triggerPos = QPoint(0, 512);
+
+ QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
+ s->run();
+ QVERIFY(runningChangedSpy.wait());
+
+ QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged);
+ QVERIFY(showDesktopSpy.isValid());
+
+ //trigger the edge
+ KWin::Cursor::setPos(triggerPos);
+ QCOMPARE(showDesktopSpy.count(), 1);
+
+ //reset
+ KWin::Cursor::setPos(500,500);
+ workspace()->slotToggleShowDesktop();
+ showDesktopSpy.clear();
+
+ //trigger again, to show that retriggering works
+ KWin::Cursor::setPos(triggerPos);
+ QCOMPARE(showDesktopSpy.count(), 1);
+
+ //reset
+ KWin::Cursor::setPos(500,500);
+ workspace()->slotToggleShowDesktop();
+ showDesktopSpy.clear();
+
+ //make the script unregister the edge
+ configGroup.writeEntry("mode", "unregister");
+ triggerConfigReload();
+ KWin::Cursor::setPos(triggerPos);
+ QCOMPARE(showDesktopSpy.count(), 0); //not triggered
+
+ //force the script to unregister a non-registered edge to prove it doesn't explode
+ triggerConfigReload();
+}
+
WAYLANDTEST_MAIN(ScreenEdgeTest)
#include "screenedge_test.moc"
diff --git a/autotests/integration/scripting/scripts/screenedgeunregister.js b/autotests/integration/scripting/scripts/screenedgeunregister.js
new file mode 100644
index 0000000000..a73b68e7f5
--- /dev/null
+++ b/autotests/integration/scripting/scripts/screenedgeunregister.js
@@ -0,0 +1,12 @@
+function init() {
+ var edge = readConfig("Edge", 1);
+ if (readConfig("mode", "") == "unregister") {
+ unregisterScreenEdge(edge);
+ } else {
+ registerScreenEdge(edge, function() { workspace.slotToggleShowDesktop(); });
+ }
+}
+options.configChanged.connect(init);
+
+init();
+
diff --git a/scripting/documentation-global.xml b/scripting/documentation-global.xml
index 6ab70cd341..af4d9a0d5a 100644
--- a/scripting/documentation-global.xml
+++ b/scripting/documentation-global.xml
@@ -57,6 +57,14 @@
Registers the callback for the screen edge. When the mouse gets pushed against the given edge the callback will be invoked.
+
+ Q_SCRIPTABLE bool
+ bool KWin::Scripting::unregisterScreenEdge
+ (ElectricBorder border)
+ unregisterScreenEdge
+
+ Unregisters the callback for the screen edge. This will disconnect all callbacks from this script to that edge.
+
Q_SCRIPTABLE bool
bool KWin::Scripting::registerShortcut
diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp
index 7ce6d59fd7..b63bee6cb5 100644
--- a/scripting/scripting.cpp
+++ b/scripting/scripting.cpp
@@ -154,6 +154,12 @@ QScriptValue kwinRegisterScreenEdge(QScriptContext *context, QScriptEngine *engi
return KWin::registerScreenEdge(context, engine);
}
+QScriptValue kwinUnregisterScreenEdge(QScriptContext *context, QScriptEngine *engine)
+{
+ return KWin::unregisterScreenEdge(context, engine);
+}
+
+
QScriptValue kwinRegisterUserActionsMenu(QScriptContext *context, QScriptEngine *engine)
{
return KWin::registerUserActionsMenu(context, engine);
@@ -277,6 +283,8 @@ void KWin::Script::installScriptFunctions(QScriptEngine* engine)
registerGlobalShortcutFunction(this, engine, kwinScriptGlobalShortcut);
// add screen edge
registerScreenEdgeFunction(this, engine, kwinRegisterScreenEdge);
+ unregisterScreenEdgeFunction(this, engine, kwinUnregisterScreenEdge);
+
// add user actions menu register function
regesterUserActionsMenuFunction(this, engine, kwinRegisterUserActionsMenu);
// add assertions
diff --git a/scripting/scriptingutils.h b/scripting/scriptingutils.h
index d1e74cd4af..2dc25d9837 100644
--- a/scripting/scriptingutils.h
+++ b/scripting/scriptingutils.h
@@ -170,6 +170,31 @@ QScriptValue registerScreenEdge(QScriptContext *context, QScriptEngine *engine)
return engine->newVariant(true);
}
+template
+QScriptValue unregisterScreenEdge(QScriptContext *context, QScriptEngine *engine)
+{
+ T script = qobject_cast(context->callee().data().toQObject());
+ if (!script) {
+ return engine->undefinedValue();
+ }
+ if (!validateParameters(context, 1, 1)) {
+ return engine->undefinedValue();
+ }
+ if (!validateArgumentType(context)) {
+ return engine->undefinedValue();
+ }
+
+ const int edge = context->argument(0).toVariant().toInt();
+ QHash >::iterator it = script->screenEdgeCallbacks().find(edge);
+ if (it == script->screenEdgeCallbacks().end()) {
+ //not previously registered
+ return engine->newVariant(false);
+ }
+ ScreenEdges::self()->unreserve(static_cast(edge), script);
+ script->screenEdgeCallbacks().erase(it);
+ return engine->newVariant(true);
+}
+
template
QScriptValue registerUserActionsMenu(QScriptContext *context, QScriptEngine *engine)
{
@@ -271,6 +296,13 @@ inline void registerScreenEdgeFunction(QObject *parent, QScriptEngine *engine, Q
engine->globalObject().setProperty(QStringLiteral("registerScreenEdge"), shortcutFunc);
}
+inline void unregisterScreenEdgeFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
+{
+ QScriptValue shortcutFunc = engine->newFunction(function);
+ shortcutFunc.setData(engine->newQObject(parent));
+ engine->globalObject().setProperty(QStringLiteral("unregisterScreenEdge"), shortcutFunc);
+}
+
inline void regesterUserActionsMenuFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
{
QScriptValue shortcutFunc = engine->newFunction(function);