Пример #1
0
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);
}
Пример #2
0
bool ScrollAnimator::willAnimateToOffset(const ScrollOffset& targetOffset) {
  if (m_runState == RunState::PostAnimationCleanup)
    resetAnimationState();

  if (m_runState == RunState::WaitingToCancelOnCompositor ||
      m_runState == RunState::WaitingToCancelOnCompositorButNewScroll) {
    ASSERT(m_animationCurve);
    m_targetOffset = targetOffset;
    if (registerAndScheduleAnimation())
      m_runState = RunState::WaitingToCancelOnCompositorButNewScroll;
    return true;
  }

  if (m_animationCurve) {
    if ((targetOffset - m_targetOffset).isZero())
      return true;

    m_targetOffset = targetOffset;
    ASSERT(m_runState == RunState::RunningOnMainThread ||
           m_runState == RunState::RunningOnCompositor ||
           m_runState == RunState::RunningOnCompositorButNeedsUpdate ||
           m_runState == RunState::RunningOnCompositorButNeedsTakeover);

    // Running on the main thread, simply update the target offset instead
    // of sending to the compositor.
    if (m_runState == RunState::RunningOnMainThread) {
      m_animationCurve->updateTarget(
          m_timeFunction() - m_startTime,
          compositorOffsetFromBlinkOffset(targetOffset));
      return true;
    }

    if (registerAndScheduleAnimation())
      m_runState = RunState::RunningOnCompositorButNeedsUpdate;
    return true;
  }

  if ((targetOffset - currentOffset()).isZero())
    return false;

  m_targetOffset = targetOffset;
  m_startTime = m_timeFunction();

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

  return true;
}
Пример #3
0
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;
    }
  }
}
Пример #4
0
void ScrollAnimator::updateCompositorAnimations() {
  ScrollAnimatorCompositorCoordinator::updateCompositorAnimations();

  if (m_runState == RunState::PostAnimationCleanup) {
    postAnimationCleanupAndReset();
    return;
  }

  if (m_runState == RunState::WaitingToCancelOnCompositor) {
    DCHECK(m_compositorAnimationId);
    abortAnimation();
    postAnimationCleanupAndReset();
    return;
  }

  if (m_runState == RunState::RunningOnCompositorButNeedsTakeover) {
    // The call to ::takeOverCompositorAnimation aborted the animation and
    // put us in this state. The assumption is that takeOver is called
    // because a main thread scrolling reason is added, and simply trying
    // to ::sendAnimationToCompositor will fail and we will run on the main
    // thread.
    resetAnimationIds();
    m_runState = RunState::WaitingToSendToCompositor;
  }

  if (m_runState == RunState::RunningOnCompositorButNeedsUpdate ||
      m_runState == RunState::WaitingToCancelOnCompositorButNewScroll ||
      m_runState == RunState::RunningOnCompositorButNeedsAdjustment) {
    // Abort the running animation before a new one with an updated
    // target is added.
    abortAnimation();
    resetAnimationIds();

    if (m_runState != RunState::RunningOnCompositorButNeedsAdjustment) {
      // When in RunningOnCompositorButNeedsAdjustment, the call to
      // ::adjustScrollOffsetAnimation should have made the necessary
      // adjustment to the curve.
      m_animationCurve->updateTarget(
          m_timeFunction() - m_startTime,
          compositorOffsetFromBlinkOffset(m_targetOffset));
    }

    if (m_runState == RunState::WaitingToCancelOnCompositorButNewScroll) {
      m_animationCurve->setInitialValue(
          compositorOffsetFromBlinkOffset(currentOffset()));
    }

    m_runState = RunState::WaitingToSendToCompositor;
  }

  if (m_runState == RunState::WaitingToSendToCompositor) {
    if (!m_compositorAnimationAttachedToElementId)
      reattachCompositorPlayerIfNeeded(
          getScrollableArea()->compositorAnimationTimeline());

    if (!m_animationCurve)
      createAnimationCurve();

    bool runningOnMainThread = false;
    bool sentToCompositor = sendAnimationToCompositor();
    if (!sentToCompositor) {
      runningOnMainThread = registerAndScheduleAnimation();
      if (runningOnMainThread)
        m_runState = RunState::RunningOnMainThread;
    }

    // Main thread should deal with the scroll animations it started.
    if (sentToCompositor || runningOnMainThread)
      addMainThreadScrollingReason();
    else
      removeMainThreadScrollingReason();
  }
}
Пример #5
0
void ScrollAnimator::updateCompositorAnimations()
{
    if (m_compositorAnimationId && m_runState != RunState::RunningOnCompositor
        && m_runState != RunState::RunningOnCompositorButNeedsUpdate) {
        // 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);

        abortAnimation();

        m_compositorAnimationId = 0;
        m_compositorAnimationGroupId = 0;
        if (m_runState == RunState::WaitingToCancelOnCompositor) {
            resetAnimationState();
            return;
        }
    }

    if (m_runState == RunState::WaitingToSendToCompositor
        || m_runState == RunState::RunningOnCompositorButNeedsUpdate) {
        if (m_runState == RunState::RunningOnCompositorButNeedsUpdate) {
            // Abort the running animation before a new one with an updated
            // target is added.
            abortAnimation();

            m_compositorAnimationId = 0;
            m_compositorAnimationGroupId = 0;

            m_animationCurve->updateTarget(m_timeFunction() - m_startTime,
                m_targetOffset);
            m_runState = RunState::WaitingToSendToCompositor;
        }

        if (!m_animationCurve) {
            m_animationCurve = adoptPtr(Platform::current()->compositorSupport()
                ->createScrollOffsetAnimationCurve(
                    m_targetOffset,
                    WebCompositorAnimationCurve::TimingFunctionTypeEaseInOut,
                    m_lastGranularity == ScrollByPixel ?
                        WebScrollOffsetAnimationCurve::ScrollDurationInverseDelta :
                        WebScrollOffsetAnimationCurve::ScrollDurationConstant));
            m_animationCurve->setInitialValue(currentPosition());
        }

        bool sentToCompositor = false;
        if (!m_scrollableArea->shouldScrollOnMainThread()) {
            OwnPtr<WebCompositorAnimation> animation = adoptPtr(
                Platform::current()->compositorSupport()->createAnimation(
                    *m_animationCurve,
                    WebCompositorAnimation::TargetPropertyScrollOffset));
            // Being here means that either there is an animation that needs
            // to be sent to the compositor, or an animation that needs to
            // be updated (a new scroll event before the previous animation
            // is finished). In either case, the start time is when the
            // first animation was initiated. This re-targets the animation
            // using the current time on main thread.
            animation->setStartTime(m_startTime);

            int animationId = animation->id();
            int animationGroupId = animation->group();

            sentToCompositor = addAnimation(animation.release());
            if (sentToCompositor) {
                m_runState = RunState::RunningOnCompositor;
                m_compositorAnimationId = animationId;
                m_compositorAnimationGroupId = animationGroupId;
            }
        }

        if (!sentToCompositor) {
            if (registerAndScheduleAnimation())
                m_runState = RunState::RunningOnMainThread;
        }
    }
}