Title: [283335] trunk/Source/WebCore
Revision
283335
Author
simon.fra...@apple.com
Date
2021-09-30 13:58:03 -0700 (Thu, 30 Sep 2021)

Log Message

Replace the confusing isPinnedForScrollDelta() logic with code that uses BoxSide
https://bugs.webkit.org/show_bug.cgi?id=231004

Reviewed by Tim Horton.

isPinnedForScrollDelta()/isPinnedForScrollDeltaOnAxis() are ambiguous because it's
easy to interpret them as looking at the magnitude of the delta to determine whether
the delta will cause stretching on an edge. However, they don't do this; they simply
use the delta to choose which edge to look at, and the "is pinned" refers to whether
the scroller is already scrolled to that edge or stretching at that edge.

To reduce ambiguity, rewrite the code in terms of BoxSides, separating the code
that determines which BoxSide to look at for a given event delta from the code that
computed pinned state. It's now clearer that it's the caller's responsibility to
do "dominant axis" delta transformations too.

* page/EventHandler.cpp:
(WebCore::EventHandler::scrollableAreaCanHandleEvent):
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::mainFrameCanRubberBandOnSide):
(WebCore::ScrollingTree::mainFrameCanRubberBandInDirection): Deleted.
* page/scrolling/ScrollingTree.h:
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
(WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsHorizontalStretching const):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsVerticalStretching const):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedOnSide const): Remove the old "scrollOffsetLimit" threshold. Our scroll offsets
are currently all integral so I don't think this did anything.
(WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandOnSide const):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDeltaOnAxis const): Deleted.
(WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDelta const): Deleted.
(WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandInDirection const): Deleted.
* platform/ScrollAnimator.cpp:
(WebCore::ScrollAnimator::isPinnedOnSide const):
(WebCore::ScrollAnimator::isPinnedForScrollDelta const): Deleted.
* platform/ScrollAnimator.h:
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::isPinnedOnSide const):
(WebCore::ScrollableArea::targetSideForScrollDelta):
(WebCore::ScrollableArea::isPinnedForScrollDeltaOnAxis const): Deleted.
(WebCore::ScrollableArea::isPinnedForScrollDelta const): Deleted.
* platform/ScrollableArea.h:
* platform/ScrollingEffectsController.h:
* platform/ios/ScrollAnimatorIOS.mm:
(WebCore::ScrollAnimatorIOS::determineScrollableAreaForTouchSequence):
* platform/mac/ScrollAnimatorMac.h:
* platform/mac/ScrollAnimatorMac.mm:
(WebCore::ScrollAnimatorMac::allowsVerticalStretching const):
(WebCore::ScrollAnimatorMac::allowsHorizontalStretching const):
(WebCore::ScrollAnimatorMac::shouldRubberBandOnSide const):
(WebCore::ScrollAnimatorMac::shouldRubberBandInDirection const): Deleted.
* platform/mac/ScrollingEffectsController.mm:
(WebCore::dominantAxisFavoringVertical):
(WebCore::deltaAlignedToAxis):
(WebCore::deltaAlignedToDominantAxis):
(WebCore::affectedSideOnDominantAxis):
(WebCore::isHorizontalSide):
(WebCore::isVerticalSide):
(WebCore::ScrollingEffectsController::handleWheelEvent):
(WebCore::ScrollingEffectsController::wheelDeltaBiasingTowardsVertical):
(WebCore::ScrollingEffectsController::shouldRubberBandOnSide const):
(WebCore::convertToProminentAxisFavoringVertical): Deleted.
(WebCore::ScrollingEffectsController::directionFromEvent): Deleted.
(WebCore::ScrollingEffectsController::shouldRubberBandInHorizontalDirection const): Deleted.
(WebCore::ScrollingEffectsController::shouldRubberBandInDirection const): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (283334 => 283335)


--- trunk/Source/WebCore/ChangeLog	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/ChangeLog	2021-09-30 20:58:03 UTC (rev 283335)
@@ -1,3 +1,71 @@
+2021-09-29  Simon Fraser  <simon.fra...@apple.com>
+
+        Replace the confusing isPinnedForScrollDelta() logic with code that uses BoxSide
+        https://bugs.webkit.org/show_bug.cgi?id=231004
+
+        Reviewed by Tim Horton.
+
+        isPinnedForScrollDelta()/isPinnedForScrollDeltaOnAxis() are ambiguous because it's
+        easy to interpret them as looking at the magnitude of the delta to determine whether
+        the delta will cause stretching on an edge. However, they don't do this; they simply
+        use the delta to choose which edge to look at, and the "is pinned" refers to whether
+        the scroller is already scrolled to that edge or stretching at that edge.
+
+        To reduce ambiguity, rewrite the code in terms of BoxSides, separating the code
+        that determines which BoxSide to look at for a given event delta from the code that
+        computed pinned state. It's now clearer that it's the caller's responsibility to
+        do "dominant axis" delta transformations too.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::scrollableAreaCanHandleEvent):
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::mainFrameCanRubberBandOnSide):
+        (WebCore::ScrollingTree::mainFrameCanRubberBandInDirection): Deleted.
+        * page/scrolling/ScrollingTree.h:
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsHorizontalStretching const):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsVerticalStretching const):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedOnSide const): Remove the old "scrollOffsetLimit" threshold. Our scroll offsets
+        are currently all integral so I don't think this did anything.
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandOnSide const):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDeltaOnAxis const): Deleted.
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDelta const): Deleted.
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandInDirection const): Deleted.
+        * platform/ScrollAnimator.cpp:
+        (WebCore::ScrollAnimator::isPinnedOnSide const):
+        (WebCore::ScrollAnimator::isPinnedForScrollDelta const): Deleted.
+        * platform/ScrollAnimator.h:
+        * platform/ScrollableArea.cpp:
+        (WebCore::ScrollableArea::isPinnedOnSide const):
+        (WebCore::ScrollableArea::targetSideForScrollDelta):
+        (WebCore::ScrollableArea::isPinnedForScrollDeltaOnAxis const): Deleted.
+        (WebCore::ScrollableArea::isPinnedForScrollDelta const): Deleted.
+        * platform/ScrollableArea.h:
+        * platform/ScrollingEffectsController.h:
+        * platform/ios/ScrollAnimatorIOS.mm:
+        (WebCore::ScrollAnimatorIOS::determineScrollableAreaForTouchSequence):
+        * platform/mac/ScrollAnimatorMac.h:
+        * platform/mac/ScrollAnimatorMac.mm:
+        (WebCore::ScrollAnimatorMac::allowsVerticalStretching const):
+        (WebCore::ScrollAnimatorMac::allowsHorizontalStretching const):
+        (WebCore::ScrollAnimatorMac::shouldRubberBandOnSide const):
+        (WebCore::ScrollAnimatorMac::shouldRubberBandInDirection const): Deleted.
+        * platform/mac/ScrollingEffectsController.mm:
+        (WebCore::dominantAxisFavoringVertical):
+        (WebCore::deltaAlignedToAxis):
+        (WebCore::deltaAlignedToDominantAxis):
+        (WebCore::affectedSideOnDominantAxis):
+        (WebCore::isHorizontalSide):
+        (WebCore::isVerticalSide):
+        (WebCore::ScrollingEffectsController::handleWheelEvent):
+        (WebCore::ScrollingEffectsController::wheelDeltaBiasingTowardsVertical):
+        (WebCore::ScrollingEffectsController::shouldRubberBandOnSide const):
+        (WebCore::convertToProminentAxisFavoringVertical): Deleted.
+        (WebCore::ScrollingEffectsController::directionFromEvent): Deleted.
+        (WebCore::ScrollingEffectsController::shouldRubberBandInHorizontalDirection const): Deleted.
+        (WebCore::ScrollingEffectsController::shouldRubberBandInDirection const): Deleted.
+
 2021-09-30  Devin Rousso  <drou...@apple.com>
 
         [GPU Process] support rendering Apple Pay buttons

Modified: trunk/Source/WebCore/page/EventHandler.cpp (283334 => 283335)


--- trunk/Source/WebCore/page/EventHandler.cpp	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2021-09-30 20:58:03 UTC (rev 283335)
@@ -98,6 +98,7 @@
 #include "ScrollAnimator.h"
 #include "ScrollLatchingController.h"
 #include "Scrollbar.h"
+#include "ScrollingEffectsController.h"
 #include "SelectionRestorationMode.h"
 #include "Settings.h"
 #include "ShadowRoot.h"
@@ -3103,10 +3104,12 @@
     auto biasedDelta = wheelEvent.delta();
 #endif
 
-    if (biasedDelta.height() && !scrollableArea.isPinnedForScrollDeltaOnAxis(-biasedDelta.height(), ScrollEventAxis::Vertical))
+    auto verticalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Vertical);
+    if (verticalSide && !scrollableArea.isPinnedOnSide(*verticalSide))
         return true;
 
-    if (biasedDelta.width() && !scrollableArea.isPinnedForScrollDeltaOnAxis(-biasedDelta.width(), ScrollEventAxis::Horizontal))
+    auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Horizontal);
+    if (horizontalSide && !scrollableArea.isPinnedOnSide(*horizontalSide))
         return true;
 
     return false;

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (283334 => 283335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2021-09-30 20:58:03 UTC (rev 283335)
@@ -595,18 +595,10 @@
     m_swipeState.canRubberBand = canRubberBand;
 }
 
-bool ScrollingTree::mainFrameCanRubberBandInDirection(ScrollDirection direction)
+bool ScrollingTree::mainFrameCanRubberBandOnSide(BoxSide side)
 {
     Locker locker { m_swipeStateLock };
-
-    switch (direction) {
-    case ScrollUp: return m_swipeState.canRubberBand.top();
-    case ScrollDown: return m_swipeState.canRubberBand.bottom();
-    case ScrollLeft: return m_swipeState.canRubberBand.left();
-    case ScrollRight: return m_swipeState.canRubberBand.right();
-    };
-
-    return false;
+    return m_swipeState.canRubberBand.at(side);
 }
 
 void ScrollingTree::addPendingScrollUpdate(ScrollUpdate&& update)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (283334 => 283335)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -173,7 +173,7 @@
 
     // Can be called from any thread. Will update what edges allow rubber-banding.
     WEBCORE_EXPORT void setMainFrameCanRubberBand(RectEdges<bool>);
-    bool mainFrameCanRubberBandInDirection(ScrollDirection);
+    bool mainFrameCanRubberBandOnSide(BoxSide);
 
     bool isHandlingProgrammaticScroll() const { return m_isHandlingProgrammaticScroll; }
     void setIsHandlingProgrammaticScroll(bool isHandlingProgrammaticScroll) { m_isHandlingProgrammaticScroll = isHandlingProgrammaticScroll; }

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h (283334 => 283335)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -68,8 +68,6 @@
     void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) const override;
 
 private:
-    bool isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis, float scrollLimit = 0) const;
-
     // ScrollingEffectsControllerClient.
     std::unique_ptr<ScrollingEffectsControllerTimer> createTimer(Function<void()>&&) final;
     void startAnimationCallback(ScrollingEffectsController&) final;
@@ -78,7 +76,8 @@
     bool allowsHorizontalStretching(const PlatformWheelEvent&) const final;
     bool allowsVerticalStretching(const PlatformWheelEvent&) const final;
     IntSize stretchAmount() const final;
-    bool isPinnedForScrollDelta(const FloatSize&) const final;
+    bool isPinnedOnSide(BoxSide) const final;
+
     RectEdges<bool> edgePinnedState() const final;
     bool allowsHorizontalScrolling() const final;
     bool allowsVerticalScrolling() const final;
@@ -85,7 +84,7 @@
     void setScrollBehaviorStatus(ScrollBehaviorStatus status) final { m_scrollBehaviorStatus = status; }
     ScrollBehaviorStatus scrollBehaviorStatus() const final { return m_scrollBehaviorStatus; }
 
-    bool shouldRubberBandInDirection(ScrollDirection) const final;
+    bool shouldRubberBandOnSide(BoxSide) const final;
     void immediateScrollBy(const FloatSize&) final;
     void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) final;
     void didStopRubberbandSnapAnimation() final;

Modified: trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm (283334 => 283335)


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-09-30 20:58:03 UTC (rev 283335)
@@ -172,43 +172,6 @@
     return m_scrollController.isScrollSnapInProgress();
 }
 
-bool ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis axis, float scrollLimit) const
-{
-    auto scrollPosition = currentScrollPosition();
-    switch (axis) {
-    case ScrollEventAxis::Vertical:
-        if (!allowsVerticalScrolling())
-            return true;
-
-        if (scrollDelta < 0) {
-            auto topOffset = scrollPosition.y() - minimumScrollPosition().y();
-            return topOffset <= scrollLimit;
-        }
-
-        if (scrollDelta > 0) {
-            auto bottomOffset = maximumScrollPosition().y() - scrollPosition.y();
-            return bottomOffset <= scrollLimit;
-        }
-        break;
-    case ScrollEventAxis::Horizontal:
-        if (!allowsHorizontalScrolling())
-            return true;
-
-        if (scrollDelta < 0) {
-            auto leftOffset = scrollPosition.x() - minimumScrollPosition().x();
-            return leftOffset <= scrollLimit;
-        }
-
-        if (scrollDelta > 0) {
-            auto rightOffset = maximumScrollPosition().x() - scrollPosition.x();
-            return rightOffset <= scrollLimit;
-        }
-        break;
-    }
-
-    return false;
-}
-
 std::unique_ptr<ScrollingEffectsControllerTimer> ScrollingTreeScrollingNodeDelegateMac::createTimer(Function<void()>&& function)
 {
     return WTF::makeUnique<ScrollingEffectsControllerTimer>(RunLoop::current(), [function = WTFMove(function), protectedNode = Ref { scrollingNode() }] {
@@ -244,15 +207,16 @@
     switch (horizontalScrollElasticity()) {
     case ScrollElasticityAutomatic: {
         bool scrollbarsAllowStretching = allowsHorizontalScrolling() || !allowsVerticalScrolling();
-        bool eventPreventsStretching = wheelEvent.isGestureStart() && isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaX(), ScrollEventAxis::Horizontal);
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
+        bool eventPreventsStretching = wheelEvent.isGestureStart() && relevantSide && isPinnedOnSide(*relevantSide);
         return scrollbarsAllowStretching && !eventPreventsStretching;
     }
     case ScrollElasticityNone:
         return false;
     case ScrollElasticityAllowed: {
-        auto scrollDirection = ScrollingEffectsController::directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
-        if (scrollDirection)
-            return shouldRubberBandInDirection(scrollDirection.value());
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
+        if (relevantSide)
+            return shouldRubberBandOnSide(*relevantSide);
         return true;
     }
     }
@@ -266,15 +230,16 @@
     switch (verticalScrollElasticity()) {
     case ScrollElasticityAutomatic: {
         bool scrollbarsAllowStretching = allowsVerticalScrolling() || !allowsHorizontalScrolling();
-        bool eventPreventsStretching = wheelEvent.isGestureStart() && isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaY(), ScrollEventAxis::Vertical);
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
+        bool eventPreventsStretching = wheelEvent.isGestureStart() && relevantSide && isPinnedOnSide(*relevantSide);
         return scrollbarsAllowStretching && !eventPreventsStretching;
     }
     case ScrollElasticityNone:
         return false;
     case ScrollElasticityAllowed: {
-        auto scrollDirection = ScrollingEffectsController::directionFromEvent(wheelEvent, ScrollEventAxis::Vertical);
-        if (scrollDirection)
-            return shouldRubberBandInDirection(scrollDirection.value());
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
+        if (relevantSide)
+            return shouldRubberBandOnSide(*relevantSide);
         return true;
     }
     }
@@ -301,17 +266,26 @@
     return stretch;
 }
 
-bool ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDelta(const FloatSize& delta) const
+bool ScrollingTreeScrollingNodeDelegateMac::isPinnedOnSide(BoxSide side) const
 {
-    // This "offset < 1" logic was added in r107488. Unclear if it's needed.
-    constexpr float scrollOffsetLimit = 1.0f - std::numeric_limits<float>::epsilon();
-
-    if (fabsf(delta.height()) >= fabsf(delta.width()))
-        return isPinnedForScrollDeltaOnAxis(delta.height(), ScrollEventAxis::Vertical, scrollOffsetLimit);
-
-    if (delta.width())
-        return isPinnedForScrollDeltaOnAxis(delta.width(), ScrollEventAxis::Horizontal, scrollOffsetLimit);
-
+    switch (side) {
+    case BoxSide::Top:
+        if (!allowsVerticalScrolling())
+            return true;
+        return currentScrollPosition().y() <= minimumScrollPosition().y();
+    case BoxSide::Bottom:
+        if (!allowsVerticalScrolling())
+            return true;
+        return currentScrollPosition().y() >= maximumScrollPosition().y();
+    case BoxSide::Left:
+        if (!allowsHorizontalScrolling())
+            return true;
+        return currentScrollPosition().x() <= minimumScrollPosition().x();
+    case BoxSide::Right:
+        if (!allowsHorizontalScrolling())
+            return true;
+        return currentScrollPosition().x() >= maximumScrollPosition().x();
+    }
     return false;
 }
 
@@ -330,17 +304,17 @@
     return ScrollingTreeScrollingNodeDelegate::allowsVerticalScrolling();
 }
 
-bool ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandInDirection(ScrollDirection direction) const
+bool ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandOnSide(BoxSide side) const
 {
     if (scrollingNode().isRootNode())
-        return scrollingTree().mainFrameCanRubberBandInDirection(direction);
+        return scrollingTree().mainFrameCanRubberBandOnSide(side);
 
-    switch (direction) {
-    case ScrollDirection::ScrollUp:
-    case ScrollDirection::ScrollDown:
+    switch (side) {
+    case BoxSide::Top:
+    case BoxSide::Bottom:
         return allowsVerticalScrolling();
-    case ScrollDirection::ScrollLeft:
-    case ScrollDirection::ScrollRight:
+    case BoxSide::Left:
+    case BoxSide::Right:
         return allowsHorizontalScrolling();
     }
     return true;

Modified: trunk/Source/WebCore/platform/ScrollAnimator.cpp (283334 => 283335)


--- trunk/Source/WebCore/platform/ScrollAnimator.cpp	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ScrollAnimator.cpp	2021-09-30 20:58:03 UTC (rev 283335)
@@ -308,16 +308,11 @@
     return m_scrollableArea.edgePinnedState();
 }
 
-bool ScrollAnimator::isPinnedForScrollDelta(const FloatSize& delta) const
+bool ScrollAnimator::isPinnedOnSide(BoxSide side) const
 {
-    if (fabsf(delta.height()) >= fabsf(delta.width()))
-        return m_scrollableArea.isPinnedForScrollDeltaOnAxis(delta.height(), ScrollEventAxis::Vertical);
+    return m_scrollableArea.isPinnedOnSide(side);
+}
 
-    if (delta.width())
-        return m_scrollableArea.isPinnedForScrollDeltaOnAxis(delta.width(), ScrollEventAxis::Horizontal);
-
-    return false;
-}
 #endif
 
 void ScrollAnimator::adjustScrollPositionToBoundsIfNecessary()

Modified: trunk/Source/WebCore/platform/ScrollAnimator.h (283334 => 283335)


--- trunk/Source/WebCore/platform/ScrollAnimator.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ScrollAnimator.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -154,7 +154,7 @@
 #if HAVE(RUBBER_BANDING)
     IntSize stretchAmount() const final;
     RectEdges<bool> edgePinnedState() const final;
-    bool isPinnedForScrollDelta(const FloatSize&) const final;
+    bool isPinnedOnSide(BoxSide) const final;
 #endif
 
 #if PLATFORM(MAC)

Modified: trunk/Source/WebCore/platform/ScrollableArea.cpp (283334 => 283335)


--- trunk/Source/WebCore/platform/ScrollableArea.cpp	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ScrollableArea.cpp	2021-09-30 20:58:03 UTC (rev 283335)
@@ -578,43 +578,29 @@
     scrollAnimator->scrollToPositionWithAnimation(position);
 }
 
-bool ScrollableArea::isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis axis) const
+bool ScrollableArea::isPinnedOnSide(BoxSide side) const
 {
-    auto scrollPosition = this->scrollPosition();
-    switch (axis) {
-    case ScrollEventAxis::Vertical:
+    switch (side) {
+    case BoxSide::Top:
         if (!allowsVerticalScrolling())
             return true;
-
-        if (scrollDelta < 0) // top
-            return scrollPosition.y() <= minimumScrollPosition().y();
-
-        if (scrollDelta > 0) // bottom
-            return scrollPosition.y() >= maximumScrollPosition().y();
-
-        break;
-    case ScrollEventAxis::Horizontal:
+        return scrollPosition().y() <= minimumScrollPosition().y();
+    case BoxSide::Bottom:
+        if (!allowsVerticalScrolling())
+            return true;
+        return scrollPosition().y() >= maximumScrollPosition().y();
+    case BoxSide::Left:
         if (!allowsHorizontalScrolling())
             return true;
-
-        if (scrollDelta < 0) // left
-            return scrollPosition.x() <= minimumScrollPosition().x();
-
-        if (scrollDelta > 0) // right
-            return scrollPosition.x() >= maximumScrollPosition().x();
-
-        break;
+        return scrollPosition().x() <= minimumScrollPosition().x();
+    case BoxSide::Right:
+        if (!allowsHorizontalScrolling())
+            return true;
+        return scrollPosition().x() >= maximumScrollPosition().x();
     }
-
     return false;
 }
 
-bool ScrollableArea::isPinnedForScrollDelta(const FloatSize& scrollDelta) const
-{
-    return (!scrollDelta.width() || isPinnedForScrollDeltaOnAxis(scrollDelta.width(), ScrollEventAxis::Horizontal))
-        && (!scrollDelta.height() || isPinnedForScrollDeltaOnAxis(scrollDelta.height(), ScrollEventAxis::Vertical));
-}
-
 RectEdges<bool> ScrollableArea::edgePinnedState() const
 {
     auto scrollPosition = this->scrollPosition();
@@ -797,6 +783,29 @@
     }
 }
 
+std::optional<BoxSide> ScrollableArea::targetSideForScrollDelta(FloatSize delta, ScrollEventAxis axis)
+{
+    switch (axis) {
+    case ScrollEventAxis::Horizontal:
+        if (delta.width() < 0)
+            return BoxSide::Left;
+
+        if (delta.width() > 0)
+            return BoxSide::Right;
+        break;
+
+    case ScrollEventAxis::Vertical:
+        if (delta.height() < 0)
+            return BoxSide::Top;
+
+        if (delta.height() > 0)
+            return BoxSide::Bottom;
+        break;
+    }
+
+    return { };
+}
+
 TextStream& operator<<(TextStream& ts, const ScrollableArea& scrollableArea)
 {
     ts << scrollableArea.debugDescription();

Modified: trunk/Source/WebCore/platform/ScrollableArea.h (283334 => 283335)


--- trunk/Source/WebCore/platform/ScrollableArea.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ScrollableArea.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -317,8 +317,10 @@
     // This function is static so that it can be called from the main thread or the scrolling thread.
     WEBCORE_EXPORT static void computeScrollbarValueAndOverhang(float currentPosition, float totalSize, float visibleSize, float& doubleValue, float& overhangAmount);
 
-    bool isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis) const;
-    bool isPinnedForScrollDelta(const FloatSize&) const;
+    static std::optional<BoxSide> targetSideForScrollDelta(FloatSize, ScrollEventAxis);
+
+    // "Pinned" means scrolled at or beyond the edge.
+    bool isPinnedOnSide(BoxSide) const;
     RectEdges<bool> edgePinnedState() const;
 
     // True if scrolling happens by moving compositing layers.

Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.h (283334 => 283335)


--- trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -85,6 +85,7 @@
     virtual void setScrollBehaviorStatus(ScrollBehaviorStatus) = 0;
     virtual ScrollBehaviorStatus scrollBehaviorStatus() const = 0;
 
+    // FIXME: use ScrollClamping to collapse these to one.
     virtual void immediateScrollBy(const FloatSize&) = 0;
     virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
 
@@ -97,13 +98,12 @@
     virtual bool allowsVerticalStretching(const PlatformWheelEvent&) const = 0;
     virtual IntSize stretchAmount() const = 0;
 
-    virtual bool isPinnedForScrollDelta(const FloatSize&) const = 0;
-
+    // "Pinned" means scrolled at or beyond the edge.
+    virtual bool isPinnedOnSide(BoxSide) const = 0;
     virtual RectEdges<bool> edgePinnedState() const = 0;
 
-    virtual bool shouldRubberBandInDirection(ScrollDirection) const = 0;
+    virtual bool shouldRubberBandOnSide(BoxSide) const = 0;
 
-    // FIXME: use ScrollClamping to collapse these to one.
     virtual void willStartRubberBandSnapAnimation() { }
     virtual void didStopRubberbandSnapAnimation() { }
 
@@ -167,8 +167,6 @@
     // Returns true if handled.
     bool handleWheelEvent(const PlatformWheelEvent&);
 
-    enum class WheelAxisBias { None, Vertical };
-    static std::optional<ScrollDirection> directionFromEvent(const PlatformWheelEvent&, std::optional<ScrollEventAxis>, WheelAxisBias = WheelAxisBias::None);
     static FloatSize wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent&);
 
     bool isScrollSnapInProgress() const;
@@ -204,8 +202,7 @@
     void stopSnapRubberbandAnimation();
 
     void snapRubberBand();
-    bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&) const;
-    bool shouldRubberBandInDirection(ScrollDirection) const;
+    bool shouldRubberBandOnSide(BoxSide) const;
     bool isRubberBandInProgressInternal() const;
     void updateRubberBandingState();
     void updateRubberBandingEdges(IntSize clientStretch);

Modified: trunk/Source/WebCore/platform/ios/ScrollAnimatorIOS.mm (283334 => 283335)


--- trunk/Source/WebCore/platform/ios/ScrollAnimatorIOS.mm	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/ios/ScrollAnimatorIOS.mm	2021-09-30 20:58:03 UTC (rev 283335)
@@ -31,6 +31,7 @@
 #import "Frame.h"
 #import "RenderLayer.h"
 #import "ScrollableArea.h"
+#import "ScrollingEffectsController.h"
 
 #if ENABLE(TOUCH_EVENTS)
 #import "PlatformTouchEventIOS.h"
@@ -163,12 +164,18 @@
 {
     ASSERT(!m_scrollableAreaForTouchSequence);
 
-    ScrollableArea* scrollableArea = &m_scrollableArea;
+    auto horizontalEdge = ScrollableArea::targetSideForScrollDelta(scrollDelta, ScrollEventAxis::Horizontal);
+    auto verticalEdge = ScrollableArea::targetSideForScrollDelta(scrollDelta, ScrollEventAxis::Vertical);
+
+    auto* scrollableArea = &m_scrollableArea;
     while (true) {
-        if (!scrollableArea->isPinnedForScrollDelta(scrollDelta))
+        if (verticalEdge && !scrollableArea->isPinnedOnSide(*verticalEdge))
             break;
 
-        ScrollableArea* enclosingArea = scrollableArea->enclosingScrollableArea();
+        if (horizontalEdge && !scrollableArea->isPinnedOnSide(*horizontalEdge))
+            break;
+
+        auto* enclosingArea = scrollableArea->enclosingScrollableArea();
         if (!enclosingArea)
             break;
 

Modified: trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.h (283334 => 283335)


--- trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.h	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.h	2021-09-30 20:58:03 UTC (rev 283335)
@@ -59,7 +59,7 @@
     // ScrollingEffectsControllerClient.
     bool allowsHorizontalStretching(const PlatformWheelEvent&) const final;
     bool allowsVerticalStretching(const PlatformWheelEvent&) const final;
-    bool shouldRubberBandInDirection(ScrollDirection) const final;
+    bool shouldRubberBandOnSide(BoxSide) const final;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm (283334 => 283335)


--- trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2021-09-30 20:58:03 UTC (rev 283335)
@@ -158,7 +158,8 @@
         Scrollbar* hScroller = m_scrollableArea.horizontalScrollbar();
         Scrollbar* vScroller = m_scrollableArea.verticalScrollbar();
         bool scrollbarsAllowStretching = ((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled()));
-        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && m_scrollableArea.isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaY(), ScrollEventAxis::Vertical);
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
+        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && relevantSide && m_scrollableArea.isPinnedOnSide(*relevantSide);
         if (!eventPreventsStretching)
             eventPreventsStretching = gestureShouldBeginSnap(wheelEvent, ScrollEventAxis::Vertical, m_scrollableArea.snapOffsetsInfo());
         return scrollbarsAllowStretching && !eventPreventsStretching;
@@ -180,7 +181,8 @@
         Scrollbar* hScroller = m_scrollableArea.horizontalScrollbar();
         Scrollbar* vScroller = m_scrollableArea.verticalScrollbar();
         bool scrollbarsAllowStretching = ((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled()));
-        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && m_scrollableArea.isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaX(), ScrollEventAxis::Horizontal);
+        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
+        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && relevantSide && m_scrollableArea.isPinnedOnSide(*relevantSide);
         if (!eventPreventsStretching)
             eventPreventsStretching = gestureShouldBeginSnap(wheelEvent, ScrollEventAxis::Horizontal, m_scrollableArea.snapOffsetsInfo());
         return scrollbarsAllowStretching && !eventPreventsStretching;
@@ -195,7 +197,7 @@
     return false;
 }
 
-bool ScrollAnimatorMac::shouldRubberBandInDirection(ScrollDirection) const
+bool ScrollAnimatorMac::shouldRubberBandOnSide(BoxSide) const
 {
     return false;
 }

Modified: trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm (283334 => 283335)


--- trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-09-30 20:51:45 UTC (rev 283334)
+++ trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-09-30 20:58:03 UTC (rev 283335)
@@ -83,15 +83,46 @@
 #endif
 }
 
-
-static FloatSize convertToProminentAxisFavoringVertical(FloatSize delta)
+static ScrollEventAxis dominantAxisFavoringVertical(FloatSize delta)
 {
     if (fabsf(delta.height()) >= fabsf(delta.width()))
-        return { 0, delta.height() };
+        return ScrollEventAxis::Vertical;
 
-    return { delta.width(), 0 };
+    return ScrollEventAxis::Horizontal;
 }
 
+static FloatSize deltaAlignedToAxis(FloatSize delta, ScrollEventAxis axis)
+{
+    switch (axis) {
+    case ScrollEventAxis::Horizontal: return FloatSize { delta.width(), 0 };
+    case ScrollEventAxis::Vertical: return FloatSize { 0, delta.height() };
+    }
+
+    return { };
+}
+
+static FloatSize deltaAlignedToDominantAxis(FloatSize delta)
+{
+    auto dominantAxis = dominantAxisFavoringVertical(delta);
+    return deltaAlignedToAxis(delta, dominantAxis);
+}
+
+static std::optional<BoxSide> affectedSideOnDominantAxis(FloatSize delta)
+{
+    auto dominantAxis = dominantAxisFavoringVertical(delta);
+    return ScrollableArea::targetSideForScrollDelta(delta, dominantAxis);
+}
+
+static bool isHorizontalSide(std::optional<BoxSide> side)
+{
+    return side && (*side == BoxSide::Left || *side == BoxSide::Right);
+}
+
+static bool isVerticalSide(std::optional<BoxSide> side)
+{
+    return side && (*side == BoxSide::Top || *side == BoxSide::Bottom);
+}
+
 bool ScrollingEffectsController::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
 {
     if (processWheelEventForScrollSnap(wheelEvent))
@@ -102,12 +133,12 @@
 
     if (wheelEvent.phase() == PlatformWheelEventPhase::Began) {
         // FIXME: Trying to decide if a gesture is horizontal or vertical at the "began" phase is very error-prone.
-        auto direction = directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
-        if (direction && m_client.isPinnedForScrollDelta(FloatSize(-wheelEvent.deltaX(), 0)) && !shouldRubberBandInDirection(direction.value()))
+        auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
+        if (horizontalSide && m_client.isPinnedOnSide(*horizontalSide) && !shouldRubberBandOnSide(*horizontalSide))
             return false;
 
-        direction = directionFromEvent(wheelEvent, ScrollEventAxis::Vertical);
-        if (direction && m_client.isPinnedForScrollDelta(FloatSize(0, -wheelEvent.deltaY())) && !shouldRubberBandInDirection(direction.value()))
+        auto verticalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
+        if (verticalSide && m_client.isPinnedOnSide(*verticalSide) && !shouldRubberBandOnSide(*verticalSide))
             return false;
 
         m_momentumScrollInProgress = false;
@@ -155,7 +186,9 @@
     auto eventCoalescedDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();
     delta += eventCoalescedDelta;
 
-    delta = convertToProminentAxisFavoringVertical(delta);
+    // FIXME: All of the code below could be simplified since predominantAxis is known, and we zero out the delta on the other axis.
+    auto affectedSide = affectedSideOnDominantAxis(delta);
+
     float deltaX = delta.width();
     float deltaY = delta.height();
 
@@ -177,7 +210,7 @@
         }
 
         if (isVerticallyStretched) {
-            if (!isHorizontallyStretched && m_client.isPinnedForScrollDelta(FloatSize(deltaX, 0))) {
+            if (!isHorizontallyStretched && isHorizontalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
                 // Stretching only in the vertical.
                 if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
                     deltaX = 0;
@@ -189,7 +222,7 @@
             }
         } else if (isHorizontallyStretched) {
             // Stretching only in the horizontal.
-            if (m_client.isPinnedForScrollDelta(FloatSize(0, deltaY))) {
+            if (isVerticalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
                 if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
                     deltaY = 0;
                 else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
@@ -200,7 +233,7 @@
             }
         } else {
             // Not stretching at all yet.
-            if (m_client.isPinnedForScrollDelta(FloatSize(deltaX, deltaY))) {
+            if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
                 if (fabsf(deltaY) >= fabsf(deltaX)) {
                     if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
                         m_unappliedOverscrollDelta.expand(deltaX, 0);
@@ -233,12 +266,13 @@
                 m_client.immediateScrollBy(FloatSize(deltaX, 0));
             }
         } else {
+            affectedSide = affectedSideOnDominantAxis({ deltaX, deltaY });
             if (deltaX) {
                 if (!m_client.allowsHorizontalStretching(wheelEvent)) {
                     deltaX = 0;
                     eventCoalescedDelta.setWidth(0);
                     handled = false;
-                } else if (!isHorizontallyStretched && !m_client.isPinnedForScrollDelta(FloatSize(deltaX, 0))) {
+                } else if (!isHorizontallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
                     deltaX *= scrollWheelMultiplier();
 
                     m_client.immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
@@ -251,7 +285,7 @@
                     deltaY = 0;
                     eventCoalescedDelta.setHeight(0);
                     handled = false;
-                } else if (!isVerticallyStretched && !m_client.isPinnedForScrollDelta(FloatSize(0, deltaY))) {
+                } else if (!isVerticallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
                     deltaY *= scrollWheelMultiplier();
 
                     m_client.immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
@@ -262,7 +296,8 @@
             IntSize stretchAmount = m_client.stretchAmount();
 
             if (m_momentumScrollInProgress) {
-                if ((m_client.isPinnedForScrollDelta(eventCoalescedDelta) || eventCoalescedDelta.isZero()) && m_lastMomentumScrollTimestamp) {
+                auto sideAffectedByEventDelta = affectedSideOnDominantAxis(eventCoalescedDelta);
+                if ((!sideAffectedByEventDelta || m_client.isPinnedOnSide(*sideAffectedByEventDelta)) && m_lastMomentumScrollTimestamp) {
                     m_ignoreMomentumScrolls = true;
                     m_momentumScrollInProgress = false;
                     snapRubberBand();
@@ -293,55 +328,9 @@
 
 FloatSize ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent& wheelEvent)
 {
-    return convertToProminentAxisFavoringVertical(wheelEvent.delta());
+    return deltaAlignedToDominantAxis(wheelEvent.delta());
 }
 
-std::optional<ScrollDirection> ScrollingEffectsController::directionFromEvent(const PlatformWheelEvent& wheelEvent, std::optional<ScrollEventAxis> axis, WheelAxisBias bias)
-{
-    // FIXME: It's impossible to infer direction from a single event, since the start of a gesture is either zero or
-    // has small deltas on both axes.
-
-    auto wheelDelta = FloatSize { wheelEvent.deltaX(), wheelEvent.deltaY() };
-    if (bias == WheelAxisBias::Vertical)
-        wheelDelta = wheelDeltaBiasingTowardsVertical(wheelEvent);
-
-    if (axis) {
-        switch (axis.value()) {
-        case ScrollEventAxis::Vertical:
-            if (wheelDelta.height() < 0)
-                return ScrollDown;
-
-            if (wheelDelta.height() > 0)
-                return ScrollUp;
-            break;
-
-        case ScrollEventAxis::Horizontal:
-            if (wheelDelta.width() > 0)
-                return ScrollLeft;
-
-            if (wheelDelta.width() < 0)
-                return ScrollRight;
-        }
-
-        return std::nullopt;
-    }
-
-    // Check Y first because vertical scrolling dominates.
-    if (wheelDelta.height() < 0)
-        return ScrollDown;
-
-    if (wheelDelta.height() > 0)
-        return ScrollUp;
-
-    if (wheelDelta.width() > 0)
-        return ScrollLeft;
-
-    if (wheelDelta.width() < 0)
-        return ScrollRight;
-
-    return std::nullopt;
-}
-
 static inline float roundTowardZero(float num)
 {
     return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
@@ -493,20 +482,11 @@
     startRubberbandAnimation();
 }
 
-bool ScrollingEffectsController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent) const
+bool ScrollingEffectsController::shouldRubberBandOnSide(BoxSide side) const
 {
-    auto direction = directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
-    if (direction)
-        return shouldRubberBandInDirection(direction.value());
-
-    return true;
+    return m_client.shouldRubberBandOnSide(side);
 }
 
-bool ScrollingEffectsController::shouldRubberBandInDirection(ScrollDirection direction) const
-{
-    return m_client.shouldRubberBandInDirection(direction);
-}
-
 bool ScrollingEffectsController::isRubberBandInProgressInternal() const
 {
     if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_isAnimatingRubberBand)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to