示例#1
0
float ScrollAnimator::computeDeltaToConsume(
    ScrollbarOrientation orientation, float pixelDelta) const
{
    FloatPoint pos = desiredTargetPosition();
    float currentPos = (orientation == HorizontalScrollbar) ? pos.x() : pos.y();
    float newPos = clampScrollPosition(orientation, currentPos + pixelDelta);
    return (currentPos == newPos) ? 0.0f : (newPos - currentPos);
}
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)
        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();

    if (registerAndScheduleAnimation())
        m_runState = RunState::WaitingToSendToCompositor;

    return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0);
}