[scripting] Make DBus invokable run method return result after execution

Summary:
In 403038 the user expected the DBus call to run to finish before
processing the next request. For a singleshot script that makes a lot of
sense, otherwise you have no idea when it finishes.

This also allows us to return errors.

CCBUG: 403038

Test Plan:
NUM=$(qdbus org.kde.KWin /Scripting org.kde.kwin.Scripting.loadScript /noFile.js Minimize)
qdbus org.kde.KWin /$NUM org.kde.kwin.Scripting.run
  Error: org.kde.kwin.Scripting.FileError
  Could not open /noFile.js

Running a real script behaved effectively the same as before.

Reviewers: #kwin, graesslin

Reviewed By: #kwin, graesslin

Subscribers: zzag, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D18127
icc-effect-5.17.5
David Edmundson 2019-02-22 14:40:15 +00:00
parent 7014a33992
commit 47be4be020
4 changed files with 28 additions and 1 deletions

View File

@ -365,6 +365,7 @@ target_link_libraries(testOnScreenNotification
Qt5::Test
Qt5::Widgets # QAction include
Qt5::Quick
Qt5::DBus
KF5::ConfigCore
)

View File

@ -22,6 +22,7 @@ target_link_libraries( testTabBoxClientModel
Qt5::Script
Qt5::Quick
Qt5::Test
Qt5::DBus
Qt5::X11Extras
KF5::ConfigCore
KF5::I18n
@ -54,6 +55,7 @@ target_link_libraries( testTabBoxHandler
Qt5::Script
Qt5::Quick
Qt5::Test
Qt5::DBus
Qt5::X11Extras
KF5::ConfigCore
KF5::I18n

View File

@ -465,6 +465,12 @@ void KWin::Script::run()
if (running() || m_starting) {
return;
}
if (calledFromDBus()) {
m_invocationContext = message();
setDelayedReply(true);
}
m_starting = true;
QFutureWatcher<QByteArray> *watcher = new QFutureWatcher<QByteArray>(this);
connect(watcher, SIGNAL(finished()), SLOT(slotScriptLoadedFromFile()));
@ -492,8 +498,16 @@ void KWin::Script::slotScriptLoadedFromFile()
// do not load empty script
deleteLater();
watcher->deleteLater();
if (m_invocationContext.type() == QDBusMessage::MethodCallMessage) {
auto reply = m_invocationContext.createErrorReply("org.kde.kwin.Scripting.FileError", QString("Could not open %1").arg(fileName()));
QDBusConnection::sessionBus().send(reply);
m_invocationContext = QDBusMessage();
}
return;
}
QScriptValue optionsValue = m_engine->newQObject(options, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater);
m_engine->globalObject().setProperty(QStringLiteral("options"), optionsValue, QScriptValue::Undeletable);
@ -509,6 +523,12 @@ void KWin::Script::slotScriptLoadedFromFile()
deleteLater();
}
if (m_invocationContext.type() == QDBusMessage::MethodCallMessage) {
auto reply = m_invocationContext.createReply();
QDBusConnection::sessionBus().send(reply);
m_invocationContext = QDBusMessage();
}
watcher->deleteLater();
setRunning(true);
m_starting = false;

View File

@ -30,6 +30,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QtScript/QScriptEngineAgent>
#include <QJSValue>
#include <QDBusContext>
#include <QDBusMessage>
class QQmlComponent;
class QQmlContext;
class QQmlEngine;
@ -214,7 +217,7 @@ private:
QList<QScriptValue> m_userActionsMenuCallbacks;
};
class Script : public AbstractScript
class Script : public AbstractScript, QDBusContext
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
@ -254,6 +257,7 @@ private:
**/
QByteArray loadScriptFromFile(const QString &fileName);
QScriptEngine *m_engine;
QDBusMessage m_invocationContext;
bool m_starting;
QScopedPointer<ScriptUnloaderAgent> m_agent;
QHash<int, QAction*> m_touchScreenEdgeCallbacks;