ScrollResult ScrollAnimatorBase::userScroll(ScrollGranularity, const ScrollOffset& delta) { ScrollOffset consumedDelta = computeDeltaToConsume(delta); ScrollOffset newPos = m_currentOffset + consumedDelta; if (m_currentOffset == newPos) return ScrollResult(false, false, delta.width(), delta.height()); m_currentOffset = newPos; notifyOffsetChanged(); return ScrollResult(consumedDelta.width(), consumedDelta.height(), delta.width() - consumedDelta.width(), delta.height() - consumedDelta.height()); }
ScrollResult ScrollAnimatorBase::userScroll(ScrollGranularity, const FloatSize& delta) { FloatSize consumedDelta = computeDeltaToConsume(delta); FloatPoint newPos = m_currentPos + consumedDelta; if (m_currentPos == newPos) return ScrollResult(false, false, delta.width(), delta.height()); m_currentPos = newPos; notifyPositionChanged(); return ScrollResult( consumedDelta.width(), consumedDelta.height(), delta.width() - consumedDelta.width(), delta.height() - consumedDelta.height()); }
ScrollResult ScrollableArea::handleWheel(const PlatformWheelEvent& wheelEvent) { // Wheel events which do not scroll are used to trigger zooming. if (!wheelEvent.canScroll()) return ScrollResult(); cancelProgrammaticScrollAnimation(); return scrollAnimator()->handleWheelEvent(wheelEvent); }
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()); }
ScrollResult RootFrameViewport::handleWheel(const PlatformWheelEvent& event) { updateScrollAnimator(); ScrollableArea& primary = !m_invertScrollOrder ? layoutViewport() : visualViewport(); ScrollableArea& secondary = !m_invertScrollOrder ? visualViewport() : layoutViewport(); ScrollResult viewScrollResult = primary.handleWheel(event); // The visual viewport will only accept pixel scrolls. if (!event.canScroll() || event.granularity() == ScrollByPageWheelEvent) return viewScrollResult; // TODO(sataya.m) : The delta in PlatformWheelEvent is negative when scrolling the // wheel towards the user, so negate it to get the scroll delta that should be applied // to the page. unusedScrollDelta computed in the ScrollResult is also negative. Say // there is WheelEvent({0, -10} and page scroll by 2px and unusedScrollDelta computed // is {0, -8}. Due to which we have to negate the unusedScrollDelta to obtain the expected // animation.Please address http://crbug.com/504389. DoublePoint oldOffset = secondary.scrollPositionDouble(); DoublePoint locationDelta; if (viewScrollResult.didScroll()) { locationDelta = -DoublePoint(viewScrollResult.unusedScrollDeltaX, viewScrollResult.unusedScrollDeltaY); } else { if (event.railsMode() != PlatformEvent::RailsModeVertical) locationDelta.setX(-event.deltaX()); if (event.railsMode() != PlatformEvent::RailsModeHorizontal) locationDelta.setY(-event.deltaY()); } DoublePoint targetPosition = secondary.clampScrollPosition( secondary.scrollPositionDouble() + toDoubleSize(locationDelta)); secondary.setScrollPosition(targetPosition, UserScroll); DoublePoint usedLocationDelta(secondary.scrollPositionDouble() - oldOffset); bool didScrollX = viewScrollResult.didScrollX || usedLocationDelta.x(); bool didScrollY = viewScrollResult.didScrollY || usedLocationDelta.y(); return ScrollResult(didScrollX, didScrollY, -viewScrollResult.unusedScrollDeltaX - usedLocationDelta.x(), -viewScrollResult.unusedScrollDeltaY - usedLocationDelta.y()); }
ScrollResult RootFrameViewport::userScroll(ScrollGranularity granularity, const FloatSize& delta) { // TODO(bokan/ymalik): Once smooth scrolling is permanently enabled we // should be able to remove this method override and use the base class // version: ScrollableArea::userScroll. updateScrollAnimator(); // Distribute the scroll between the visual and layout viewport. float stepX = scrollStep(granularity, HorizontalScrollbar); float stepY = scrollStep(granularity, VerticalScrollbar); FloatSize pixelDelta(delta); pixelDelta.scale(stepX, stepY); // Precompute the amount of possible scrolling since, when animated, // ScrollAnimator::userScroll will report having consumed the total given // scroll delta, regardless of how much will actually scroll, but we need to // know how much to leave for the layout viewport. FloatSize visualConsumedDelta = visualViewport().scrollAnimator().computeDeltaToConsume(pixelDelta); // Split the remaining delta between scrollable and unscrollable axes of the // layout viewport. We only pass a delta to the scrollable axes and remember // how much was held back so we can add it to the unused delta in the // result. FloatSize layoutDelta = pixelDelta - visualConsumedDelta; FloatSize scrollableAxisDelta( layoutViewport().userInputScrollable(HorizontalScrollbar) ? layoutDelta.width() : 0, layoutViewport().userInputScrollable(VerticalScrollbar) ? layoutDelta.height() : 0); // If there won't be any scrolling, bail early so we don't produce any side // effects like cancelling existing animations. if (visualConsumedDelta.isZero() && scrollableAxisDelta.isZero()) { return ScrollResult(false, false, pixelDelta.width(), pixelDelta.height()); } cancelProgrammaticScrollAnimation(); // TODO(bokan): Why do we call userScroll on the animators directly and // not through the ScrollableAreas? ScrollResult visualResult = visualViewport().scrollAnimator().userScroll( granularity, visualConsumedDelta); if (visualConsumedDelta == pixelDelta) return visualResult; ScrollResult layoutResult = layoutViewport().scrollAnimator().userScroll( granularity, scrollableAxisDelta); // Remember to add any delta not used because of !userInputScrollable to the // unusedScrollDelta in the result. FloatSize unscrollableAxisDelta = layoutDelta - scrollableAxisDelta; return ScrollResult( visualResult.didScrollX || layoutResult.didScrollX, visualResult.didScrollY || layoutResult.didScrollY, layoutResult.unusedScrollDeltaX + unscrollableAxisDelta.width(), layoutResult.unusedScrollDeltaY + unscrollableAxisDelta.height()); }