void ScrollAnimator::adjustAnimationAndSetScrollOffset( const ScrollOffset& offset, ScrollType scrollType) { IntSize adjustment = roundedIntSize(offset) - roundedIntSize(m_scrollableArea->scrollOffset()); scrollOffsetChanged(offset, scrollType); if (m_runState == RunState::Idle) { adjustImplOnlyScrollOffsetAnimation(adjustment); } else if (hasRunningAnimation()) { m_targetOffset += ScrollOffset(adjustment); if (m_animationCurve) { m_animationCurve->applyAdjustment(adjustment); if (m_runState != RunState::RunningOnMainThread && registerAndScheduleAnimation()) m_runState = RunState::RunningOnCompositorButNeedsAdjustment; } } }
void ScrollAnimator::notifyAnimationTakeover( double monotonicTime, double animationStartTime, std::unique_ptr<cc::AnimationCurve> curve) { // If there is already an animation running and the compositor asks to take // over an animation, do nothing to avoid judder. if (hasRunningAnimation()) return; cc::ScrollOffsetAnimationCurve* scrollOffsetAnimationCurve = curve->ToScrollOffsetAnimationCurve(); ScrollOffset targetValue(scrollOffsetAnimationCurve->target_value().x(), scrollOffsetAnimationCurve->target_value().y()); if (willAnimateToOffset(targetValue)) { m_animationCurve = CompositorScrollOffsetAnimationCurve::create( std::move(scrollOffsetAnimationCurve)); m_startTime = animationStartTime; } }
ScrollResult ScrollAnimator::userScroll(ScrollGranularity granularity, const ScrollOffset& delta) { if (!m_scrollableArea->scrollAnimatorEnabled()) return ScrollAnimatorBase::userScroll(granularity, delta); TRACE_EVENT0("blink", "ScrollAnimator::scroll"); if (granularity == ScrollByPrecisePixel) { // Cancel scroll animation because asked to instant scroll. if (hasRunningAnimation()) cancelAnimation(); return ScrollAnimatorBase::userScroll(granularity, delta); } bool needsPostAnimationCleanup = m_runState == RunState::PostAnimationCleanup; if (m_runState == RunState::PostAnimationCleanup) resetAnimationState(); ScrollOffset consumedDelta = computeDeltaToConsume(delta); ScrollOffset targetOffset = desiredTargetOffset(); targetOffset += consumedDelta; if (willAnimateToOffset(targetOffset)) { m_lastGranularity = granularity; // Report unused delta only if there is no animation running. See // comment below regarding scroll latching. // TODO(bokan): Need to standardize how ScrollAnimators report // unusedDelta. This differs from ScrollAnimatorMac currently. return ScrollResult(true, true, 0, 0); } // If the run state when this method was called was PostAnimationCleanup and // we're not starting an animation, stay in PostAnimationCleanup state so // that the main thread scrolling reason can be removed. if (needsPostAnimationCleanup) m_runState = RunState::PostAnimationCleanup; // Report unused delta only if there is no animation and we are not // starting one. This ensures we latch for the duration of the // animation rather than animating multiple scrollers at the same time. return ScrollResult(false, false, delta.width(), delta.height()); }
ScrollResultOneDimensional ScrollAnimator::userScroll( ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float delta) { if (!m_scrollableArea->scrollAnimatorEnabled()) return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); TRACE_EVENT0("blink", "ScrollAnimator::scroll"); if (granularity == ScrollByPrecisePixel) { if (hasRunningAnimation()) { abortAnimation(); resetAnimationState(); } return ScrollAnimatorBase::userScroll(orientation, granularity, step, delta); } float usedPixelDelta = computeDeltaToConsume(orientation, step * delta); FloatPoint pixelDelta = (orientation == VerticalScrollbar ? FloatPoint(0, usedPixelDelta) : FloatPoint(usedPixelDelta, 0)); FloatPoint targetPos = desiredTargetPosition(); targetPos.moveBy(pixelDelta); if (m_animationCurve) { if ((targetPos - m_targetOffset).isZero()) { // Report unused delta only if there is no animation running. See // comment below regarding scroll latching. return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } m_targetOffset = targetPos; ASSERT(m_runState == RunState::RunningOnMainThread || m_runState == RunState::RunningOnCompositor || m_runState == RunState::RunningOnCompositorButNeedsUpdate); if (m_runState == RunState::RunningOnCompositor || m_runState == RunState::RunningOnCompositorButNeedsUpdate) { if (registerAndScheduleAnimation()) m_runState = RunState::RunningOnCompositorButNeedsUpdate; return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } // Running on the main thread, simply update the target offset instead // of sending to the compositor. m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos); return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); } if ((targetPos - currentPosition()).isZero()) { // Report unused delta only if there is no animation and we are not // starting one. This ensures we latch for the duration of the // animation rather than animating multiple scrollers at the same time. return ScrollResultOneDimensional(/* didScroll */ false, delta); } m_targetOffset = targetPos; m_startTime = m_timeFunction(); m_lastGranularity = granularity; if (registerAndScheduleAnimation()) m_runState = RunState::WaitingToSendToCompositor; return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); }