export AnimationEffect::set and ::cancel to script
Also harmonize script parsing - any combination of animationarray and global animation setting that results in a valid animation is possible using the global settings as default on the array values REVIEW: 109212
This commit is contained in:
parent
9a3a7c8824
commit
77bcadc5b4
3 changed files with 203 additions and 56 deletions
|
@ -50,8 +50,8 @@
|
||||||
</sectiondef>
|
</sectiondef>
|
||||||
<sectiondef kind="public-func">
|
<sectiondef kind="public-func">
|
||||||
<memberdef kind="function">
|
<memberdef kind="function">
|
||||||
<type>Q_SCRIPTABLE void</type>
|
<type>Q_SCRIPTABLE QList<quint64></type>
|
||||||
<definition>void KWin::ScriptedEffect::animate</definition>
|
<definition>QList<quint64> KWin::ScriptedEffect::animate</definition>
|
||||||
<argsstring>(settings)</argsstring>
|
<argsstring>(settings)</argsstring>
|
||||||
<name>animate</name>
|
<name>animate</name>
|
||||||
<read></read>
|
<read></read>
|
||||||
|
@ -79,7 +79,29 @@ supports the following attributes:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
</syntaxhighlight>
|
</syntaxhighlight>
|
||||||
At least one animation needs to be specified either with the top-level properties or in the animations list.
|
At least one animation or attribute setter (see below) needs to be specified either with the top-level properties or in the animations list.
|
||||||
|
</detaileddescription>
|
||||||
|
</memberdef>
|
||||||
|
<memberdef kind="function">
|
||||||
|
<type>Q_SCRIPTABLE QList<quint64></type>
|
||||||
|
<definition>QList<quint64> KWin::ScriptedEffect::set</definition>
|
||||||
|
<argsstring>(settings)</argsstring>
|
||||||
|
<name>set</name>
|
||||||
|
<read></read>
|
||||||
|
<detaileddescription>
|
||||||
|
Like animate, just that the manipulation does not implicitly end with the animation. You have to explicitly cancel it.
|
||||||
|
Until then, the manipulated attribute will remain at animation target value.
|
||||||
|
</detaileddescription>
|
||||||
|
</memberdef>
|
||||||
|
<memberdef kind="function">
|
||||||
|
<type>Q_SCRIPTABLE bool</type>
|
||||||
|
<definition>bool KWin::ScriptedEffect::cancel</definition>
|
||||||
|
<argsstring>(QList<quint64>)</argsstring>
|
||||||
|
<name>cancel</name>
|
||||||
|
<read></read>
|
||||||
|
<detaileddescription>
|
||||||
|
Cancel one or more present animations caused and returned by KWin::ScriptedEffect::animate or KWin::ScriptedEffect::set.
|
||||||
|
For convenience you can pass a single quint64 as well.
|
||||||
</detaileddescription>
|
</detaileddescription>
|
||||||
</memberdef>
|
</memberdef>
|
||||||
<memberdef kind="function">
|
<memberdef kind="function">
|
||||||
|
|
|
@ -94,28 +94,36 @@ QScriptValue kwinScriptScreenEdge(QScriptContext *context, QScriptEngine *engine
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnimationSettings {
|
struct AnimationSettings {
|
||||||
AnimationEffect::Attribute a;
|
enum { Type = 1<<0, Curve = 1<<1, Delay = 1<<2, Duration = 1<<3 };
|
||||||
|
AnimationEffect::Attribute type;
|
||||||
QEasingCurve::Type curve;
|
QEasingCurve::Type curve;
|
||||||
bool curveSet;
|
|
||||||
FPx2 from;
|
FPx2 from;
|
||||||
FPx2 to;
|
FPx2 to;
|
||||||
int delay;
|
int delay;
|
||||||
bool valid;
|
uint duration;
|
||||||
|
uint set;
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationSettings animationSettingsFromObject(QScriptValue &object)
|
AnimationSettings animationSettingsFromObject(QScriptValue &object)
|
||||||
{
|
{
|
||||||
AnimationSettings settings;
|
AnimationSettings settings;
|
||||||
settings.curve = QEasingCurve::Linear;
|
settings.set = 0;
|
||||||
settings.valid = true;
|
|
||||||
settings.curveSet = false;
|
|
||||||
|
|
||||||
settings.to = qscriptvalue_cast<FPx2>(object.property("to"));
|
settings.to = qscriptvalue_cast<FPx2>(object.property("to"));
|
||||||
settings.from = qscriptvalue_cast<FPx2>(object.property("from"));
|
settings.from = qscriptvalue_cast<FPx2>(object.property("from"));
|
||||||
|
|
||||||
|
QScriptValue duration = object.property("duration");
|
||||||
|
if (duration.isValid() && duration.isNumber()) {
|
||||||
|
settings.duration = duration.toUInt32();
|
||||||
|
settings.set |= AnimationSettings::Duration;
|
||||||
|
} else {
|
||||||
|
settings.duration = 0;
|
||||||
|
}
|
||||||
|
|
||||||
QScriptValue delay = object.property("delay");
|
QScriptValue delay = object.property("delay");
|
||||||
if (delay.isValid() && delay.isNumber()) {
|
if (delay.isValid() && delay.isNumber()) {
|
||||||
settings.delay = delay.toInt32();
|
settings.delay = delay.toInt32();
|
||||||
|
settings.set |= AnimationSettings::Delay;
|
||||||
} else {
|
} else {
|
||||||
settings.delay = 0;
|
settings.delay = 0;
|
||||||
}
|
}
|
||||||
|
@ -123,65 +131,53 @@ AnimationSettings animationSettingsFromObject(QScriptValue &object)
|
||||||
QScriptValue curve = object.property("curve");
|
QScriptValue curve = object.property("curve");
|
||||||
if (curve.isValid() && curve.isNumber()) {
|
if (curve.isValid() && curve.isNumber()) {
|
||||||
settings.curve = static_cast<QEasingCurve::Type>(curve.toInt32());
|
settings.curve = static_cast<QEasingCurve::Type>(curve.toInt32());
|
||||||
settings.curveSet = true;
|
settings.set |= AnimationSettings::Curve;
|
||||||
|
} else {
|
||||||
|
settings.curve = QEasingCurve::Linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue type = object.property("type");
|
QScriptValue type = object.property("type");
|
||||||
if (!type.isValid() || !type.isNumber()) {
|
if (type.isValid() && type.isNumber()) {
|
||||||
settings.valid = false;
|
settings.type = static_cast<AnimationEffect::Attribute>(type.toInt32());
|
||||||
|
settings.set |= AnimationSettings::Type;
|
||||||
|
} else {
|
||||||
|
settings.type = static_cast<AnimationEffect::Attribute>(-1);
|
||||||
}
|
}
|
||||||
settings.a = static_cast<AnimationEffect::Attribute>(type.toInt32());
|
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue kwinEffectAnimate(QScriptContext *context, QScriptEngine *engine)
|
QList<AnimationSettings> animationSettings(QScriptContext *context, ScriptedEffect *effect, EffectWindow **window)
|
||||||
{
|
{
|
||||||
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
|
QList<AnimationSettings> settings;
|
||||||
if (!effect) {
|
if (!effect) {
|
||||||
context->throwError(QScriptContext::ReferenceError, "Internal Scripted KWin Effect error");
|
context->throwError(QScriptContext::ReferenceError, "Internal Scripted KWin Effect error");
|
||||||
return engine->undefinedValue();
|
return settings;
|
||||||
}
|
}
|
||||||
if (context->argumentCount() != 1) {
|
if (context->argumentCount() != 1) {
|
||||||
context->throwError(QScriptContext::SyntaxError, "Exactly one argument expected");
|
context->throwError(QScriptContext::SyntaxError, "Exactly one argument expected");
|
||||||
return engine->undefinedValue();
|
return settings;
|
||||||
}
|
}
|
||||||
if (!context->argument(0).isObject()) {
|
if (!context->argument(0).isObject()) {
|
||||||
context->throwError(QScriptContext::TypeError, "Argument needs to be an object");
|
context->throwError(QScriptContext::TypeError, "Argument needs to be an object");
|
||||||
return engine->undefinedValue();
|
return settings;
|
||||||
}
|
}
|
||||||
QScriptValue object = context->argument(0);
|
QScriptValue object = context->argument(0);
|
||||||
QScriptValue windowProperty = object.property("window");
|
QScriptValue windowProperty = object.property("window");
|
||||||
if (!windowProperty.isValid() || !windowProperty.isObject()) {
|
if (!windowProperty.isValid() || !windowProperty.isObject()) {
|
||||||
context->throwError(QScriptContext::TypeError, "Window property missing in animation options");
|
context->throwError(QScriptContext::TypeError, "Window property missing in animation options");
|
||||||
return engine->undefinedValue();
|
return settings;
|
||||||
}
|
}
|
||||||
EffectWindow *window = qobject_cast<EffectWindow*>(windowProperty.toQObject());
|
*window = qobject_cast<EffectWindow*>(windowProperty.toQObject());
|
||||||
if (!window) {
|
|
||||||
context->throwError(QScriptContext::TypeError, "Window property does not contain an EffectWindow");
|
|
||||||
return engine->undefinedValue();
|
|
||||||
}
|
|
||||||
QScriptValue durationProperty = object.property("duration");
|
|
||||||
if (!durationProperty.isValid() || !durationProperty.isNumber()) {
|
|
||||||
context->throwError(QScriptContext::TypeError, "Duration property missing in animation options");
|
|
||||||
return engine->undefinedValue();
|
|
||||||
}
|
|
||||||
const int duration = durationProperty.toInt32();
|
|
||||||
|
|
||||||
QEasingCurve::Type curve = QEasingCurve::Linear;
|
settings << animationSettingsFromObject(object); // global
|
||||||
QList<AnimationSettings> settings;
|
|
||||||
AnimationSettings globalSettings = animationSettingsFromObject(object);
|
QScriptValue animations = object.property("animations"); // array
|
||||||
if (globalSettings.valid) {
|
|
||||||
settings << globalSettings;
|
|
||||||
if (globalSettings.curveSet) {
|
|
||||||
curve = globalSettings.curve;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QScriptValue animations = object.property("animations");
|
|
||||||
if (animations.isValid()) {
|
if (animations.isValid()) {
|
||||||
if (!animations.isArray()) {
|
if (!animations.isArray()) {
|
||||||
context->throwError(QScriptContext::TypeError, "Animations provided but not an array");
|
context->throwError(QScriptContext::TypeError, "Animations provided but not an array");
|
||||||
return engine->undefinedValue();
|
settings.clear();
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
const int length = static_cast<int>(animations.property("length").toInteger());
|
const int length = static_cast<int>(animations.property("length").toInteger());
|
||||||
for (int i=0; i<length; ++i) {
|
for (int i=0; i<length; ++i) {
|
||||||
|
@ -191,29 +187,136 @@ QScriptValue kwinEffectAnimate(QScriptContext *context, QScriptEngine *engine)
|
||||||
}
|
}
|
||||||
if (value.isObject()) {
|
if (value.isObject()) {
|
||||||
AnimationSettings s = animationSettingsFromObject(value);
|
AnimationSettings s = animationSettingsFromObject(value);
|
||||||
if (s.valid) {
|
const uint set = s.set | settings.at(0).set;
|
||||||
|
if (!(set & AnimationSettings::Type)) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Type property missing in animation options");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(set & AnimationSettings::Duration)) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Duration property missing in animation options");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!s.set & AnimationSettings::Curve) {
|
||||||
|
s.curve = settings.at(0).curve;
|
||||||
|
}
|
||||||
|
if (!s.set & AnimationSettings::Delay) {
|
||||||
|
s.delay = settings.at(0).delay;
|
||||||
|
}
|
||||||
settings << s;
|
settings << s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.count() == 1) {
|
||||||
|
const uint set = settings.at(0).set;
|
||||||
|
if (!(set & AnimationSettings::Type)) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Type property missing in animation options");
|
||||||
|
settings.clear();
|
||||||
|
}
|
||||||
|
if (!(set & AnimationSettings::Duration)) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Duration property missing in animation options");
|
||||||
|
settings.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue kwinEffectAnimate(QScriptContext *context, QScriptEngine *engine)
|
||||||
|
{
|
||||||
|
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
|
||||||
|
EffectWindow *window;
|
||||||
|
QList<AnimationSettings> settings = animationSettings(context, effect, &window);
|
||||||
if (settings.empty()) {
|
if (settings.empty()) {
|
||||||
context->throwError(QScriptContext::TypeError, "No animations provided");
|
context->throwError(QScriptContext::TypeError, "No animations provided");
|
||||||
return engine->undefinedValue();
|
return engine->undefinedValue();
|
||||||
}
|
}
|
||||||
|
if (!window) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Window property does not contain an EffectWindow");
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QVariant> animIds;
|
||||||
foreach (const AnimationSettings &setting, settings) {
|
foreach (const AnimationSettings &setting, settings) {
|
||||||
effect->animate(window,
|
animIds << QVariant(effect->animate(window,
|
||||||
setting.a,
|
setting.type,
|
||||||
duration,
|
setting.duration,
|
||||||
setting.to,
|
setting.to,
|
||||||
setting.from,
|
setting.from,
|
||||||
NULL,
|
NULL,
|
||||||
setting.curveSet ? setting.curve : curve,
|
setting.curve,
|
||||||
setting.delay);
|
setting.delay));
|
||||||
}
|
}
|
||||||
|
|
||||||
return engine->newVariant(true);
|
return engine->newVariant(animIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue kwinEffectSet(QScriptContext *context, QScriptEngine *engine)
|
||||||
|
{
|
||||||
|
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
|
||||||
|
|
||||||
|
EffectWindow *window;
|
||||||
|
QList<AnimationSettings> settings = animationSettings(context, effect, &window);
|
||||||
|
if (settings.empty()) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "No animations provided");
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
if (!window) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Window property does not contain an EffectWindow");
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QVariant> animIds;
|
||||||
|
foreach (const AnimationSettings &setting, settings) {
|
||||||
|
animIds << QVariant(effect->set(window,
|
||||||
|
setting.type,
|
||||||
|
setting.duration,
|
||||||
|
setting.to,
|
||||||
|
setting.from,
|
||||||
|
NULL,
|
||||||
|
setting.curve,
|
||||||
|
setting.delay));
|
||||||
|
}
|
||||||
|
|
||||||
|
return engine->newVariant(animIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue kwinEffectCancel(QScriptContext *context, QScriptEngine *engine)
|
||||||
|
{
|
||||||
|
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
|
||||||
|
if (context->argumentCount() != 1) {
|
||||||
|
context->throwError(QScriptContext::SyntaxError, "Exactly one argument expected");
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
QVariant v = context->argument(0).toVariant();
|
||||||
|
QList<quint64> animIds;
|
||||||
|
bool ok = false;
|
||||||
|
if (v.isValid()) {
|
||||||
|
quint64 animId = v.toULongLong(&ok);
|
||||||
|
if (ok)
|
||||||
|
animIds << animId;
|
||||||
|
}
|
||||||
|
if (!ok) { // may still be a variantlist of variants being quint64
|
||||||
|
QList<QVariant> list = v.toList();
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
foreach (const QVariant &vv, list) {
|
||||||
|
quint64 animId = vv.toULongLong(&ok);
|
||||||
|
if (ok)
|
||||||
|
animIds << animId;
|
||||||
|
}
|
||||||
|
ok = !animIds.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
context->throwError(QScriptContext::TypeError, "Argument needs to be one or several quint64");
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const quint64 &animId, animIds) {
|
||||||
|
ok |= engine->newVariant(effect->cancel(animId)).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
return engine->newVariant(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue effectWindowToScriptValue(QScriptEngine *eng, const KEffectWindowRef &window)
|
QScriptValue effectWindowToScriptValue(QScriptEngine *eng, const KEffectWindowRef &window)
|
||||||
|
@ -331,6 +434,16 @@ bool ScriptedEffect::init(const QString &effectName, const QString &pathToScript
|
||||||
animateFunc.setData(m_engine->newQObject(this));
|
animateFunc.setData(m_engine->newQObject(this));
|
||||||
m_engine->globalObject().setProperty("animate", animateFunc);
|
m_engine->globalObject().setProperty("animate", animateFunc);
|
||||||
|
|
||||||
|
// and the set variant
|
||||||
|
QScriptValue setFunc = m_engine->newFunction(kwinEffectSet);
|
||||||
|
setFunc.setData(m_engine->newQObject(this));
|
||||||
|
m_engine->globalObject().setProperty("set", setFunc);
|
||||||
|
|
||||||
|
// cancel...
|
||||||
|
QScriptValue cancelFunc = m_engine->newFunction(kwinEffectCancel);
|
||||||
|
cancelFunc.setData(m_engine->newQObject(this));
|
||||||
|
m_engine->globalObject().setProperty("cancel", cancelFunc);
|
||||||
|
|
||||||
QScriptValue ret = m_engine->evaluate(scriptFile.readAll());
|
QScriptValue ret = m_engine->evaluate(scriptFile.readAll());
|
||||||
|
|
||||||
if (ret.isError()) {
|
if (ret.isError()) {
|
||||||
|
@ -355,7 +468,7 @@ void ScriptedEffect::signalHandlerException(const QScriptValue &value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptedEffect::animate(KWin::EffectWindow* w, KWin::AnimationEffect::Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from, KWin::AnimationData* data, QEasingCurve::Type curve, int delay)
|
uint metaFromData(KWin::AnimationData* data)
|
||||||
{
|
{
|
||||||
uint meta = 0;
|
uint meta = 0;
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -381,7 +494,17 @@ void ScriptedEffect::animate(KWin::EffectWindow* w, KWin::AnimationEffect::Attri
|
||||||
AnimationEffect::setMetaData(AnimationEffect::RelativeTargetY, data->relativeTargetY(), meta);
|
AnimationEffect::setMetaData(AnimationEffect::RelativeTargetY, data->relativeTargetY(), meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimationEffect::animate(w, a, meta, ms, to, QEasingCurve(curve), delay, from);
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ScriptedEffect::animate(KWin::EffectWindow* w, KWin::AnimationEffect::Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from, KWin::AnimationData* data, QEasingCurve::Type curve, int delay)
|
||||||
|
{
|
||||||
|
return AnimationEffect::animate(w, a, metaFromData(data), ms, to, QEasingCurve(curve), delay, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ScriptedEffect::set(KWin::EffectWindow* w, KWin::AnimationEffect::Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from, KWin::AnimationData* data, QEasingCurve::Type curve, int delay)
|
||||||
|
{
|
||||||
|
return AnimationEffect::set(w, a, metaFromData(data), ms, to, QEasingCurve(curve), delay, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptedEffect::isGrabbed(EffectWindow* w, ScriptedEffect::DataRole grabRole)
|
bool ScriptedEffect::isGrabbed(EffectWindow* w, ScriptedEffect::DataRole grabRole)
|
||||||
|
|
|
@ -131,7 +131,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void animate(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve::Type curve = QEasingCurve::Linear, int delay = 0);
|
quint64 animate(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve::Type curve = QEasingCurve::Linear, int delay = 0);
|
||||||
|
quint64 set(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve::Type curve = QEasingCurve::Linear, int delay = 0);
|
||||||
|
bool cancel(quint64 animationId) { return AnimationEffect::cancel(animationId); }
|
||||||
virtual bool borderActivated(ElectricBorder border);
|
virtual bool borderActivated(ElectricBorder border);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
Loading…
Reference in a new issue