diff --git a/autotests/integration/effects/scripted_effects_test.cpp b/autotests/integration/effects/scripted_effects_test.cpp --- a/autotests/integration/effects/scripted_effects_test.cpp +++ b/autotests/integration/effects/scripted_effects_test.cpp @@ -49,6 +49,8 @@ #include using namespace KWin; +using namespace std::chrono_literals; + static const QString s_socketName = QStringLiteral("wayland_test_effects_scripts-0"); class ScriptedEffectsTest : public QObject @@ -289,25 +291,20 @@ QVERIFY(c); QCOMPARE(workspace()->activeClient(), c); - // we are running the event loop during renderAndWaitForShown - // some time will pass with the event loop running between the window being added and getting to here - // anim.duration is an aboslute value, but retarget will update the duration based on time passed - int timePassed = 0; - { const AnimationEffect::AniMap state = effect->state(); QCOMPARE(state.count(), 1); QCOMPARE(state.firstKey(), c->effectWindow()); const auto &animationsForWindow = state.first().first; QCOMPARE(animationsForWindow.count(), animationCount); - QCOMPARE(animationsForWindow[0].duration, 100); + QCOMPARE(animationsForWindow[0].timeLine.duration(), 100ms); QCOMPARE(animationsForWindow[0].to, FPx2(1.4)); QCOMPARE(animationsForWindow[0].attribute, AnimationEffect::Scale); - QCOMPARE(animationsForWindow[0].curve.type(), QEasingCurve::OutQuad); + QCOMPARE(animationsForWindow[0].timeLine.easingCurve().type(), QEasingCurve::OutQuad); QCOMPARE(animationsForWindow[0].keepAtTarget, false); - timePassed = animationsForWindow[0].time; + if (animationCount == 2) { - QCOMPARE(animationsForWindow[1].duration, 100); + QCOMPARE(animationsForWindow[1].timeLine.duration(), 100ms); QCOMPARE(animationsForWindow[1].to, FPx2(0.0)); QCOMPARE(animationsForWindow[1].attribute, AnimationEffect::Opacity); QCOMPARE(animationsForWindow[1].keepAtTarget, false); @@ -323,12 +320,12 @@ QCOMPARE(state.count(), 1); const auto &animationsForWindow = state.first().first; QCOMPARE(animationsForWindow.count(), animationCount); - QCOMPARE(animationsForWindow[0].duration, 200 + timePassed); + QCOMPARE(animationsForWindow[0].timeLine.duration(), 200ms); QCOMPARE(animationsForWindow[0].to, FPx2(1.5)); QCOMPARE(animationsForWindow[0].attribute, AnimationEffect::Scale); QCOMPARE(animationsForWindow[0].keepAtTarget, false); if (animationCount == 2) { - QCOMPARE(animationsForWindow[1].duration, 200 + timePassed); + QCOMPARE(animationsForWindow[1].timeLine.duration(), 200ms); QCOMPARE(animationsForWindow[1].to, FPx2(1.5)); QCOMPARE(animationsForWindow[1].attribute, AnimationEffect::Opacity); QCOMPARE(animationsForWindow[1].keepAtTarget, false); diff --git a/libkwineffects/anidata.cpp b/libkwineffects/anidata.cpp --- a/libkwineffects/anidata.cpp +++ b/libkwineffects/anidata.cpp @@ -70,26 +70,21 @@ AniData::AniData() : attribute(AnimationEffect::Opacity) , customCurve(0) // Linear - , time(0) - , duration(0) , meta(0) , startTime(0) , waitAtSource(false) , keepAtTarget(false) , keepAlive(true) { } -AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to_, - QEasingCurve curve_, int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_, +AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_, + int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_, FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive, PreviousWindowPixmapLockPtr previousWindowPixmapLock_) : attribute(a) - , curve(curve_) , from(from_) , to(to_) - , time(0) - , duration(ms) , meta(meta_) , startTime(AnimationEffect::clock() + delay) , fullScreenEffectLock(fullScreenEffectLock_) @@ -122,6 +117,6 @@ QLatin1String("\n From: ") + from.toString() + QLatin1String("\n To: ") + to.toString() + QLatin1String("\n Started: ") + QString::number(AnimationEffect::clock() - startTime) + QLatin1String("ms ago\n") + - QLatin1String( " Duration: ") + QString::number(duration) + QLatin1String("ms\n") + - QLatin1String( " Passed: ") + QString::number(time) + QLatin1String("ms\n"); + QLatin1String( " Duration: ") + QString::number(timeLine.duration().count()) + QLatin1String("ms\n") + + QLatin1String( " Passed: ") + QString::number(timeLine.elapsed().count()) + QLatin1String("ms\n"); } diff --git a/libkwineffects/anidata_p.h b/libkwineffects/anidata_p.h --- a/libkwineffects/anidata_p.h +++ b/libkwineffects/anidata_p.h @@ -74,22 +74,21 @@ class KWINEFFECTS_EXPORT AniData { public: AniData(); - AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, - QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, + AniData(AnimationEffect::Attribute a, int meta, const FPx2 &to, + int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget = false, FullScreenEffectLockPtr=FullScreenEffectLockPtr(), bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {}); - inline void addTime(int t) { time += t; } + inline bool isOneDimensional() const { return from[0] == from[1] && to[0] == to[1]; } quint64 id{0}; QString debugInfo() const; AnimationEffect::Attribute attribute; - QEasingCurve curve; int customCurve; FPx2 from, to; - int time, duration; + TimeLine timeLine; uint meta; qint64 startTime; QSharedPointer fullScreenEffectLock; diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -254,9 +254,7 @@ it->first.append(AniData( a, // Attribute meta, // Metadata - ms, // Duration to, // Target - curve, // Easing curve delay, // Delay from, // Source waitAtSource, // Whether the animation should be kept at source @@ -266,8 +264,16 @@ previousPixmap // Previous window pixmap lock )); - quint64 ret_id = ++d->m_animCounter; - it->first.last().id = ret_id; + const quint64 ret_id = ++d->m_animCounter; + AniData &animation = it->first.last(); + animation.id = ret_id; + + animation.timeLine.setDirection(TimeLine::Forward); + animation.timeLine.setDuration(std::chrono::milliseconds(ms)); + animation.timeLine.setEasingCurve(curve); + animation.timeLine.setSourceRedirectMode(TimeLine::RedirectMode::Strict); + animation.timeLine.setTargetRedirectMode(TimeLine::RedirectMode::Relaxed); + it->second = QRect(); d->m_animationsTouched = true; @@ -297,7 +303,11 @@ anim->from.set(interpolated(*anim, 0), interpolated(*anim, 1)); validate(anim->attribute, anim->meta, nullptr, &newTarget, entry.key()); anim->to.set(newTarget[0], newTarget[1]); - anim->duration = anim->time + newRemainingTime; + + anim->timeLine.setDirection(TimeLine::Forward); + anim->timeLine.setDuration(std::chrono::milliseconds(newRemainingTime)); + anim->timeLine.reset(); + return true; } } @@ -351,10 +361,10 @@ continue; } } else { - anim->addTime(time); + anim->timeLine.update(std::chrono::milliseconds(time)); } - if (anim->time < anim->duration || anim->keepAtTarget) { + if (!anim->timeLine.done() || anim->keepAtTarget) { // if (anim->attribute != Brightness && anim->attribute != Saturation && anim->attribute != Opacity) // transformed = true; d->m_animated = true; @@ -671,7 +681,7 @@ for (; anim != it->first.constEnd(); ++anim) { if (anim->startTime > clock()) continue; - if (anim->time < anim->duration) { + if (!anim->timeLine.done()) { addRepaint = true; break; } @@ -689,18 +699,14 @@ { if (a.startTime > clock()) return 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]); + if (!a.timeLine.done()) + return a.from[i] + a.timeLine.value() * (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; - 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 + return a.startTime < clock() ? a.timeLine.value() : 0.0; } @@ -782,7 +788,7 @@ static float fixOvershoot(float f, const AniData &d, short int dir, float s = 1.1) { - switch(d.curve.type()) { + switch(d.timeLine.easingCurve().type()) { case QEasingCurve::InOutElastic: case QEasingCurve::InOutBack: return f * s;