JavaScript bindings for KWin effects
Scripted effects follow the Plamsoid package structure and the effect loader recognizes a scripted effect at the according line in the desktop file. If it is a scripted effect a different loader is used which instantiates an object of the ScriptedEffect class. This class inherits the AnimationEffect and exports the animate method and the EffectsHandler.
This commit is contained in:
parent
2007a7eab8
commit
5592dffb48
6 changed files with 275 additions and 1 deletions
|
@ -122,6 +122,7 @@ if(KWIN_BUILD_SCRIPTING)
|
|||
scripting/scripting.cpp
|
||||
scripting/workspace_wrapper.cpp
|
||||
scripting/meta.cpp
|
||||
scripting/scriptedeffect.cpp
|
||||
scripting/timer.cpp
|
||||
)
|
||||
endif(KWIN_BUILD_SCRIPTING)
|
||||
|
|
32
effects.cpp
32
effects.cpp
|
@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#ifdef KWIN_BUILD_TABBOX
|
||||
#include "tabbox.h"
|
||||
#endif
|
||||
#include "scripting/scriptedeffect.h"
|
||||
#include "thumbnailitem.h"
|
||||
#include "workspace.h"
|
||||
#include "kwinglutils.h"
|
||||
|
@ -1139,6 +1140,11 @@ bool EffectsHandlerImpl::loadEffect(const QString& name, bool checkDefault)
|
|||
}
|
||||
KService::Ptr service = offers.first();
|
||||
|
||||
if (service->property("X-Plasma-API").toString() == "javascript") {
|
||||
// this is a scripted effect - use different loader
|
||||
return loadScriptedEffect(name, service.data());
|
||||
}
|
||||
|
||||
KLibrary* library = findEffectLibrary(service.data());
|
||||
if (!library) {
|
||||
return false;
|
||||
|
@ -1222,6 +1228,28 @@ bool EffectsHandlerImpl::loadEffect(const QString& name, bool checkDefault)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::loadScriptedEffect(const QString& name, KService *service)
|
||||
{
|
||||
const KDesktopFile df("services", service->entryPath());
|
||||
const QString scriptName = df.desktopGroup().readEntry<QString>("X-Plasma-MainScript", "");
|
||||
if (scriptName.isEmpty()) {
|
||||
kDebug(1212) << "X-Plasma-MainScript not set";
|
||||
return false;
|
||||
}
|
||||
const QString scriptFile = KStandardDirs::locateLocal("data", "kwin/effects/" + name + '/' + scriptName);
|
||||
if (scriptFile.isNull()) {
|
||||
kDebug(1212) << "Could not locate the effect script";
|
||||
return false;
|
||||
}
|
||||
ScriptedEffect *effect = ScriptedEffect::create(scriptFile);
|
||||
if (!effect) {
|
||||
return false;
|
||||
}
|
||||
effect_order.insert(service->property("X-KDE-Ordering").toInt(), EffectPair(name, effect));
|
||||
effectsChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::unloadEffect(const QString& name)
|
||||
{
|
||||
Workspace::self()->addRepaintFull();
|
||||
|
@ -1235,7 +1263,9 @@ void EffectsHandlerImpl::unloadEffect(const QString& name)
|
|||
delete it.value().second;
|
||||
effect_order.erase(it);
|
||||
effectsChanged();
|
||||
effect_libraries[ name ]->unload();
|
||||
if (effect_libraries.contains(name)) {
|
||||
effect_libraries[ name ]->unload();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ protected Q_SLOTS:
|
|||
void slotPropertyNotify(long atom);
|
||||
|
||||
protected:
|
||||
bool loadScriptedEffect(const QString &name, KService *service);
|
||||
KLibrary* findEffectLibrary(KService* service);
|
||||
void effectsChanged();
|
||||
void setupClientConnections(KWin::Client *c);
|
||||
|
|
|
@ -90,6 +90,9 @@ class AnimationEffectPrivate;
|
|||
class KWIN_EXPORT AnimationEffect : public Effect
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(Anchor)
|
||||
Q_ENUMS(Attribute)
|
||||
Q_ENUMS(MetaType)
|
||||
public:
|
||||
enum Anchor { Left = 1<<0, Top = 1<<1, Right = 1<<2, Bottom = 1<<3,
|
||||
Horizontal = Left|Right, Vertical = Top|Bottom, Mouse = 1<<4 };
|
||||
|
|
174
scripting/scriptedeffect.cpp
Normal file
174
scripting/scriptedeffect.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
|
||||
#include "scriptedeffect.h"
|
||||
#include "meta.h"
|
||||
// KDE
|
||||
#include <KDE/KDebug>
|
||||
// Qt
|
||||
#include <QtCore/QFile>
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtScript/QScriptValueIterator>
|
||||
|
||||
typedef KWin::EffectWindow* KEffectWindowRef;
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
QScriptValue kwinEffectScriptPrint(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
ScriptedEffect *script = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
|
||||
QString result;
|
||||
for (int i = 0; i < context->argumentCount(); ++i) {
|
||||
if (i > 0) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(context->argument(i).toString());
|
||||
}
|
||||
kDebug(1212) << script->scriptFile() << ":" << result;
|
||||
|
||||
return engine->undefinedValue();
|
||||
}
|
||||
|
||||
QScriptValue effectWindowToScriptValue(QScriptEngine *eng, const KEffectWindowRef &window)
|
||||
{
|
||||
return eng->newQObject(window, QScriptEngine::QtOwnership,
|
||||
QScriptEngine::ExcludeChildObjects | QScriptEngine::ExcludeDeleteLater | QScriptEngine::PreferExistingWrapperObject);
|
||||
}
|
||||
|
||||
void effectWindowFromScriptValue(const QScriptValue &value, EffectWindow* &window)
|
||||
{
|
||||
window = qobject_cast<EffectWindow*>(value.toQObject());
|
||||
}
|
||||
|
||||
ScriptedEffect *ScriptedEffect::create(const QString &pathToScript)
|
||||
{
|
||||
ScriptedEffect *effect = new ScriptedEffect();
|
||||
if (!effect->init(pathToScript)) {
|
||||
delete effect;
|
||||
return NULL;
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
ScriptedEffect::ScriptedEffect()
|
||||
: AnimationEffect()
|
||||
, m_engine(new QScriptEngine(this))
|
||||
{
|
||||
connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), SLOT(signalHandlerException(QScriptValue)));
|
||||
}
|
||||
|
||||
bool ScriptedEffect::init(const QString &pathToScript)
|
||||
{
|
||||
QFile scriptFile(pathToScript);
|
||||
if (!scriptFile.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
m_scriptFile = pathToScript;
|
||||
QScriptValue effectsObject = m_engine->newQObject(effects, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater);
|
||||
m_engine->globalObject().setProperty("effects", effectsObject, QScriptValue::Undeletable);
|
||||
m_engine->globalObject().setProperty("Effect", m_engine->newQMetaObject(&AnimationEffect::staticMetaObject));
|
||||
m_engine->globalObject().setProperty("effect", m_engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater), QScriptValue::Undeletable);
|
||||
MetaScripting::registration(m_engine);
|
||||
qScriptRegisterMetaType<KEffectWindowRef>(m_engine, effectWindowToScriptValue, effectWindowFromScriptValue);
|
||||
// add our print
|
||||
QScriptValue printFunc = m_engine->newFunction(kwinEffectScriptPrint);
|
||||
printFunc.setData(m_engine->newQObject(this));
|
||||
m_engine->globalObject().setProperty("print", printFunc);
|
||||
|
||||
QScriptValue ret = m_engine->evaluate(scriptFile.readAll());
|
||||
|
||||
if (ret.isError()) {
|
||||
signalHandlerException(ret);
|
||||
return false;
|
||||
}
|
||||
scriptFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptedEffect::signalHandlerException(const QScriptValue &value)
|
||||
{
|
||||
if (value.isError()) {
|
||||
kDebug(1212) << "KWin Effect script encountered an error at [Line " << m_engine->uncaughtExceptionLineNumber() << "]";
|
||||
kDebug(1212) << "Message: " << value.toString();
|
||||
|
||||
QScriptValueIterator iter(value);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
kDebug(1212) << " " << iter.name() << ": " << iter.value().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, float to, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay);
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QPoint to, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay);
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QPointF to, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay);
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QSize to, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay);
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QSizeF to, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay);
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, float to, float from, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay, FPx2(from));
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, float to, float to2, float from, float from2, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to, to2), curve, delay, FPx2(from, from2));
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QPoint to, QPoint from, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay, FPx2(from));
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QPointF to, QPointF from, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay, FPx2(from));
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QSize to, QSize from, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay, FPx2(from));
|
||||
}
|
||||
|
||||
void ScriptedEffect::animate(EffectWindow *w, Attribute a, int ms, QSizeF to, QSizeF from, uint meta, QEasingCurve curve, int delay)
|
||||
{
|
||||
AnimationEffect::animate(w, a, meta, ms, FPx2(to), curve, delay, FPx2(from));
|
||||
}
|
||||
|
||||
} // namespace
|
65
scripting/scriptedeffect.h
Normal file
65
scripting/scriptedeffect.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef KWIN_SCRIPTEDEFFECT_H
|
||||
#define KWIN_SCRIPTEDEFFECT_H
|
||||
|
||||
#include <kwinanimationeffect.h>
|
||||
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class ScriptedEffect : public KWin::AnimationEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
const QString &scriptFile() const {
|
||||
return m_scriptFile;
|
||||
}
|
||||
static ScriptedEffect *create(const QString &pathToScript);
|
||||
|
||||
public Q_SLOTS:
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, float to, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QPoint to, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QPointF to, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QSize to, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QSizeF to, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, float to, float from, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, float to, float to2, float from, float from2, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QPoint to, QPoint from, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QPointF to, QPointF from, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QSize to, QSize from, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, QSizeF to, QSizeF from, uint meta = 0, QEasingCurve curve = QEasingCurve(), int delay = 0);
|
||||
|
||||
private Q_SLOTS:
|
||||
void signalHandlerException(const QScriptValue &value);
|
||||
private:
|
||||
ScriptedEffect();
|
||||
bool init(const QString &pathToScript);
|
||||
QScriptEngine *m_engine;
|
||||
QString m_scriptFile;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KWIN_SCRIPTEDEFFECT_H
|
Loading…
Reference in a new issue