diff --git a/libkwineffects/anidata.cpp b/libkwineffects/anidata.cpp index f1a07d46cb..cc0d872e7f 100644 --- a/libkwineffects/anidata.cpp +++ b/libkwineffects/anidata.cpp @@ -30,11 +30,11 @@ AniData::AniData() attribute = AnimationEffect::Opacity; windowType = (NET::WindowTypeMask)0; duration = time = meta = startTime = 0; - waitAtSource = false; + waitAtSource = keepAtTarget = false; } AniData::AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, - QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource ) + QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget ) { attribute = a; this->from = from; @@ -44,6 +44,7 @@ AniData::AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, time = 0; this->meta = meta; this->waitAtSource = waitAtSource; + this->keepAtTarget = keepAtTarget; startTime = AnimationEffect::clock() + delay; } @@ -58,6 +59,8 @@ AniData::AniData(const AniData &other) customCurve = other.customCurve; windowType = other.windowType; meta = other.meta; + waitAtSource = other.waitAtSource; + keepAtTarget = other.keepAtTarget; startTime = other.startTime; } diff --git a/libkwineffects/anidata_p.h b/libkwineffects/anidata_p.h index a0c450bc0a..b2c704912c 100644 --- a/libkwineffects/anidata_p.h +++ b/libkwineffects/anidata_p.h @@ -31,7 +31,7 @@ class AniData { public: AniData(); AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, - QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource ); + QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget = false); AniData(const AniData &other); explicit AniData(const QString &str); inline void addTime(int t) { time += t; } @@ -48,7 +48,7 @@ public: uint meta; qint64 startTime; NET::WindowTypeMask windowType; - bool waitAtSource; + bool waitAtSource, keepAtTarget; }; } // namespace diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp index 9709be4517..f2b55d0508 100644 --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -74,7 +74,7 @@ bool AnimationEffect::isActive() const #define RELATIVE_XY(_FIELD_) const bool relative[2] = { static_cast(metaData(Relative##_FIELD_##X, meta)), \ static_cast(metaData(Relative##_FIELD_##Y, meta)) } -void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from ) +quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget ) { const bool waitAtSource = from.isValid(); if (a < NonFloatBase) { @@ -179,7 +179,8 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms, AniMap::iterator it = d->m_animations.find(w); if (it == d->m_animations.end()) it = d->m_animations.insert(w, QPair, QRect>(QList(), QRect())); - it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource)); + it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource, keepAtTarget)); + quint64 ret_id = quint64(&it->first.last()); it->second = QRect(); d->m_animationsTouched = true; @@ -192,6 +193,29 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms, else { triggerRepaint(); } + return ret_id; +} + +bool AnimationEffect::cancel(quint64 animationId) +{ + Q_D(AnimationEffect); + for (AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); entry != mapEnd; ++entry) { + for (QList::iterator anim = entry->first.begin(), animEnd = entry->first.end(); anim != animEnd; ++anim) { + if (quint64(&(*anim)) == animationId) { + entry->first.erase(anim); // remove the animation + if (entry->first.isEmpty()) { // no other animations on the window, release it. + const int i = d->m_zombies.indexOf(entry.key()); + if ( i > -1 ) { + d->m_zombies.removeAt( i ); + entry.key()->unrefWindow(); + } + d->m_animations.erase(entry); + } + return true; + } + } + } + return false; } void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) @@ -221,7 +245,7 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) anim->addTime(time); } - if (anim->time < anim->duration) { + if (anim->time < anim->duration || anim->keepAtTarget) { // if (anim->attribute != Brightness && anim->attribute != Saturation && anim->attribute != Opacity) // transformed = true; d->m_animated = true; @@ -540,14 +564,18 @@ float AnimationEffect::interpolated( const AniData &a, int i ) const { if (a.startTime > clock()) return a.from[i]; - return a.from[i] + a.curve.valueForProgress( ((float)a.time)/a.duration )*(a.to[i] - a.from[i]); + if (a.time < a.duration) + return a.from[i] + a.curve.valueForProgress( ((float)a.time)/a.duration )*(a.to[i] - a.from[i]); + return a.to[i]; // we're done and "waiting" at the target value } float AnimationEffect::progress( const AniData &a ) const { if (a.startTime > clock()) return 0.0; - return a.curve.valueForProgress( ((float)a.time)/a.duration ); + if (a.time < a.duration) + return a.curve.valueForProgress( ((float)a.time)/a.duration ); + return 1.0; // we're done and "waiting" at the target value } diff --git a/libkwineffects/kwinanimationeffect.h b/libkwineffects/kwinanimationeffect.h index d7b6722055..09ff09cb71 100644 --- a/libkwineffects/kwinanimationeffect.h +++ b/libkwineffects/kwinanimationeffect.h @@ -155,13 +155,32 @@ protected: * @param shape - How the animation progresses, eg. Linear progresses constantly while Exponential start slow and becomes very fast in the end * @param delay - When the animation will start compared to "now" (the window will remain at the "from" position until then) * @param from - the starting value, the default is invalid, ie. the attribute for the window is not transformed in the beginning + * @return an ID that you can use to cancel a running animation */ - void animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve = QEasingCurve(), int delay = 0, FPx2 from = FPx2() ); + quint64 animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve = QEasingCurve(), int delay = 0, FPx2 from = FPx2() ) + { return p_animate(w, a, meta, ms, to, curve, delay, from, false); } + + /** + * Equal to ::animate() with one important difference: + * The target value for the attribute is kept until you ::cancel() this animation + * @return an ID that you need to use to cancel this manipulation + */ + quint64 set( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve = QEasingCurve(), int delay = 0, FPx2 from = FPx2() ) + { return p_animate(w, a, meta, ms, to, curve, delay, from, true); } + /** * Called whenever an animation end, passes the transformed @class EffectWindow @enum Attribute and originally supplied @param meta * You can reimplement it to keep a constant transformation for the window (ie. keep it a this opacity or position) or to start another animation */ virtual void animationEnded( EffectWindow *, Attribute, uint meta ) {Q_UNUSED(meta);} + + /** + * Cancel a running animation. @return true if an animation for @p animationId was found (and canceled) + * NOTICE that there is NO animated reset of the original value. You'll have to provide that with a second animation + * NOTICE as well that this will eventually release a Deleted window. + * If you intend to run another animation on the (Deleted) window, you have to do that before cancelling the old animation (to keep the window around) + */ + bool cancel(quint64 animationId); /** * Called if the transformed @enum Attribute is Generic. You should reimplement it if you transform this "Attribute". * You could use the meta information to eg. support more than one additional animations @@ -170,6 +189,7 @@ protected: {Q_UNUSED(w); Q_UNUSED(data); Q_UNUSED(progress); Q_UNUSED(meta);} private: + quint64 p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget ); QRect clipRect(const QRect &windowRect, const AniData&) const; void clipWindow(const EffectWindow *, const AniData &, WindowQuadList &) const; float interpolated( const AniData&, int i = 0 ) const; diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index 79901ecd59..7aee5568e5 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -170,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 220 +#define KWIN_EFFECT_API_VERSION_MINOR 221 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )