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();
};
}