⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 283335 in webkit


Ignore:
Timestamp:
Sep 30, 2021, 1:58:03 PM (5 years ago)
Author:
Simon Fraser
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.

Location:
trunk/Source/WebCore
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r283331 r283335  
     12021-09-29  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Replace the confusing isPinnedForScrollDelta() logic with code that uses BoxSide
     4        https://bugs.webkit.org/show_bug.cgi?id=231004
     5
     6        Reviewed by Tim Horton.
     7
     8        isPinnedForScrollDelta()/isPinnedForScrollDeltaOnAxis() are ambiguous because it's
     9        easy to interpret them as looking at the magnitude of the delta to determine whether
     10        the delta will cause stretching on an edge. However, they don't do this; they simply
     11        use the delta to choose which edge to look at, and the "is pinned" refers to whether
     12        the scroller is already scrolled to that edge or stretching at that edge.
     13
     14        To reduce ambiguity, rewrite the code in terms of BoxSides, separating the code
     15        that determines which BoxSide to look at for a given event delta from the code that
     16        computed pinned state. It's now clearer that it's the caller's responsibility to
     17        do "dominant axis" delta transformations too.
     18
     19        * page/EventHandler.cpp:
     20        (WebCore::EventHandler::scrollableAreaCanHandleEvent):
     21        * page/scrolling/ScrollingTree.cpp:
     22        (WebCore::ScrollingTree::mainFrameCanRubberBandOnSide):
     23        (WebCore::ScrollingTree::mainFrameCanRubberBandInDirection): Deleted.
     24        * page/scrolling/ScrollingTree.h:
     25        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
     26        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
     27        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsHorizontalStretching const):
     28        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsVerticalStretching const):
     29        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedOnSide const): Remove the old "scrollOffsetLimit" threshold. Our scroll offsets
     30        are currently all integral so I don't think this did anything.
     31        (WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandOnSide const):
     32        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDeltaOnAxis const): Deleted.
     33        (WebCore::ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDelta const): Deleted.
     34        (WebCore::ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandInDirection const): Deleted.
     35        * platform/ScrollAnimator.cpp:
     36        (WebCore::ScrollAnimator::isPinnedOnSide const):
     37        (WebCore::ScrollAnimator::isPinnedForScrollDelta const): Deleted.
     38        * platform/ScrollAnimator.h:
     39        * platform/ScrollableArea.cpp:
     40        (WebCore::ScrollableArea::isPinnedOnSide const):
     41        (WebCore::ScrollableArea::targetSideForScrollDelta):
     42        (WebCore::ScrollableArea::isPinnedForScrollDeltaOnAxis const): Deleted.
     43        (WebCore::ScrollableArea::isPinnedForScrollDelta const): Deleted.
     44        * platform/ScrollableArea.h:
     45        * platform/ScrollingEffectsController.h:
     46        * platform/ios/ScrollAnimatorIOS.mm:
     47        (WebCore::ScrollAnimatorIOS::determineScrollableAreaForTouchSequence):
     48        * platform/mac/ScrollAnimatorMac.h:
     49        * platform/mac/ScrollAnimatorMac.mm:
     50        (WebCore::ScrollAnimatorMac::allowsVerticalStretching const):
     51        (WebCore::ScrollAnimatorMac::allowsHorizontalStretching const):
     52        (WebCore::ScrollAnimatorMac::shouldRubberBandOnSide const):
     53        (WebCore::ScrollAnimatorMac::shouldRubberBandInDirection const): Deleted.
     54        * platform/mac/ScrollingEffectsController.mm:
     55        (WebCore::dominantAxisFavoringVertical):
     56        (WebCore::deltaAlignedToAxis):
     57        (WebCore::deltaAlignedToDominantAxis):
     58        (WebCore::affectedSideOnDominantAxis):
     59        (WebCore::isHorizontalSide):
     60        (WebCore::isVerticalSide):
     61        (WebCore::ScrollingEffectsController::handleWheelEvent):
     62        (WebCore::ScrollingEffectsController::wheelDeltaBiasingTowardsVertical):
     63        (WebCore::ScrollingEffectsController::shouldRubberBandOnSide const):
     64        (WebCore::convertToProminentAxisFavoringVertical): Deleted.
     65        (WebCore::ScrollingEffectsController::directionFromEvent): Deleted.
     66        (WebCore::ScrollingEffectsController::shouldRubberBandInHorizontalDirection const): Deleted.
     67        (WebCore::ScrollingEffectsController::shouldRubberBandInDirection const): Deleted.
     68
    1692021-09-30  Devin Rousso  <drousso@apple.com>
    270
  • trunk/Source/WebCore/page/EventHandler.cpp

    r282860 r283335  
    9999#include "ScrollLatchingController.h"
    100100#include "Scrollbar.h"
     101#include "ScrollingEffectsController.h"
    101102#include "SelectionRestorationMode.h"
    102103#include "Settings.h"
     
    31043105#endif
    31053106
    3106     if (biasedDelta.height() && !scrollableArea.isPinnedForScrollDeltaOnAxis(-biasedDelta.height(), ScrollEventAxis::Vertical))
     3107    auto verticalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Vertical);
     3108    if (verticalSide && !scrollableArea.isPinnedOnSide(*verticalSide))
    31073109        return true;
    31083110
    3109     if (biasedDelta.width() && !scrollableArea.isPinnedForScrollDeltaOnAxis(-biasedDelta.width(), ScrollEventAxis::Horizontal))
     3111    auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Horizontal);
     3112    if (horizontalSide && !scrollableArea.isPinnedOnSide(*horizontalSide))
    31103113        return true;
    31113114
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp

    r278253 r283335  
    596596}
    597597
    598 bool ScrollingTree::mainFrameCanRubberBandInDirection(ScrollDirection direction)
     598bool ScrollingTree::mainFrameCanRubberBandOnSide(BoxSide side)
    599599{
    600600    Locker locker { m_swipeStateLock };
    601 
    602     switch (direction) {
    603     case ScrollUp: return m_swipeState.canRubberBand.top();
    604     case ScrollDown: return m_swipeState.canRubberBand.bottom();
    605     case ScrollLeft: return m_swipeState.canRubberBand.left();
    606     case ScrollRight: return m_swipeState.canRubberBand.right();
    607     };
    608 
    609     return false;
     601    return m_swipeState.canRubberBand.at(side);
    610602}
    611603
  • trunk/Source/WebCore/page/scrolling/ScrollingTree.h

    r278923 r283335  
    174174    // Can be called from any thread. Will update what edges allow rubber-banding.
    175175    WEBCORE_EXPORT void setMainFrameCanRubberBand(RectEdges<bool>);
    176     bool mainFrameCanRubberBandInDirection(ScrollDirection);
     176    bool mainFrameCanRubberBandOnSide(BoxSide);
    177177
    178178    bool isHandlingProgrammaticScroll() const { return m_isHandlingProgrammaticScroll; }
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h

    r283019 r283335  
    6969
    7070private:
    71     bool isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis, float scrollLimit = 0) const;
    72 
    7371    // ScrollingEffectsControllerClient.
    7472    std::unique_ptr<ScrollingEffectsControllerTimer> createTimer(Function<void()>&&) final;
     
    7977    bool allowsVerticalStretching(const PlatformWheelEvent&) const final;
    8078    IntSize stretchAmount() const final;
    81     bool isPinnedForScrollDelta(const FloatSize&) const final;
     79    bool isPinnedOnSide(BoxSide) const final;
     80
    8281    RectEdges<bool> edgePinnedState() const final;
    8382    bool allowsHorizontalScrolling() const final;
     
    8685    ScrollBehaviorStatus scrollBehaviorStatus() const final { return m_scrollBehaviorStatus; }
    8786
    88     bool shouldRubberBandInDirection(ScrollDirection) const final;
     87    bool shouldRubberBandOnSide(BoxSide) const final;
    8988    void immediateScrollBy(const FloatSize&) final;
    9089    void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) final;
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm

    r283019 r283335  
    173173}
    174174
    175 bool ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis axis, float scrollLimit) const
    176 {
    177     auto scrollPosition = currentScrollPosition();
    178     switch (axis) {
    179     case ScrollEventAxis::Vertical:
    180         if (!allowsVerticalScrolling())
    181             return true;
    182 
    183         if (scrollDelta < 0) {
    184             auto topOffset = scrollPosition.y() - minimumScrollPosition().y();
    185             return topOffset <= scrollLimit;
    186         }
    187 
    188         if (scrollDelta > 0) {
    189             auto bottomOffset = maximumScrollPosition().y() - scrollPosition.y();
    190             return bottomOffset <= scrollLimit;
    191         }
    192         break;
    193     case ScrollEventAxis::Horizontal:
    194         if (!allowsHorizontalScrolling())
    195             return true;
    196 
    197         if (scrollDelta < 0) {
    198             auto leftOffset = scrollPosition.x() - minimumScrollPosition().x();
    199             return leftOffset <= scrollLimit;
    200         }
    201 
    202         if (scrollDelta > 0) {
    203             auto rightOffset = maximumScrollPosition().x() - scrollPosition.x();
    204             return rightOffset <= scrollLimit;
    205         }
    206         break;
    207     }
    208 
    209     return false;
    210 }
    211 
    212175std::unique_ptr<ScrollingEffectsControllerTimer> ScrollingTreeScrollingNodeDelegateMac::createTimer(Function<void()>&& function)
    213176{
     
    245208    case ScrollElasticityAutomatic: {
    246209        bool scrollbarsAllowStretching = allowsHorizontalScrolling() || !allowsVerticalScrolling();
    247         bool eventPreventsStretching = wheelEvent.isGestureStart() && isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaX(), ScrollEventAxis::Horizontal);
     210        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
     211        bool eventPreventsStretching = wheelEvent.isGestureStart() && relevantSide && isPinnedOnSide(*relevantSide);
    248212        return scrollbarsAllowStretching && !eventPreventsStretching;
    249213    }
     
    251215        return false;
    252216    case ScrollElasticityAllowed: {
    253         auto scrollDirection = ScrollingEffectsController::directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
    254         if (scrollDirection)
    255             return shouldRubberBandInDirection(scrollDirection.value());
     217        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
     218        if (relevantSide)
     219            return shouldRubberBandOnSide(*relevantSide);
    256220        return true;
    257221    }
     
    267231    case ScrollElasticityAutomatic: {
    268232        bool scrollbarsAllowStretching = allowsVerticalScrolling() || !allowsHorizontalScrolling();
    269         bool eventPreventsStretching = wheelEvent.isGestureStart() && isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaY(), ScrollEventAxis::Vertical);
     233        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
     234        bool eventPreventsStretching = wheelEvent.isGestureStart() && relevantSide && isPinnedOnSide(*relevantSide);
    270235        return scrollbarsAllowStretching && !eventPreventsStretching;
    271236    }
     
    273238        return false;
    274239    case ScrollElasticityAllowed: {
    275         auto scrollDirection = ScrollingEffectsController::directionFromEvent(wheelEvent, ScrollEventAxis::Vertical);
    276         if (scrollDirection)
    277             return shouldRubberBandInDirection(scrollDirection.value());
     240        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
     241        if (relevantSide)
     242            return shouldRubberBandOnSide(*relevantSide);
    278243        return true;
    279244    }
     
    302267}
    303268
    304 bool ScrollingTreeScrollingNodeDelegateMac::isPinnedForScrollDelta(const FloatSize& delta) const
    305 {
    306     // This "offset < 1" logic was added in r107488. Unclear if it's needed.
    307     constexpr float scrollOffsetLimit = 1.0f - std::numeric_limits<float>::epsilon();
    308 
    309     if (fabsf(delta.height()) >= fabsf(delta.width()))
    310         return isPinnedForScrollDeltaOnAxis(delta.height(), ScrollEventAxis::Vertical, scrollOffsetLimit);
    311 
    312     if (delta.width())
    313         return isPinnedForScrollDeltaOnAxis(delta.width(), ScrollEventAxis::Horizontal, scrollOffsetLimit);
    314 
     269bool ScrollingTreeScrollingNodeDelegateMac::isPinnedOnSide(BoxSide side) const
     270{
     271    switch (side) {
     272    case BoxSide::Top:
     273        if (!allowsVerticalScrolling())
     274            return true;
     275        return currentScrollPosition().y() <= minimumScrollPosition().y();
     276    case BoxSide::Bottom:
     277        if (!allowsVerticalScrolling())
     278            return true;
     279        return currentScrollPosition().y() >= maximumScrollPosition().y();
     280    case BoxSide::Left:
     281        if (!allowsHorizontalScrolling())
     282            return true;
     283        return currentScrollPosition().x() <= minimumScrollPosition().x();
     284    case BoxSide::Right:
     285        if (!allowsHorizontalScrolling())
     286            return true;
     287        return currentScrollPosition().x() >= maximumScrollPosition().x();
     288    }
    315289    return false;
    316290}
     
    331305}
    332306
    333 bool ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandInDirection(ScrollDirection direction) const
     307bool ScrollingTreeScrollingNodeDelegateMac::shouldRubberBandOnSide(BoxSide side) const
    334308{
    335309    if (scrollingNode().isRootNode())
    336         return scrollingTree().mainFrameCanRubberBandInDirection(direction);
    337 
    338     switch (direction) {
    339     case ScrollDirection::ScrollUp:
    340     case ScrollDirection::ScrollDown:
     310        return scrollingTree().mainFrameCanRubberBandOnSide(side);
     311
     312    switch (side) {
     313    case BoxSide::Top:
     314    case BoxSide::Bottom:
    341315        return allowsVerticalScrolling();
    342     case ScrollDirection::ScrollLeft:
    343     case ScrollDirection::ScrollRight:
     316    case BoxSide::Left:
     317    case BoxSide::Right:
    344318        return allowsHorizontalScrolling();
    345319    }
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r283019 r283335  
    309309}
    310310
    311 bool ScrollAnimator::isPinnedForScrollDelta(const FloatSize& delta) const
    312 {
    313     if (fabsf(delta.height()) >= fabsf(delta.width()))
    314         return m_scrollableArea.isPinnedForScrollDeltaOnAxis(delta.height(), ScrollEventAxis::Vertical);
    315 
    316     if (delta.width())
    317         return m_scrollableArea.isPinnedForScrollDeltaOnAxis(delta.width(), ScrollEventAxis::Horizontal);
    318 
    319     return false;
    320 }
     311bool ScrollAnimator::isPinnedOnSide(BoxSide side) const
     312{
     313    return m_scrollableArea.isPinnedOnSide(side);
     314}
     315
    321316#endif
    322317
  • trunk/Source/WebCore/platform/ScrollAnimator.h

    r283019 r283335  
    155155    IntSize stretchAmount() const final;
    156156    RectEdges<bool> edgePinnedState() const final;
    157     bool isPinnedForScrollDelta(const FloatSize&) const final;
     157    bool isPinnedOnSide(BoxSide) const final;
    158158#endif
    159159
  • trunk/Source/WebCore/platform/ScrollableArea.cpp

    r282903 r283335  
    579579}
    580580
    581 bool ScrollableArea::isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis axis) const
    582 {
    583     auto scrollPosition = this->scrollPosition();
    584     switch (axis) {
    585     case ScrollEventAxis::Vertical:
     581bool ScrollableArea::isPinnedOnSide(BoxSide side) const
     582{
     583    switch (side) {
     584    case BoxSide::Top:
    586585        if (!allowsVerticalScrolling())
    587586            return true;
    588 
    589         if (scrollDelta < 0) // top
    590             return scrollPosition.y() <= minimumScrollPosition().y();
    591 
    592         if (scrollDelta > 0) // bottom
    593             return scrollPosition.y() >= maximumScrollPosition().y();
    594 
    595         break;
    596     case ScrollEventAxis::Horizontal:
     587        return scrollPosition().y() <= minimumScrollPosition().y();
     588    case BoxSide::Bottom:
     589        if (!allowsVerticalScrolling())
     590            return true;
     591        return scrollPosition().y() >= maximumScrollPosition().y();
     592    case BoxSide::Left:
    597593        if (!allowsHorizontalScrolling())
    598594            return true;
    599 
    600         if (scrollDelta < 0) // left
    601             return scrollPosition.x() <= minimumScrollPosition().x();
    602 
    603         if (scrollDelta > 0) // right
    604             return scrollPosition.x() >= maximumScrollPosition().x();
    605 
    606         break;
    607     }
    608 
     595        return scrollPosition().x() <= minimumScrollPosition().x();
     596    case BoxSide::Right:
     597        if (!allowsHorizontalScrolling())
     598            return true;
     599        return scrollPosition().x() >= maximumScrollPosition().x();
     600    }
    609601    return false;
    610 }
    611 
    612 bool ScrollableArea::isPinnedForScrollDelta(const FloatSize& scrollDelta) const
    613 {
    614     return (!scrollDelta.width() || isPinnedForScrollDeltaOnAxis(scrollDelta.width(), ScrollEventAxis::Horizontal))
    615         && (!scrollDelta.height() || isPinnedForScrollDeltaOnAxis(scrollDelta.height(), ScrollEventAxis::Vertical));
    616602}
    617603
     
    798784}
    799785
     786std::optional<BoxSide> ScrollableArea::targetSideForScrollDelta(FloatSize delta, ScrollEventAxis axis)
     787{
     788    switch (axis) {
     789    case ScrollEventAxis::Horizontal:
     790        if (delta.width() < 0)
     791            return BoxSide::Left;
     792
     793        if (delta.width() > 0)
     794            return BoxSide::Right;
     795        break;
     796
     797    case ScrollEventAxis::Vertical:
     798        if (delta.height() < 0)
     799            return BoxSide::Top;
     800
     801        if (delta.height() > 0)
     802            return BoxSide::Bottom;
     803        break;
     804    }
     805
     806    return { };
     807}
     808
    800809TextStream& operator<<(TextStream& ts, const ScrollableArea& scrollableArea)
    801810{
  • trunk/Source/WebCore/platform/ScrollableArea.h

    r282862 r283335  
    318318    WEBCORE_EXPORT static void computeScrollbarValueAndOverhang(float currentPosition, float totalSize, float visibleSize, float& doubleValue, float& overhangAmount);
    319319
    320     bool isPinnedForScrollDeltaOnAxis(float scrollDelta, ScrollEventAxis) const;
    321     bool isPinnedForScrollDelta(const FloatSize&) const;
     320    static std::optional<BoxSide> targetSideForScrollDelta(FloatSize, ScrollEventAxis);
     321
     322    // "Pinned" means scrolled at or beyond the edge.
     323    bool isPinnedOnSide(BoxSide) const;
    322324    RectEdges<bool> edgePinnedState() const;
    323325
  • trunk/Source/WebCore/platform/ScrollingEffectsController.h

    r283296 r283335  
    8686    virtual ScrollBehaviorStatus scrollBehaviorStatus() const = 0;
    8787
     88    // FIXME: use ScrollClamping to collapse these to one.
    8889    virtual void immediateScrollBy(const FloatSize&) = 0;
    8990    virtual void immediateScrollByWithoutContentEdgeConstraints(const FloatSize&) = 0;
     
    9899    virtual IntSize stretchAmount() const = 0;
    99100
    100     virtual bool isPinnedForScrollDelta(const FloatSize&) const = 0;
    101 
     101    // "Pinned" means scrolled at or beyond the edge.
     102    virtual bool isPinnedOnSide(BoxSide) const = 0;
    102103    virtual RectEdges<bool> edgePinnedState() const = 0;
    103104
    104     virtual bool shouldRubberBandInDirection(ScrollDirection) const = 0;
    105 
    106     // FIXME: use ScrollClamping to collapse these to one.
     105    virtual bool shouldRubberBandOnSide(BoxSide) const = 0;
     106
    107107    virtual void willStartRubberBandSnapAnimation() { }
    108108    virtual void didStopRubberbandSnapAnimation() { }
     
    168168    bool handleWheelEvent(const PlatformWheelEvent&);
    169169
    170     enum class WheelAxisBias { None, Vertical };
    171     static std::optional<ScrollDirection> directionFromEvent(const PlatformWheelEvent&, std::optional<ScrollEventAxis>, WheelAxisBias = WheelAxisBias::None);
    172170    static FloatSize wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent&);
    173171
     
    205203
    206204    void snapRubberBand();
    207     bool shouldRubberBandInHorizontalDirection(const PlatformWheelEvent&) const;
    208     bool shouldRubberBandInDirection(ScrollDirection) const;
     205    bool shouldRubberBandOnSide(BoxSide) const;
    209206    bool isRubberBandInProgressInternal() const;
    210207    void updateRubberBandingState();
  • trunk/Source/WebCore/platform/ios/ScrollAnimatorIOS.mm

    r282720 r283335  
    3232#import "RenderLayer.h"
    3333#import "ScrollableArea.h"
     34#import "ScrollingEffectsController.h"
    3435
    3536#if ENABLE(TOUCH_EVENTS)
     
    164165    ASSERT(!m_scrollableAreaForTouchSequence);
    165166
    166     ScrollableArea* scrollableArea = &m_scrollableArea;
     167    auto horizontalEdge = ScrollableArea::targetSideForScrollDelta(scrollDelta, ScrollEventAxis::Horizontal);
     168    auto verticalEdge = ScrollableArea::targetSideForScrollDelta(scrollDelta, ScrollEventAxis::Vertical);
     169
     170    auto* scrollableArea = &m_scrollableArea;
    167171    while (true) {
    168         if (!scrollableArea->isPinnedForScrollDelta(scrollDelta))
     172        if (verticalEdge && !scrollableArea->isPinnedOnSide(*verticalEdge))
    169173            break;
    170174
    171         ScrollableArea* enclosingArea = scrollableArea->enclosingScrollableArea();
     175        if (horizontalEdge && !scrollableArea->isPinnedOnSide(*horizontalEdge))
     176            break;
     177
     178        auto* enclosingArea = scrollableArea->enclosingScrollableArea();
    172179        if (!enclosingArea)
    173180            break;
  • trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.h

    r283019 r283335  
    6060    bool allowsHorizontalStretching(const PlatformWheelEvent&) const final;
    6161    bool allowsVerticalStretching(const PlatformWheelEvent&) const final;
    62     bool shouldRubberBandInDirection(ScrollDirection) const final;
     62    bool shouldRubberBandOnSide(BoxSide) const final;
    6363};
    6464
  • trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm

    r283019 r283335  
    159159        Scrollbar* vScroller = m_scrollableArea.verticalScrollbar();
    160160        bool scrollbarsAllowStretching = ((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled()));
    161         bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && m_scrollableArea.isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaY(), ScrollEventAxis::Vertical);
     161        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
     162        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && relevantSide && m_scrollableArea.isPinnedOnSide(*relevantSide);
    162163        if (!eventPreventsStretching)
    163164            eventPreventsStretching = gestureShouldBeginSnap(wheelEvent, ScrollEventAxis::Vertical, m_scrollableArea.snapOffsetsInfo());
     
    181182        Scrollbar* vScroller = m_scrollableArea.verticalScrollbar();
    182183        bool scrollbarsAllowStretching = ((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled()));
    183         bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && m_scrollableArea.isPinnedForScrollDeltaOnAxis(-wheelEvent.deltaX(), ScrollEventAxis::Horizontal);
     184        auto relevantSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
     185        bool eventPreventsStretching = m_scrollableArea.hasScrollableOrRubberbandableAncestor() && wheelEvent.isGestureStart() && relevantSide && m_scrollableArea.isPinnedOnSide(*relevantSide);
    184186        if (!eventPreventsStretching)
    185187            eventPreventsStretching = gestureShouldBeginSnap(wheelEvent, ScrollEventAxis::Horizontal, m_scrollableArea.snapOffsetsInfo());
     
    196198}
    197199
    198 bool ScrollAnimatorMac::shouldRubberBandInDirection(ScrollDirection) const
     200bool ScrollAnimatorMac::shouldRubberBandOnSide(BoxSide) const
    199201{
    200202    return false;
  • trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm

    r283296 r283335  
    8484}
    8585
    86 
    87 static FloatSize convertToProminentAxisFavoringVertical(FloatSize delta)
     86static ScrollEventAxis dominantAxisFavoringVertical(FloatSize delta)
    8887{
    8988    if (fabsf(delta.height()) >= fabsf(delta.width()))
    90         return { 0, delta.height() };
    91 
    92     return { delta.width(), 0 };
     89        return ScrollEventAxis::Vertical;
     90
     91    return ScrollEventAxis::Horizontal;
     92}
     93
     94static FloatSize deltaAlignedToAxis(FloatSize delta, ScrollEventAxis axis)
     95{
     96    switch (axis) {
     97    case ScrollEventAxis::Horizontal: return FloatSize { delta.width(), 0 };
     98    case ScrollEventAxis::Vertical: return FloatSize { 0, delta.height() };
     99    }
     100
     101    return { };
     102}
     103
     104static FloatSize deltaAlignedToDominantAxis(FloatSize delta)
     105{
     106    auto dominantAxis = dominantAxisFavoringVertical(delta);
     107    return deltaAlignedToAxis(delta, dominantAxis);
     108}
     109
     110static std::optional<BoxSide> affectedSideOnDominantAxis(FloatSize delta)
     111{
     112    auto dominantAxis = dominantAxisFavoringVertical(delta);
     113    return ScrollableArea::targetSideForScrollDelta(delta, dominantAxis);
     114}
     115
     116static bool isHorizontalSide(std::optional<BoxSide> side)
     117{
     118    return side && (*side == BoxSide::Left || *side == BoxSide::Right);
     119}
     120
     121static bool isVerticalSide(std::optional<BoxSide> side)
     122{
     123    return side && (*side == BoxSide::Top || *side == BoxSide::Bottom);
    93124}
    94125
     
    103134    if (wheelEvent.phase() == PlatformWheelEventPhase::Began) {
    104135        // FIXME: Trying to decide if a gesture is horizontal or vertical at the "began" phase is very error-prone.
    105         auto direction = directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
    106         if (direction && m_client.isPinnedForScrollDelta(FloatSize(-wheelEvent.deltaX(), 0)) && !shouldRubberBandInDirection(direction.value()))
     136        auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
     137        if (horizontalSide && m_client.isPinnedOnSide(*horizontalSide) && !shouldRubberBandOnSide(*horizontalSide))
    107138            return false;
    108139
    109         direction = directionFromEvent(wheelEvent, ScrollEventAxis::Vertical);
    110         if (direction && m_client.isPinnedForScrollDelta(FloatSize(0, -wheelEvent.deltaY())) && !shouldRubberBandInDirection(direction.value()))
     140        auto verticalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
     141        if (verticalSide && m_client.isPinnedOnSide(*verticalSide) && !shouldRubberBandOnSide(*verticalSide))
    111142            return false;
    112143
     
    156187    delta += eventCoalescedDelta;
    157188
    158     delta = convertToProminentAxisFavoringVertical(delta);
     189    // FIXME: All of the code below could be simplified since predominantAxis is known, and we zero out the delta on the other axis.
     190    auto affectedSide = affectedSideOnDominantAxis(delta);
     191
    159192    float deltaX = delta.width();
    160193    float deltaY = delta.height();
     
    178211
    179212        if (isVerticallyStretched) {
    180             if (!isHorizontallyStretched && m_client.isPinnedForScrollDelta(FloatSize(deltaX, 0))) {
     213            if (!isHorizontallyStretched && isHorizontalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
    181214                // Stretching only in the vertical.
    182215                if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
     
    190223        } else if (isHorizontallyStretched) {
    191224            // Stretching only in the horizontal.
    192             if (m_client.isPinnedForScrollDelta(FloatSize(0, deltaY))) {
     225            if (isVerticalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
    193226                if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
    194227                    deltaY = 0;
     
    201234        } else {
    202235            // Not stretching at all yet.
    203             if (m_client.isPinnedForScrollDelta(FloatSize(deltaX, deltaY))) {
     236            if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
    204237                if (fabsf(deltaY) >= fabsf(deltaX)) {
    205238                    if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
     
    234267            }
    235268        } else {
     269            affectedSide = affectedSideOnDominantAxis({ deltaX, deltaY });
    236270            if (deltaX) {
    237271                if (!m_client.allowsHorizontalStretching(wheelEvent)) {
     
    239273                    eventCoalescedDelta.setWidth(0);
    240274                    handled = false;
    241                 } else if (!isHorizontallyStretched && !m_client.isPinnedForScrollDelta(FloatSize(deltaX, 0))) {
     275                } else if (!isHorizontallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
    242276                    deltaX *= scrollWheelMultiplier();
    243277
     
    252286                    eventCoalescedDelta.setHeight(0);
    253287                    handled = false;
    254                 } else if (!isVerticallyStretched && !m_client.isPinnedForScrollDelta(FloatSize(0, deltaY))) {
     288                } else if (!isVerticallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
    255289                    deltaY *= scrollWheelMultiplier();
    256290
     
    263297
    264298            if (m_momentumScrollInProgress) {
    265                 if ((m_client.isPinnedForScrollDelta(eventCoalescedDelta) || eventCoalescedDelta.isZero()) && m_lastMomentumScrollTimestamp) {
     299                auto sideAffectedByEventDelta = affectedSideOnDominantAxis(eventCoalescedDelta);
     300                if ((!sideAffectedByEventDelta || m_client.isPinnedOnSide(*sideAffectedByEventDelta)) && m_lastMomentumScrollTimestamp) {
    266301                    m_ignoreMomentumScrolls = true;
    267302                    m_momentumScrollInProgress = false;
     
    294329FloatSize ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent& wheelEvent)
    295330{
    296     return convertToProminentAxisFavoringVertical(wheelEvent.delta());
    297 }
    298 
    299 std::optional<ScrollDirection> ScrollingEffectsController::directionFromEvent(const PlatformWheelEvent& wheelEvent, std::optional<ScrollEventAxis> axis, WheelAxisBias bias)
    300 {
    301     // FIXME: It's impossible to infer direction from a single event, since the start of a gesture is either zero or
    302     // has small deltas on both axes.
    303 
    304     auto wheelDelta = FloatSize { wheelEvent.deltaX(), wheelEvent.deltaY() };
    305     if (bias == WheelAxisBias::Vertical)
    306         wheelDelta = wheelDeltaBiasingTowardsVertical(wheelEvent);
    307 
    308     if (axis) {
    309         switch (axis.value()) {
    310         case ScrollEventAxis::Vertical:
    311             if (wheelDelta.height() < 0)
    312                 return ScrollDown;
    313 
    314             if (wheelDelta.height() > 0)
    315                 return ScrollUp;
    316             break;
    317 
    318         case ScrollEventAxis::Horizontal:
    319             if (wheelDelta.width() > 0)
    320                 return ScrollLeft;
    321 
    322             if (wheelDelta.width() < 0)
    323                 return ScrollRight;
    324         }
    325 
    326         return std::nullopt;
    327     }
    328 
    329     // Check Y first because vertical scrolling dominates.
    330     if (wheelDelta.height() < 0)
    331         return ScrollDown;
    332 
    333     if (wheelDelta.height() > 0)
    334         return ScrollUp;
    335 
    336     if (wheelDelta.width() > 0)
    337         return ScrollLeft;
    338 
    339     if (wheelDelta.width() < 0)
    340         return ScrollRight;
    341 
    342     return std::nullopt;
     331    return deltaAlignedToDominantAxis(wheelEvent.delta());
    343332}
    344333
     
    494483}
    495484
    496 bool ScrollingEffectsController::shouldRubberBandInHorizontalDirection(const PlatformWheelEvent& wheelEvent) const
    497 {
    498     auto direction = directionFromEvent(wheelEvent, ScrollEventAxis::Horizontal);
    499     if (direction)
    500         return shouldRubberBandInDirection(direction.value());
    501 
    502     return true;
    503 }
    504 
    505 bool ScrollingEffectsController::shouldRubberBandInDirection(ScrollDirection direction) const
    506 {
    507     return m_client.shouldRubberBandInDirection(direction);
     485bool ScrollingEffectsController::shouldRubberBandOnSide(BoxSide side) const
     486{
     487    return m_client.shouldRubberBandOnSide(side);
    508488}
    509489
Note: See TracChangeset for help on using the changeset viewer.