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

Changeset 283393 in webkit


Ignore:
Timestamp:
Oct 1, 2021, 1:25:48 PM (5 years ago)
Author:
Simon Fraser
Message:

Further cleanup of macOS rubberbanding code
https://bugs.webkit.org/show_bug.cgi?id=231087

Reviewed by Alan Bujtas.

Split chunks of rubber-banding logic into their own functions for clarity,
separating the "compute the delta" and "apply the delta" parts.

  • platform/ScrollingEffectsController.h:
  • platform/mac/ScrollingEffectsController.mm:

(WebCore::ScrollingEffectsController::handleWheelEvent):
(WebCore::ScrollingEffectsController::modifyScrollDeltaForStretching):
(WebCore::ScrollingEffectsController::applyScrollDeltaWithStretching):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r283392 r283393  
     12021-10-01  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Further cleanup of macOS rubberbanding code
     4        https://bugs.webkit.org/show_bug.cgi?id=231087
     5
     6        Reviewed by Alan Bujtas.
     7
     8        Split chunks of rubber-banding logic into their own functions for clarity,
     9        separating the "compute the delta" and "apply the delta" parts.
     10
     11        * platform/ScrollingEffectsController.h:
     12        * platform/mac/ScrollingEffectsController.mm:
     13        (WebCore::ScrollingEffectsController::handleWheelEvent):
     14        (WebCore::ScrollingEffectsController::modifyScrollDeltaForStretching):
     15        (WebCore::ScrollingEffectsController::applyScrollDeltaWithStretching):
     16
    1172021-10-01  Alan Bujtas  <zalan@apple.com>
    218
  • trunk/Source/WebCore/platform/ScrollingEffectsController.h

    r283355 r283393  
    199199    void stopDeferringWheelEventTestCompletionDueToScrollSnapping();
    200200
     201    bool modifyScrollDeltaForStretching(const PlatformWheelEvent&, FloatSize&, bool isHorizontallyStretched, bool isVerticallyStretched);
     202    bool applyScrollDeltaWithStretching(const PlatformWheelEvent&, FloatSize, bool isHorizontallyStretched, bool isVerticallyStretched);
     203
    201204    void startRubberbandAnimationIfNecessary();
    202205    void startRubberbandAnimation();
  • trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm

    r283355 r283393  
    177177    }
    178178
    179     // Reset unapplied overscroll because we may decide to remove delta at various points and put it into this value.
    180     auto delta = std::exchange(m_unappliedOverscrollDelta, { });
    181 
    182179    IntSize stretchAmount = m_client.stretchAmount();
    183180    bool isVerticallyStretched = stretchAmount.height();
    184181    bool isHorizontallyStretched = stretchAmount.width();
    185182
    186     auto eventCoalescedDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();
    187     delta += eventCoalescedDelta;
    188 
    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 
    192     float deltaX = delta.width();
    193     float deltaY = delta.height();
    194 
    195     bool shouldStretch = false;
     183    // Much of this code, including this use of unaccelerated deltas when stretched, is based on AppKit behavior.
     184    auto eventDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();
     185
     186    // Reset unapplied overscroll because we may decide to remove delta at various points and put it into this value.
     187    auto delta = std::exchange(m_unappliedOverscrollDelta, { });
     188    delta += eventDelta;
    196189
    197190    auto momentumPhase = wheelEvent.momentumPhase();
    198 
    199191    if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhase::Began || momentumPhase == PlatformWheelEventPhase::Changed))
    200192        m_momentumScrollInProgress = true;
    201193
     194    bool shouldStretch = false;
    202195    auto timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
    203196    if (m_inScrollGesture || m_momentumScrollInProgress) {
    204197        if (m_lastMomentumScrollTimestamp && timeDelta > 0_s && timeDelta < scrollVelocityZeroingTimeout) {
    205             m_momentumVelocity = eventCoalescedDelta / timeDelta.seconds();
     198            m_momentumVelocity = eventDelta / timeDelta.seconds();
    206199            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
    207200        } else {
     
    210203        }
    211204
    212         if (isVerticallyStretched) {
    213             if (!isHorizontallyStretched && isHorizontalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
    214                 // Stretching only in the vertical.
    215                 if (deltaY && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
    216                     deltaX = 0;
    217                 else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
    218                     m_unappliedOverscrollDelta.expand(deltaX, 0);
    219                     deltaX = 0;
    220                 } else
    221                     m_unappliedOverscrollDelta.expand(deltaX, 0);
    222             }
    223         } else if (isHorizontallyStretched) {
    224             // Stretching only in the horizontal.
    225             if (isVerticalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
    226                 if (deltaX && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
    227                     deltaY = 0;
    228                 else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
    229                     m_unappliedOverscrollDelta.expand(0, deltaY);
    230                     deltaY = 0;
    231                 } else
    232                     m_unappliedOverscrollDelta.expand(0, deltaY);
    233             }
    234         } else {
    235             // Not stretching at all yet.
    236             if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
    237                 if (fabsf(deltaY) >= fabsf(deltaX)) {
    238                     if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
    239                         m_unappliedOverscrollDelta.expand(deltaX, 0);
    240                         deltaX = 0;
    241                     } else
    242                         m_unappliedOverscrollDelta.expand(deltaX, 0);
    243                 }
    244 
    245                 if (!m_client.allowsHorizontalStretching(wheelEvent))
    246                     deltaX = 0;
    247 
    248                 if (!m_client.allowsVerticalStretching(wheelEvent))
    249                     deltaY = 0;
    250 
    251                 shouldStretch = deltaX || deltaY;
    252             }
    253         }
     205        shouldStretch = modifyScrollDeltaForStretching(wheelEvent, delta, isHorizontallyStretched, isVerticallyStretched);
    254206    }
    255207
    256208    bool handled = true;
    257209
    258     if (deltaX || deltaY) {
    259         if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
    260             if (deltaY) {
    261                 deltaY *= scrollWheelMultiplier();
    262                 m_client.immediateScrollBy(FloatSize(0, deltaY));
    263             }
    264             if (deltaX) {
    265                 deltaX *= scrollWheelMultiplier();
    266                 m_client.immediateScrollBy(FloatSize(deltaX, 0));
    267             }
    268         } else {
    269             affectedSide = affectedSideOnDominantAxis({ deltaX, deltaY });
    270             if (deltaX) {
    271                 if (!m_client.allowsHorizontalStretching(wheelEvent)) {
    272                     deltaX = 0;
    273                     eventCoalescedDelta.setWidth(0);
    274                     handled = false;
    275                 } else if (!isHorizontallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
    276                     deltaX *= scrollWheelMultiplier();
    277 
    278                     m_client.immediateScrollByWithoutContentEdgeConstraints(FloatSize(deltaX, 0));
    279                     deltaX = 0;
    280                 }
    281             }
    282 
    283             if (deltaY) {
    284                 if (!m_client.allowsVerticalStretching(wheelEvent)) {
    285                     deltaY = 0;
    286                     eventCoalescedDelta.setHeight(0);
    287                     handled = false;
    288                 } else if (!isVerticallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
    289                     deltaY *= scrollWheelMultiplier();
    290 
    291                     m_client.immediateScrollByWithoutContentEdgeConstraints(FloatSize(0, deltaY));
    292                     deltaY = 0;
    293                 }
    294             }
    295 
    296             IntSize stretchAmount = m_client.stretchAmount();
    297 
     210    if (!delta.isZero()) {
     211        if (shouldStretch || isVerticallyStretched || isHorizontallyStretched) {
     212            if (delta.width() && !m_client.allowsHorizontalStretching(wheelEvent))
     213                handled = false;
     214
     215            if (delta.height() && !m_client.allowsVerticalStretching(wheelEvent))
     216                handled = false;
     217
     218            bool canStartAnimation = applyScrollDeltaWithStretching(wheelEvent, delta, isHorizontallyStretched, isVerticallyStretched);
    298219            if (m_momentumScrollInProgress) {
    299                 auto sideAffectedByEventDelta = affectedSideOnDominantAxis(eventCoalescedDelta);
    300                 if ((!sideAffectedByEventDelta || m_client.isPinnedOnSide(*sideAffectedByEventDelta)) && m_lastMomentumScrollTimestamp) {
     220                if (canStartAnimation && m_lastMomentumScrollTimestamp) {
    301221                    m_ignoreMomentumScrolls = true;
    302222                    m_momentumScrollInProgress = false;
     
    304224                }
    305225            }
    306 
    307             m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
    308             m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
    309 
    310             FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
    311 
    312             LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::handleWheelEvent() - stretchScrollForce " << m_stretchScrollForce << " move delta " << FloatSize(deltaX, deltaY) << " dampedDelta " << dampedDelta);
    313 
    314             m_client.immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
     226        } else {
     227            delta.scale(scrollWheelMultiplier());
     228            m_client.immediateScrollBy(delta);
    315229        }
    316230    }
     
    325239
    326240    return handled;
     241}
     242
     243bool ScrollingEffectsController::modifyScrollDeltaForStretching(const PlatformWheelEvent& wheelEvent, FloatSize& delta, bool isHorizontallyStretched, bool isVerticallyStretched)
     244{
     245    auto affectedSide = affectedSideOnDominantAxis(delta);
     246    if (isVerticallyStretched) {
     247        if (!isHorizontallyStretched && isHorizontalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
     248            // Stretching only in the vertical.
     249            if (delta.height() && (fabsf(delta.width() / delta.height()) < rubberbandDirectionLockStretchRatio))
     250                delta.setWidth(0);
     251            else if (fabsf(delta.width()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
     252                m_unappliedOverscrollDelta.expand(delta.width(), 0);
     253                delta.setWidth(0);
     254            } else
     255                m_unappliedOverscrollDelta.expand(delta.width(), 0);
     256        }
     257
     258        return false;
     259    }
     260
     261    if (isHorizontallyStretched) {
     262        // Stretching only in the horizontal.
     263        if (isVerticalSide(affectedSide) && m_client.isPinnedOnSide(*affectedSide)) {
     264            if (delta.width() && (fabsf(delta.height() / delta.width()) < rubberbandDirectionLockStretchRatio))
     265                delta.setHeight(0);
     266            else if (fabsf(delta.height()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
     267                m_unappliedOverscrollDelta.expand(0, delta.height());
     268                delta.setHeight(0);
     269            } else
     270                m_unappliedOverscrollDelta.expand(0, delta.height());
     271        }
     272
     273        return false;
     274    }
     275
     276    // Not stretching at all yet.
     277    if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
     278        if (fabsf(delta.height()) >= fabsf(delta.width())) {
     279            if (fabsf(delta.width()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
     280                m_unappliedOverscrollDelta.expand(delta.width(), 0);
     281                delta.setWidth(0);
     282            } else
     283                m_unappliedOverscrollDelta.expand(delta.width(), 0);
     284        }
     285
     286        if (!m_client.allowsHorizontalStretching(wheelEvent))
     287            delta.setWidth(0);
     288
     289        if (!m_client.allowsVerticalStretching(wheelEvent))
     290            delta.setHeight(0);
     291
     292        return !delta.isZero();
     293    }
     294   
     295    return false;
     296}
     297
     298bool ScrollingEffectsController::applyScrollDeltaWithStretching(const PlatformWheelEvent& wheelEvent, FloatSize delta, bool isHorizontallyStretched, bool isVerticallyStretched)
     299{
     300    auto eventDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();
     301    auto affectedSide = affectedSideOnDominantAxis(delta);
     302
     303    FloatSize deltaToScroll;
     304
     305    if (delta.width()) {
     306        if (!m_client.allowsHorizontalStretching(wheelEvent)) {
     307            delta.setWidth(0);
     308            eventDelta.setWidth(0);
     309        } else if (!isHorizontallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
     310            delta.scale(scrollWheelMultiplier(), 1);
     311            deltaToScroll += FloatSize { delta.width(), 0 };
     312            delta.setWidth(0);
     313        }
     314    }
     315
     316    if (delta.height()) {
     317        if (!m_client.allowsVerticalStretching(wheelEvent)) {
     318            delta.setHeight(0);
     319            eventDelta.setHeight(0);
     320        } else if (!isVerticallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
     321            delta.scale(1, scrollWheelMultiplier());
     322            deltaToScroll += FloatSize { 0, delta.height() };
     323            delta.setHeight(0);
     324        }
     325    }
     326
     327    if (!deltaToScroll.isZero())
     328        m_client.immediateScrollByWithoutContentEdgeConstraints(deltaToScroll);
     329
     330    bool canStartAnimation = false;
     331    if (m_momentumScrollInProgress) {
     332        // Compute canStartAnimation, which looks at isPinnedOnSide(), before applying the stretch delta.
     333        auto sideAffectedByEventDelta = affectedSideOnDominantAxis(eventDelta);
     334        canStartAnimation = !sideAffectedByEventDelta || m_client.isPinnedOnSide(*sideAffectedByEventDelta);
     335    }
     336
     337    m_stretchScrollForce += delta;
     338    auto dampedDelta = FloatSize {
     339        ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())),
     340        ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height()))
     341    };
     342
     343    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::applyScrollDeltaWithStretching() - stretchScrollForce " << m_stretchScrollForce << " move delta " << delta << " dampedDelta " << dampedDelta);
     344
     345    auto stretchAmount = m_client.stretchAmount();
     346    m_client.immediateScrollByWithoutContentEdgeConstraints(dampedDelta - stretchAmount);
     347
     348    return canStartAnimation;
    327349}
    328350
Note: See TracChangeset for help on using the changeset viewer.