| Index: Source/platform/scroll/ProgrammaticScrollAnimator.cpp
|
| diff --git a/Source/platform/scroll/ProgrammaticScrollAnimator.cpp b/Source/platform/scroll/ProgrammaticScrollAnimator.cpp
|
| index 574018064f1a97aeb528ca6e7a317ae5dec6e2aa..7b2332936a21758aa06070ec8d54633bc147ff9b 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,134 @@ 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) {
|
| + // If the current run state is WaitingToSendToCompositor but we have a
|
| + // non-zero compositor animation id, there's a currently running
|
| + // compositor animation that needs to be removed here before the new
|
| + // animation is added below.
|
| + ASSERT(m_runState == RunState::WaitingToCancelOnCompositor || m_runState == RunState::WaitingToSendToCompositor);
|
| + if (GraphicsLayer* layer = m_scrollableArea->layerForScrolling())
|
| + layer->removeAnimation(m_compositorAnimationId);
|
| + 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
|
|
|