From abd3808574f791af606cdbdf6477b3f6cdebcd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 29 Apr 2012 19:30:12 +0200 Subject: [PATCH] Read KWin Script from file moved into thread The I/O intensive reading of the complete KWin Script file into a QByteArray is moved into a thread. Evaluating and setting up the script engine is still performed in the main thread. REVIEW: 104782 --- scripting/scripting.cpp | 61 +++++++++++++++++++++++++++++++---------- scripting/scripting.h | 10 +++++++ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp index 5aad56327a..3405a410bf 100644 --- a/scripting/scripting.cpp +++ b/scripting/scripting.cpp @@ -156,6 +156,7 @@ void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine) KWin::Script::Script(int id, QString scriptName, QString pluginName, QObject* parent) : AbstractScript(id, scriptName, pluginName, parent) , m_engine(new QScriptEngine(this)) + , m_starting(false) { QDBusConnection::sessionBus().registerObject('/' + QString::number(scriptId()), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables); } @@ -167,26 +168,56 @@ KWin::Script::~Script() void KWin::Script::run() { - if (running()) { + if (running() || m_starting) { return; } - if (scriptFile().open(QIODevice::ReadOnly)) { - QScriptValue optionsValue = m_engine->newQObject(options, QScriptEngine::QtOwnership, - QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater); - m_engine->globalObject().setProperty("options", optionsValue, QScriptValue::Undeletable); - m_engine->globalObject().setProperty("QTimer", constructTimerClass(m_engine)); - QObject::connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(sigException(QScriptValue))); - KWin::MetaScripting::supplyConfig(m_engine); - installScriptFunctions(m_engine); + m_starting = true; + QFutureWatcher *watcher = new QFutureWatcher(this); + connect(watcher, SIGNAL(finished()), SLOT(slotScriptLoadedFromFile())); + watcher->setFuture(QtConcurrent::run(this, &KWin::Script::loadScriptFromFile)); +} - QScriptValue ret = m_engine->evaluate(scriptFile().readAll()); - - if (ret.isError()) { - sigException(ret); - deleteLater(); - } +QByteArray KWin::Script::loadScriptFromFile() +{ + if (!scriptFile().open(QIODevice::ReadOnly)) { + return QByteArray(); } + QByteArray result(scriptFile().readAll()); + scriptFile().close(); + return result; +} + +void KWin::Script::slotScriptLoadedFromFile() +{ + QFutureWatcher *watcher = dynamic_cast< QFutureWatcher< QByteArray>* >(sender()); + if (!watcher) { + // not invoked from a QFutureWatcher + return; + } + if (watcher->result().isNull()) { + // do not load empty script + deleteLater(); + watcher->deleteLater(); + return; + } + QScriptValue optionsValue = m_engine->newQObject(options, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater); + m_engine->globalObject().setProperty("options", optionsValue, QScriptValue::Undeletable); + m_engine->globalObject().setProperty("QTimer", constructTimerClass(m_engine)); + QObject::connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(sigException(QScriptValue))); + KWin::MetaScripting::supplyConfig(m_engine); + installScriptFunctions(m_engine); + + QScriptValue ret = m_engine->evaluate(watcher->result()); + + if (ret.isError()) { + sigException(ret); + deleteLater(); + } + + watcher->deleteLater(); setRunning(true); + m_starting = false; } void KWin::Script::sigException(const QScriptValue& exception) diff --git a/scripting/scripting.h b/scripting/scripting.h index 6907cbd794..d445635251 100644 --- a/scripting/scripting.h +++ b/scripting/scripting.h @@ -121,9 +121,19 @@ private slots: * TODO: Log to file, show from notifier.. */ void sigException(const QScriptValue &exception); + /** + * Callback for when loadScriptFromFile has finished. + **/ + void slotScriptLoadedFromFile(); private: + /** + * Read the script from file into a byte array. + * If file cannot be read an empty byte array is returned. + **/ + QByteArray loadScriptFromFile(); QScriptEngine *m_engine; + bool m_starting; }; class DeclarativeScript : public AbstractScript