Chromium Code Reviews| Index: Source/platform/scroll/ProgrammaticScrollAnimator.cpp |
| diff --git a/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/Source/platform/scroll/ProgrammaticScrollAnimator.cpp |
| index 574018064f1a97aeb528ca6e7a317ae5dec6e2aa..71ae1d49ed58fd5c61966feecbeed941cca3df7d 100644 |
| --- a/Source/platform/scroll/ProgrammaticScrollAnimator.cpp |
| +++ b/Source/platform/scroll/ProgrammaticScrollAnimator.cpp |
| @@ -6,8 +6,10 @@ |
| #include "platform/scroll/ProgrammaticScrollAnimator.h" |
| #include "platform/geometry/IntPoint.h" |
| +#include "platform/graphics/GraphicsLayer.h" |
| #include "platform/scroll/ScrollableArea.h" |
| #include "public/platform/Platform.h" |
| +#include "public/platform/WebCompositorAnimation.h" |
| #include "public/platform/WebCompositorSupport.h" |
| #include "public/platform/WebScrollOffsetAnimationCurve.h" |
| @@ -21,6 +23,9 @@ PassOwnPtr<ProgrammaticScrollAnimator> ProgrammaticScrollAnimator::create(Scroll |
| ProgrammaticScrollAnimator::ProgrammaticScrollAnimator(ScrollableArea* scrollableArea) |
| : m_scrollableArea(scrollableArea) |
| , m_startTime(0.0) |
| + , m_runState(RunState::Idle) |
| + , m_compositorAnimationId(0) |
| + , m_compositorAnimationGroupId(0) |
| { |
| } |
| @@ -32,6 +37,9 @@ void ProgrammaticScrollAnimator::resetAnimationState() |
| { |
| m_animationCurve.clear(); |
| m_startTime = 0.0; |
| + m_runState = RunState::Idle; |
| + m_compositorAnimationId = 0; |
| + m_compositorAnimationGroupId = 0; |
| } |
| void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset) |
| @@ -46,35 +54,130 @@ void ProgrammaticScrollAnimator::animateToOffset(FloatPoint offset) |
| resetAnimationState(); |
| m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y())); |
| } |
| + m_runState = RunState::WaitingToSendToCompositor; |
| } |
| void ProgrammaticScrollAnimator::cancelAnimation() |
| { |
| - resetAnimationState(); |
| + switch (m_runState) { |
| + case RunState::Idle: |
| + case RunState::WaitingToCancelOnCompositor: |
| + break; |
| + case RunState::WaitingToSendToCompositor: |
| + if (m_compositorAnimationId) { |
| + // We still have a previous animation running on the compositor. |
| + m_runState = RunState::WaitingToCancelOnCompositor; |
| + } else { |
| + resetAnimationState(); |
| + } |
| + break; |
| + case RunState::RunningOnMainThread: |
| + resetAnimationState(); |
| + break; |
| + case RunState::RunningOnCompositor: |
| + m_runState = RunState::WaitingToCancelOnCompositor; |
| + |
| + // Get serviced the next time compositor updates are allowed. |
| + m_scrollableArea->registerForAnimation(); |
| + } |
| } |
| void ProgrammaticScrollAnimator::tickAnimation(double monotonicTime) |
| { |
| - if (m_animationCurve) { |
| - if (!m_startTime) |
| - m_startTime = monotonicTime; |
| - double elapsedTime = monotonicTime - m_startTime; |
| - bool isFinished = (elapsedTime > m_animationCurve->duration()); |
| - FloatPoint offset = m_animationCurve->getValue(elapsedTime); |
| - m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y())); |
| + if (m_runState != RunState::RunningOnMainThread) |
| + return; |
| - if (isFinished) { |
| - resetAnimationState(); |
| - } else if (!m_scrollableArea->scheduleAnimation()) { |
| - m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y())); |
| + if (!m_startTime) |
| + m_startTime = monotonicTime; |
| + double elapsedTime = monotonicTime - m_startTime; |
| + bool isFinished = (elapsedTime > m_animationCurve->duration()); |
| + FloatPoint offset = m_animationCurve->getValue(elapsedTime); |
| + m_scrollableArea->notifyScrollPositionChanged(IntPoint(offset.x(), offset.y())); |
| + |
| + if (isFinished) { |
| + resetAnimationState(); |
| + } else if (!m_scrollableArea->scheduleAnimation()) { |
| + m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y())); |
| + resetAnimationState(); |
| + } |
| +} |
| + |
| +bool ProgrammaticScrollAnimator::hasAnimationThatRequiresService() const |
| +{ |
| + switch (m_runState) { |
| + case RunState::Idle: |
| + case RunState::RunningOnCompositor: |
| + return false; |
| + case RunState::WaitingToSendToCompositor: |
| + case RunState::RunningOnMainThread: |
| + case RunState::WaitingToCancelOnCompositor: |
| + return true; |
| + } |
| + ASSERT_NOT_REACHED(); |
| + return false; |
| +} |
| + |
| +void ProgrammaticScrollAnimator::updateCompositorAnimations() |
| +{ |
| + if (m_compositorAnimationId && m_runState != RunState::RunningOnCompositor) { |
| + ASSERT(m_runState == RunState::WaitingToCancelOnCompositor || m_runState == RunState::WaitingToSendToCompositor); |
| + if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling()) |
| + layer->removeAnimation(m_compositorAnimationId); |
|
Ian Vollick
2015/01/17 15:17:41
It took me a moment to realize that removing here
ajuma
2015/01/19 14:22:34
Done.
|
| + m_compositorAnimationId = 0; |
| + m_compositorAnimationGroupId = 0; |
| + if (m_runState == RunState::WaitingToCancelOnCompositor) { |
| resetAnimationState(); |
| + return; |
| + } |
| + } |
| + |
| + if (m_runState == RunState::WaitingToSendToCompositor) { |
| + bool sentToCompositor = false; |
| + |
| + if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling()) { |
| + if (!layer->platformLayer()->shouldScrollOnMainThread()) { |
| + OwnPtr<WebCompositorAnimation> animation = adoptPtr(Platform::current()->compositorSupport()->createAnimation(*m_animationCurve, WebCompositorAnimation::TargetPropertyScrollOffset)); |
| + |
| + int animationId = animation->id(); |
| + int animationGroupId = animation->group(); |
| + if (m_scrollableArea->layerForScrolling()->addAnimation(animation.release())) { |
| + sentToCompositor = true; |
| + m_runState = RunState::RunningOnCompositor; |
| + m_compositorAnimationId = animationId; |
| + m_compositorAnimationGroupId = animationGroupId; |
| + } |
| + } |
| + } |
| + |
| + if (!sentToCompositor) { |
| + m_runState = RunState::RunningOnMainThread; |
| + if (!m_scrollableArea->scheduleAnimation()) { |
| + m_scrollableArea->notifyScrollPositionChanged(IntPoint(m_targetOffset.x(), m_targetOffset.y())); |
| + resetAnimationState(); |
| + } |
| } |
| } |
| } |
| -bool ProgrammaticScrollAnimator::hasRunningAnimation() const |
| +void ProgrammaticScrollAnimator::notifyCompositorAnimationFinished(int groupId) |
| { |
| - return !!m_animationCurve; |
| + if (m_compositorAnimationGroupId != groupId) |
| + return; |
| + |
| + m_compositorAnimationId = 0; |
| + m_compositorAnimationGroupId = 0; |
| + |
| + switch (m_runState) { |
| + case RunState::Idle: |
| + case RunState::RunningOnMainThread: |
| + ASSERT_NOT_REACHED(); |
| + break; |
| + case RunState::WaitingToSendToCompositor: |
| + break; |
| + case RunState::RunningOnCompositor: |
| + case RunState::WaitingToCancelOnCompositor: |
| + resetAnimationState(); |
| + } |
| } |
| } // namespace blink |