diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp index 7e3e078c57..5aad56327a 100644 --- a/scripting/scripting.cpp +++ b/scripting/scripting.cpp @@ -37,7 +37,9 @@ along with this program. If not, see . #include // Qt #include +#include #include +#include #include #include #include @@ -248,6 +250,7 @@ void KWin::DeclarativeScript::run() KWin::Scripting::Scripting(QObject *parent) : QObject(parent) + , m_scriptsLock(new QMutex(QMutex::Recursive)) { QDBusConnection::sessionBus().registerObject("/Scripting", this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables); QDBusConnection::sessionBus().registerService("org.kde.kwin.Scripting"); @@ -256,11 +259,20 @@ KWin::Scripting::Scripting(QObject *parent) } void KWin::Scripting::start() +{ + // perform querying for the services in a thread + QFutureWatcher *watcher = new QFutureWatcher(this); + connect(watcher, SIGNAL(finished()), this, SLOT(slotScriptsQueried())); + watcher->setFuture(QtConcurrent::run(this, &KWin::Scripting::queryScriptsToLoad)); +} + +LoadScriptList KWin::Scripting::queryScriptsToLoad() { KSharedConfig::Ptr _config = KGlobal::config(); KConfigGroup conf(_config, "Plugins"); KService::List offers = KServiceTypeTrader::self()->query("KWin/Script"); + LoadScriptList scriptsToLoad; foreach (const KService::Ptr & service, offers) { KPluginInfo plugininfo(service); @@ -285,18 +297,37 @@ void KWin::Scripting::start() kDebug(1212) << "Could not find script file for " << pluginName; continue; } - if (javaScript) { - loadScript(file, pluginName); - } else if (declarativeScript) { - loadDeclarativeScript(file, pluginName); + scriptsToLoad << qMakePair(javaScript, qMakePair(file, pluginName)); + } + return scriptsToLoad; +} + +void KWin::Scripting::slotScriptsQueried() +{ + QFutureWatcher *watcher = dynamic_cast< QFutureWatcher* >(sender()); + if (!watcher) { + // slot invoked not from a FutureWatcher + return; + } + + LoadScriptList scriptsToLoad = watcher->result(); + for (LoadScriptList::const_iterator it = scriptsToLoad.constBegin(); + it != scriptsToLoad.constEnd(); + ++it) { + if (it->first) { + loadScript(it->second.first, it->second.second); + } else { + loadDeclarativeScript(it->second.first, it->second.second); } } runScripts(); + watcher->deleteLater(); } bool KWin::Scripting::isScriptLoaded(const QString &pluginName) const { + QMutexLocker locker(m_scriptsLock.data()); foreach (AbstractScript *script, scripts) { if (script->pluginName() == pluginName) { return true; @@ -307,6 +338,7 @@ bool KWin::Scripting::isScriptLoaded(const QString &pluginName) const bool KWin::Scripting::unloadScript(const QString &pluginName) { + QMutexLocker locker(m_scriptsLock.data()); foreach (AbstractScript *script, scripts) { if (script->pluginName() == pluginName) { script->deleteLater(); @@ -318,6 +350,7 @@ bool KWin::Scripting::unloadScript(const QString &pluginName) void KWin::Scripting::runScripts() { + QMutexLocker locker(m_scriptsLock.data()); for (int i = 0; i < scripts.size(); i++) { scripts.at(i)->run(); } @@ -325,11 +358,13 @@ void KWin::Scripting::runScripts() void KWin::Scripting::scriptDestroyed(QObject *object) { + QMutexLocker locker(m_scriptsLock.data()); scripts.removeAll(static_cast(object)); } int KWin::Scripting::loadScript(const QString &filePath, const QString& pluginName) { + QMutexLocker locker(m_scriptsLock.data()); if (isScriptLoaded(pluginName)) { return -1; } @@ -342,6 +377,7 @@ int KWin::Scripting::loadScript(const QString &filePath, const QString& pluginNa int KWin::Scripting::loadDeclarativeScript(const QString& filePath, const QString& pluginName) { + QMutexLocker locker(m_scriptsLock.data()); if (isScriptLoaded(pluginName)) { return -1; } diff --git a/scripting/scripting.h b/scripting/scripting.h index 5fefe87d26..6907cbd794 100644 --- a/scripting/scripting.h +++ b/scripting/scripting.h @@ -28,10 +28,14 @@ along with this program. If not, see . class QAction; class QDeclarativeView; +class QMutex; class QScriptEngine; class QScriptValue; class KConfigGroup; +/// @c true == javascript, @c false == qml +typedef QList< QPair > > LoadScriptList; + namespace KWin { class WorkspaceWrapper; @@ -147,6 +151,10 @@ class Scripting : public QObject private: QStringList scriptList; QList scripts; + /** + * Lock to protect the scripts member variable. + **/ + QScopedPointer m_scriptsLock; // Preferably call ONLY at load time void runScripts(); @@ -162,6 +170,12 @@ public: public Q_SLOTS: void scriptDestroyed(QObject *object); void start(); + +private Q_SLOTS: + void slotScriptsQueried(); + +private: + LoadScriptList queryScriptsToLoad(); }; }