Support declarative KWin scripts
For this the Script class is slightly refactored to have a common base for JavaScript and QML based scripts. Why QML bindings? This allows to use QML for example for the desktop change OSD or for fullscreen effects like Present Windows.icc-effect-5.14.5
parent
f9ad0621d5
commit
6a8b79f699
|
@ -23,15 +23,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// own
|
||||
#include "meta.h"
|
||||
#include "workspace_wrapper.h"
|
||||
#include "../thumbnailitem.h"
|
||||
// KDE
|
||||
#include <kstandarddirs.h>
|
||||
#include <KDE/KConfigGroup>
|
||||
#include <KDE/KDebug>
|
||||
#include <KDE/KPluginInfo>
|
||||
#include <KDE/KServiceTypeTrader>
|
||||
#include <kdeclarative.h>
|
||||
// Qt
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtDeclarative/QDeclarativeContext>
|
||||
#include <QtDeclarative/QDeclarativeEngine>
|
||||
#include <QtDeclarative/QDeclarativeView>
|
||||
#include <QtDeclarative/qdeclarative.h>
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
|
@ -50,36 +56,49 @@ QScriptValue kwinScriptPrint(QScriptContext *context, QScriptEngine *engine)
|
|||
return engine->undefinedValue();
|
||||
}
|
||||
|
||||
|
||||
KWin::Script::Script(int scriptId, QString scriptName, QObject *parent)
|
||||
KWin::AbstractScript::AbstractScript (int id, QString scriptName, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_scriptId(scriptId)
|
||||
, m_engine(new QScriptEngine(this))
|
||||
, m_workspace(new WorkspaceWrapper(m_engine))
|
||||
, m_scriptId(id)
|
||||
, m_running(false)
|
||||
, m_workspace(new WorkspaceWrapper(this))
|
||||
{
|
||||
m_scriptFile.setFileName(scriptName);
|
||||
QDBusConnection::sessionBus().registerObject('/' + QString::number(m_scriptId), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables);
|
||||
}
|
||||
|
||||
KWin::AbstractScript::~AbstractScript()
|
||||
{
|
||||
}
|
||||
|
||||
void KWin::AbstractScript::stop()
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
KWin::Script::Script(int id, QString scriptName, QObject *parent)
|
||||
: AbstractScript(id, scriptName, parent)
|
||||
, m_engine(new QScriptEngine(this))
|
||||
{
|
||||
QDBusConnection::sessionBus().registerObject('/' + QString::number(scriptId()), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables);
|
||||
}
|
||||
|
||||
KWin::Script::~Script()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject('/' + QString::number(m_scriptId));
|
||||
QDBusConnection::sessionBus().unregisterObject('/' + QString::number(scriptId()));
|
||||
}
|
||||
|
||||
void KWin::Script::printMessage(const QString &message)
|
||||
{
|
||||
kDebug(1212) << m_scriptFile.fileName() << ":" << message;
|
||||
kDebug(1212) << scriptFile().fileName() << ":" << message;
|
||||
emit print(message);
|
||||
}
|
||||
|
||||
void KWin::Script::run()
|
||||
{
|
||||
if (m_running) {
|
||||
if (running()) {
|
||||
return;
|
||||
}
|
||||
if (m_scriptFile.open(QIODevice::ReadOnly)) {
|
||||
QScriptValue workspace = m_engine->newQObject(m_workspace, QScriptEngine::QtOwnership,
|
||||
if (scriptFile().open(QIODevice::ReadOnly)) {
|
||||
QScriptValue workspace = m_engine->newQObject(AbstractScript::workspace(), QScriptEngine::QtOwnership,
|
||||
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater);
|
||||
m_engine->globalObject().setProperty("workspace", workspace, QScriptValue::Undeletable);
|
||||
m_engine->globalObject().setProperty("QTimer", constructTimerClass(m_engine));
|
||||
|
@ -92,14 +111,14 @@ void KWin::Script::run()
|
|||
printFunc.setData(m_engine->newQObject(this));
|
||||
m_engine->globalObject().setProperty("print", printFunc);
|
||||
|
||||
QScriptValue ret = m_engine->evaluate(m_scriptFile.readAll());
|
||||
QScriptValue ret = m_engine->evaluate(scriptFile().readAll());
|
||||
|
||||
if (ret.isError()) {
|
||||
sigException(ret);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
m_running = true;
|
||||
setRunning(true);
|
||||
}
|
||||
|
||||
void KWin::Script::sigException(const QScriptValue& exception)
|
||||
|
@ -119,11 +138,44 @@ void KWin::Script::sigException(const QScriptValue& exception)
|
|||
emit printError(exception.toString());
|
||||
}
|
||||
|
||||
void KWin::Script::stop()
|
||||
KWin::DeclarativeScript::DeclarativeScript(int id, QString scriptName, QObject *parent)
|
||||
: AbstractScript(id, scriptName, parent)
|
||||
, m_view(new QDeclarativeView())
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
KWin::DeclarativeScript::~DeclarativeScript()
|
||||
{
|
||||
}
|
||||
|
||||
void KWin::DeclarativeScript::run()
|
||||
{
|
||||
if (running()) {
|
||||
return;
|
||||
}
|
||||
m_view->setAttribute(Qt::WA_TranslucentBackground);
|
||||
m_view->setWindowFlags(Qt::X11BypassWindowManagerHint);
|
||||
m_view->setResizeMode(QDeclarativeView::SizeViewToRootObject);
|
||||
QPalette pal = m_view->palette();
|
||||
pal.setColor(m_view->backgroundRole(), Qt::transparent);
|
||||
m_view->setPalette(pal);
|
||||
|
||||
|
||||
foreach (const QString &importPath, KGlobal::dirs()->findDirs("module", "imports")) {
|
||||
m_view->engine()->addImportPath(importPath);
|
||||
}
|
||||
KDeclarative kdeclarative;
|
||||
kdeclarative.setDeclarativeEngine(m_view->engine());
|
||||
kdeclarative.initialize();
|
||||
kdeclarative.setupBindings();
|
||||
qmlRegisterType<ThumbnailItem>("org.kde.kwin", 0, 1, "ThumbnailItem");
|
||||
qmlRegisterType<WorkspaceWrapper>("org.kde.kwin", 0, 1, "KWin");
|
||||
|
||||
m_view->rootContext()->setContextProperty("workspace", workspace());
|
||||
|
||||
m_view->setSource(QUrl::fromLocalFile(scriptFile().fileName()));
|
||||
setRunning(true);
|
||||
}
|
||||
|
||||
KWin::Scripting::Scripting(QObject *parent)
|
||||
: QObject(parent)
|
||||
|
@ -142,7 +194,9 @@ void KWin::Scripting::start()
|
|||
foreach (const KService::Ptr & service, offers) {
|
||||
KPluginInfo plugininfo(service);
|
||||
plugininfo.load(conf);
|
||||
if (service->property("X-Plasma-API").toString() != "javascript") {
|
||||
const bool javaScript = service->property("X-Plasma-API").toString() == "javascript";
|
||||
const bool declarativeScript = service->property("X-Plasma-API").toString() == "declarativescript";
|
||||
if (!javaScript && !declarativeScript) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -156,7 +210,11 @@ void KWin::Scripting::start()
|
|||
kDebug(1212) << "Could not find script file for " << pluginName;
|
||||
continue;
|
||||
}
|
||||
loadScript(file);
|
||||
if (javaScript) {
|
||||
loadScript(file);
|
||||
} else if (declarativeScript) {
|
||||
loadDeclarativeScript(file);
|
||||
}
|
||||
}
|
||||
|
||||
runScripts();
|
||||
|
@ -183,6 +241,15 @@ int KWin::Scripting::loadScript(const QString &filePath)
|
|||
return id;
|
||||
}
|
||||
|
||||
int KWin::Scripting::loadDeclarativeScript(const QString &filePath)
|
||||
{
|
||||
const int id = scripts.size();
|
||||
KWin::DeclarativeScript *script = new KWin::DeclarativeScript(id, filePath, this);
|
||||
connect(script, SIGNAL(destroyed(QObject*)), SLOT(scriptDestroyed(QObject*)));
|
||||
scripts.append(script);
|
||||
return id;
|
||||
}
|
||||
|
||||
KWin::Scripting::~Scripting()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject("/Scripting");
|
||||
|
|
|
@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QtCore/QFile>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
class QDeclarativeView;
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
|
@ -32,7 +33,46 @@ namespace KWin
|
|||
{
|
||||
class WorkspaceWrapper;
|
||||
|
||||
class Script : public QObject
|
||||
class AbstractScript : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AbstractScript(int id, QString scriptName, QObject *parent = NULL);
|
||||
~AbstractScript();
|
||||
QString fileName() const {
|
||||
return m_scriptFile.fileName();
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void stop();
|
||||
Q_SCRIPTABLE virtual void run() = 0;
|
||||
|
||||
protected:
|
||||
QFile &scriptFile() {
|
||||
return m_scriptFile;
|
||||
}
|
||||
bool running() const {
|
||||
return m_running;
|
||||
}
|
||||
void setRunning(bool running) {
|
||||
m_running = running;
|
||||
}
|
||||
int scriptId() const {
|
||||
return m_scriptId;
|
||||
}
|
||||
|
||||
WorkspaceWrapper *workspace() {
|
||||
return m_workspace;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_scriptId;
|
||||
QFile m_scriptFile;
|
||||
bool m_running;
|
||||
WorkspaceWrapper *m_workspace;
|
||||
};
|
||||
|
||||
class Script : public AbstractScript
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
|
||||
|
@ -40,14 +80,10 @@ public:
|
|||
|
||||
Script(int id, QString scriptName, QObject *parent = NULL);
|
||||
virtual ~Script();
|
||||
QString fileName() const {
|
||||
return m_scriptFile.fileName();
|
||||
}
|
||||
|
||||
void printMessage(const QString &message);
|
||||
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void stop();
|
||||
Q_SCRIPTABLE void run();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -62,11 +98,22 @@ private slots:
|
|||
void sigException(const QScriptValue &exception);
|
||||
|
||||
private:
|
||||
int m_scriptId;
|
||||
QScriptEngine *m_engine;
|
||||
QFile m_scriptFile;
|
||||
WorkspaceWrapper *m_workspace;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
class DeclarativeScript : public AbstractScript
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
|
||||
public:
|
||||
explicit DeclarativeScript(int id, QString scriptName, QObject *parent = 0);
|
||||
virtual ~DeclarativeScript();
|
||||
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void run();
|
||||
|
||||
private:
|
||||
QDeclarativeView *m_view;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,7 +125,7 @@ class Scripting : public QObject
|
|||
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
|
||||
private:
|
||||
QStringList scriptList;
|
||||
QList<KWin::Script*> scripts;
|
||||
QList<KWin::AbstractScript*> scripts;
|
||||
|
||||
// Preferably call ONLY at load time
|
||||
void runScripts();
|
||||
|
@ -92,6 +139,7 @@ public:
|
|||
void start();
|
||||
~Scripting();
|
||||
Q_SCRIPTABLE Q_INVOKABLE int loadScript(const QString &filePath);
|
||||
Q_SCRIPTABLE Q_INVOKABLE int loadDeclarativeScript(const QString &filePath);
|
||||
|
||||
public Q_SLOTS:
|
||||
void scriptDestroyed(QObject *object);
|
||||
|
|
Loading…
Reference in New Issue