Title: [284136] trunk/Source/WebCore
Revision
284136
Author
simon.fra...@apple.com
Date
2021-10-13 17:18:01 -0700 (Wed, 13 Oct 2021)

Log Message

Use a ScrollAnimation for rubber-banding
https://bugs.webkit.org/show_bug.cgi?id=231695

Reviewed by Tim Horton.

The animation that runs when rubber-banding (when you momentum-scroll into an edge,
or stretch and release) was code in updateRubberBandAnimatingState(). Repackage
that code as a ScrollAnimation subclass, which allows it to share code with other
types of scroll animation.

ScrollAnimationRubberBand needs to do non-clamped scrolls, so add a way for ScrollAnimations
to state that they allow this.

Standardize the capitalization of RubberBand.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::scrollTo):
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
(WebCore::ScrollingTreeScrollingNodeDelegateMac::willDoProgrammaticScroll):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberBandAnimation):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation): Deleted.
* platform/ScrollAnimation.cpp:
(WebCore::operator<<):
* platform/ScrollAnimation.h:
(WebCore::ScrollAnimation::clamping const):
* platform/ScrollingEffectsController.cpp:
(WebCore::ScrollingEffectsController::startMomentumScrollWithInitialVelocity): Need to be sure
to stop() any existing animation.
(WebCore::ScrollingEffectsController::scrollAnimationDidUpdate):
(WebCore::ScrollingEffectsController::scrollAnimationWillStart):
(WebCore::ScrollingEffectsController::scrollAnimationDidEnd):
* platform/ScrollingEffectsController.h:
(WebCore::ScrollingEffectsControllerClient::willStartRubberBandAnimation):
(WebCore::ScrollingEffectsControllerClient::didStopRubberBandAnimation):
(WebCore::ScrollingEffectsControllerClient::willStartRubberBandSnapAnimation): Deleted.
(WebCore::ScrollingEffectsControllerClient::didStopRubberbandSnapAnimation): Deleted.
* platform/mac/ScrollAnimationRubberBand.h: Added.
* platform/mac/ScrollAnimationRubberBand.mm: Added.
(elasticDeltaForTimeDelta):
(WebCore::roundTowardZero):
(WebCore::roundToDevicePixelTowardZero):
(WebCore::ScrollAnimationRubberBand::ScrollAnimationRubberBand):
(WebCore::ScrollAnimationRubberBand::startRubberBandAnimation):
(WebCore::ScrollAnimationRubberBand::retargetActiveAnimation):
(WebCore::ScrollAnimationRubberBand::updateScrollExtents):
(WebCore::ScrollAnimationRubberBand::serviceAnimation):
* platform/mac/ScrollingEffectsController.mm:
(WebCore::ScrollingEffectsController::handleWheelEvent):
(WebCore::ScrollingEffectsController::updateRubberBandAnimatingState):
(WebCore::ScrollingEffectsController::stopRubberBanding):
(WebCore::ScrollingEffectsController::startRubberBandAnimation):
(WebCore::ScrollingEffectsController::stopRubberBandAnimation):
(WebCore::ScrollingEffectsController::willStartRubberBandAnimation):
(WebCore::ScrollingEffectsController::didStopRubberBandAnimation):
(WebCore::ScrollingEffectsController::startRubberBandAnimationIfNecessary):
(WebCore::elasticDeltaForTimeDelta): Deleted.
(WebCore::roundTowardZero): Deleted.
(WebCore::roundToDevicePixelTowardZero): Deleted.
(WebCore::ScrollingEffectsController::stopRubberbanding): Deleted.
(WebCore::ScrollingEffectsController::startRubberbandAnimation): Deleted.
(WebCore::ScrollingEffectsController::stopRubberbandAnimation): Deleted.
(WebCore::ScrollingEffectsController::startRubberbandAnimationIfNecessary): Deleted.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (284135 => 284136)


--- trunk/Source/WebCore/ChangeLog	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/ChangeLog	2021-10-14 00:18:01 UTC (rev 284136)
@@ -1,3 +1,71 @@
+2021-10-13  Simon Fraser  <simon.fra...@apple.com>
+
+        Use a ScrollAnimation for rubber-banding
+        https://bugs.webkit.org/show_bug.cgi?id=231695
+
+        Reviewed by Tim Horton.
+
+        The animation that runs when rubber-banding (when you momentum-scroll into an edge,
+        or stretch and release) was code in updateRubberBandAnimatingState(). Repackage
+        that code as a ScrollAnimation subclass, which allows it to share code with other
+        types of scroll animation.
+
+        ScrollAnimationRubberBand needs to do non-clamped scrolls, so add a way for ScrollAnimations
+        to state that they allow this.
+        
+        Standardize the capitalization of RubberBand.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::scrollTo):
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h:
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::willDoProgrammaticScroll):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberBandAnimation):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation): Deleted.
+        * platform/ScrollAnimation.cpp:
+        (WebCore::operator<<):
+        * platform/ScrollAnimation.h:
+        (WebCore::ScrollAnimation::clamping const):
+        * platform/ScrollingEffectsController.cpp:
+        (WebCore::ScrollingEffectsController::startMomentumScrollWithInitialVelocity): Need to be sure
+        to stop() any existing animation.
+        (WebCore::ScrollingEffectsController::scrollAnimationDidUpdate):
+        (WebCore::ScrollingEffectsController::scrollAnimationWillStart):
+        (WebCore::ScrollingEffectsController::scrollAnimationDidEnd):
+        * platform/ScrollingEffectsController.h:
+        (WebCore::ScrollingEffectsControllerClient::willStartRubberBandAnimation):
+        (WebCore::ScrollingEffectsControllerClient::didStopRubberBandAnimation):
+        (WebCore::ScrollingEffectsControllerClient::willStartRubberBandSnapAnimation): Deleted.
+        (WebCore::ScrollingEffectsControllerClient::didStopRubberbandSnapAnimation): Deleted.
+        * platform/mac/ScrollAnimationRubberBand.h: Added.
+        * platform/mac/ScrollAnimationRubberBand.mm: Added.
+        (elasticDeltaForTimeDelta):
+        (WebCore::roundTowardZero):
+        (WebCore::roundToDevicePixelTowardZero):
+        (WebCore::ScrollAnimationRubberBand::ScrollAnimationRubberBand):
+        (WebCore::ScrollAnimationRubberBand::startRubberBandAnimation):
+        (WebCore::ScrollAnimationRubberBand::retargetActiveAnimation):
+        (WebCore::ScrollAnimationRubberBand::updateScrollExtents):
+        (WebCore::ScrollAnimationRubberBand::serviceAnimation):
+        * platform/mac/ScrollingEffectsController.mm:
+        (WebCore::ScrollingEffectsController::handleWheelEvent):
+        (WebCore::ScrollingEffectsController::updateRubberBandAnimatingState):
+        (WebCore::ScrollingEffectsController::stopRubberBanding):
+        (WebCore::ScrollingEffectsController::startRubberBandAnimation):
+        (WebCore::ScrollingEffectsController::stopRubberBandAnimation):
+        (WebCore::ScrollingEffectsController::willStartRubberBandAnimation):
+        (WebCore::ScrollingEffectsController::didStopRubberBandAnimation):
+        (WebCore::ScrollingEffectsController::startRubberBandAnimationIfNecessary):
+        (WebCore::elasticDeltaForTimeDelta): Deleted.
+        (WebCore::roundTowardZero): Deleted.
+        (WebCore::roundToDevicePixelTowardZero): Deleted.
+        (WebCore::ScrollingEffectsController::stopRubberbanding): Deleted.
+        (WebCore::ScrollingEffectsController::startRubberbandAnimation): Deleted.
+        (WebCore::ScrollingEffectsController::stopRubberbandAnimation): Deleted.
+        (WebCore::ScrollingEffectsController::startRubberbandAnimationIfNecessary): Deleted.
+
 2021-10-13  Jean-Yves Avenard  <j...@apple.com>
 
         Clearly distinguish serial from concurrent WorkQueue

Modified: trunk/Source/WebCore/SourcesCocoa.txt (284135 => 284136)


--- trunk/Source/WebCore/SourcesCocoa.txt	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2021-10-14 00:18:01 UTC (rev 284136)
@@ -491,10 +491,11 @@
 platform/mac/PublicSuffixMac.mm
 platform/mac/SSLKeyGeneratorMac.mm
 platform/mac/ScrollAnimatorMac.mm @no-unify
-platform/mac/ScrollingEffectsController.mm
+platform/mac/ScrollAnimationRubberBand.mm
 platform/mac/ScrollViewMac.mm
 platform/mac/ScrollbarsControllerMac.mm @no-unify
 platform/mac/ScrollbarThemeMac.mm @no-unify
+platform/mac/ScrollingEffectsController.mm
 platform/mac/ScrollingMomentumCalculatorMac.mm
 platform/mac/SerializedPlatformDataCueMac.mm
 platform/mac/StringUtilities.mm

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (284135 => 284136)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-14 00:18:01 UTC (rev 284136)
@@ -6214,6 +6214,8 @@
 		0F36E7381BD184B9002DB891 /* LayoutSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutSize.cpp; sourceTree = "<group>"; };
 		0F37F0832202AC8F00A89C0B /* ScrollingTreeScrollingNodeDelegateMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeScrollingNodeDelegateMac.mm; sourceTree = "<group>"; };
 		0F37F0842202ACB700A89C0B /* ScrollingTreeScrollingNodeDelegateMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeScrollingNodeDelegateMac.h; sourceTree = "<group>"; };
+		0F38186A2708D20100414F32 /* ScrollAnimationRubberBand.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollAnimationRubberBand.mm; sourceTree = "<group>"; };
+		0F38186C2708D20200414F32 /* ScrollAnimationRubberBand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollAnimationRubberBand.h; sourceTree = "<group>"; };
 		0F3DD44D12F5EA1B000D9190 /* ShadowBlur.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowBlur.cpp; sourceTree = "<group>"; };
 		0F3DD44E12F5EA1B000D9190 /* ShadowBlur.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowBlur.h; sourceTree = "<group>"; };
 		0F3F0E57157030C3006DA57F /* RenderGeometryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderGeometryMap.cpp; sourceTree = "<group>"; };
@@ -22352,6 +22354,8 @@
 				4634592B1AC2271000ECB71C /* PowerObserverMac.cpp */,
 				46DBB64E1AB8C96F00D9A813 /* PowerObserverMac.h */,
 				0081FEFE16B0A2B6008AAA7A /* PublicSuffixMac.mm */,
+				0F38186C2708D20200414F32 /* ScrollAnimationRubberBand.h */,
+				0F38186A2708D20100414F32 /* ScrollAnimationRubberBand.mm */,
 				BCAE1FA512939DB7004CB026 /* ScrollAnimatorMac.h */,
 				BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */,
 				0F02245426F15D75000265C3 /* ScrollbarsControllerMac.h */,

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


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.h	2021-10-14 00:18:01 UTC (rev 284136)
@@ -87,7 +87,7 @@
 
     bool shouldRubberBandOnSide(BoxSide) const final;
     void immediateScrollBy(const FloatSize&, ScrollClamping = ScrollClamping::Clamped) final;
-    void didStopRubberbandSnapAnimation() final;
+    void didStopRubberBandAnimation() final;
     void rubberBandingStateChanged(bool) final;
     void adjustScrollPositionToBoundsIfNecessary() final;
 

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


--- trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm	2021-10-14 00:18:01 UTC (rev 284136)
@@ -131,7 +131,7 @@
 {
     if (scrollPositionIsNotRubberbandingEdge(targetPosition)) {
         LOG(Scrolling, "ScrollingTreeScrollingNodeDelegateMac::willDoProgrammaticScroll() - scrolling away from rubberbanding edge so stopping rubberbanding");
-        m_scrollController.stopRubberbanding();
+        m_scrollController.stopRubberBanding();
     }
 }
 
@@ -339,7 +339,7 @@
     scrollingNode().scrollBy(delta, clamping);
 }
 
-void ScrollingTreeScrollingNodeDelegateMac::didStopRubberbandSnapAnimation()
+void ScrollingTreeScrollingNodeDelegateMac::didStopRubberBandAnimation()
 {
     // Since the rubberband timer has stopped, totalContentsSizeForRubberBand can be synchronized with totalContentsSize.
     scrollingNode().setTotalContentsSizeForRubberBand(totalContentsSize());

Modified: trunk/Source/WebCore/platform/ScrollAnimation.cpp (284135 => 284136)


--- trunk/Source/WebCore/platform/ScrollAnimation.cpp	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/platform/ScrollAnimation.cpp	2021-10-14 00:18:01 UTC (rev 284136)
@@ -36,6 +36,7 @@
     case ScrollAnimation::Type::Smooth: ts << "smooth"; break;
     case ScrollAnimation::Type::Kinetic: ts << "kinetic"; break;
     case ScrollAnimation::Type::Momentum: ts << "momentum"; break;
+    case ScrollAnimation::Type::RubberBand: ts << "rubber-band"; break;
     }
     return ts;
 }

Modified: trunk/Source/WebCore/platform/ScrollAnimation.h (284135 => 284136)


--- trunk/Source/WebCore/platform/ScrollAnimation.h	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/platform/ScrollAnimation.h	2021-10-14 00:18:01 UTC (rev 284136)
@@ -54,6 +54,7 @@
         Smooth,
         Kinetic,
         Momentum,
+        RubberBand,
     };
 
     ScrollAnimation(Type animationType, ScrollAnimationClient& client)
@@ -64,6 +65,8 @@
     
     Type type() const { return m_animationType; }
 
+    virtual ScrollClamping clamping() const { return ScrollClamping::Clamped; }
+
     virtual bool retargetActiveAnimation(const FloatPoint& newDestinationOffset) = 0;
     virtual void stop()
     {
@@ -75,7 +78,7 @@
     virtual void updateScrollExtents() { };
     
     FloatPoint currentOffset() const { return m_currentOffset; }
-    
+
     virtual void serviceAnimation(MonotonicTime) = 0;
 
 protected:

Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.cpp (284135 => 284136)


--- trunk/Source/WebCore/platform/ScrollingEffectsController.cpp	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.cpp	2021-10-14 00:18:01 UTC (rev 284136)
@@ -41,6 +41,10 @@
 #include "ScrollAnimationKinetic.h"
 #endif
 
+#if HAVE(RUBBER_BANDING)
+#include "ScrollAnimationRubberBand.h"
+#endif
+
 namespace WebCore {
 
 ScrollingEffectsController::ScrollingEffectsController(ScrollingEffectsControllerClient& client)
@@ -58,7 +62,7 @@
             m_currentAnimation = nullptr;
     }
 
-    updateRubberBandAnimatingState(currentTime);
+    updateRubberBandAnimatingState();
     updateKeyboardScrollingAnimatingState(currentTime);
     
     startOrStopAnimationCallbacks();
@@ -125,9 +129,8 @@
 bool ScrollingEffectsController::startMomentumScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatSize& initialVelocity, const FloatSize& initialDelta, const Function<FloatPoint(const FloatPoint&)>& destinationModifier)
 {
     if (m_currentAnimation) {
-        if (is<ScrollAnimationMomentum>(m_currentAnimation.get()))
-            m_currentAnimation->stop();
-        else
+        m_currentAnimation->stop();
+        if (!is<ScrollAnimationMomentum>(m_currentAnimation.get()))
             m_currentAnimation = nullptr;
     }
 
@@ -429,20 +432,26 @@
     m_client.keyboardScrollingAnimator()->updateKeyboardScrollPosition(currentTime);
 }
 
-void ScrollingEffectsController::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& currentOffset)
+void ScrollingEffectsController::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& scrollOffset)
 {
-    auto scrollDelta = currentOffset - m_client.scrollOffset();
+    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController " << this << " scrollAnimationDidUpdate " << animation << " (main thread " << isMainThread() << ") scrolling to " << scrollOffset);
 
-    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController " << this << " scrollAnimationDidUpdate " << animation << " (main thread " << isMainThread() << ") scrolling by " << scrollDelta);
-    UNUSED_PARAM(animation);
+    auto currentOffset = m_client.scrollOffset();
+    auto scrollDelta = scrollOffset - currentOffset;
 
-    m_client.immediateScrollBy(scrollDelta);
+    m_client.immediateScrollBy(scrollDelta, animation.clamping());
 }
 
 void ScrollingEffectsController::scrollAnimationWillStart(ScrollAnimation& animation)
 {
     LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController " << this << " scrollAnimationWillStart " << animation);
+
+#if HAVE(RUBBER_BANDING)
+    if (is<ScrollAnimationRubberBand>(animation))
+        willStartRubberBandAnimation();
+#else
     UNUSED_PARAM(animation);
+#endif
 
     startOrStopAnimationCallbacks();
 }
@@ -450,7 +459,6 @@
 void ScrollingEffectsController::scrollAnimationDidEnd(ScrollAnimation& animation)
 {
     LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController " << this << " scrollAnimationDidEnd " << animation);
-    UNUSED_PARAM(animation);
 
     if (usesScrollSnap() && m_isAnimatingScrollSnap) {
         m_scrollSnapState->transitionToDestinationReachedState();
@@ -457,6 +465,13 @@
         stopScrollSnapAnimation();
     }
 
+#if HAVE(RUBBER_BANDING)
+    if (is<ScrollAnimationRubberBand>(animation))
+        didStopRubberBandAnimation();
+#else
+    UNUSED_PARAM(animation);
+#endif
+
     // FIXME: Need to track state better and only call this when the running animation is for CSS smooth scrolling. Calling should be harmless, though.
     m_client.didStopAnimatedScroll();
     startOrStopAnimationCallbacks();
@@ -482,7 +497,7 @@
 {
 }
 
-void ScrollingEffectsController::updateRubberBandAnimatingState(MonotonicTime)
+void ScrollingEffectsController::updateRubberBandAnimatingState()
 {
 }
 

Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.h (284135 => 284136)


--- trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-10-14 00:18:01 UTC (rev 284136)
@@ -100,8 +100,8 @@
 
     virtual bool shouldRubberBandOnSide(BoxSide) const = 0;
 
-    virtual void willStartRubberBandSnapAnimation() { }
-    virtual void didStopRubberbandSnapAnimation() { }
+    virtual void willStartRubberBandAnimation() { }
+    virtual void didStopRubberBandAnimation() { }
 
     virtual void rubberBandingStateChanged(bool) { }
 #endif
@@ -174,13 +174,13 @@
     // Returns true if handled.
     bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
 
-    void stopRubberbanding();
+    void stopRubberBanding();
     bool isRubberBandInProgress() const;
     RectEdges<bool> rubberBandingEdges() const { return m_rubberBandingEdges; }
 #endif
 
 private:
-    void updateRubberBandAnimatingState(MonotonicTime);
+    void updateRubberBandAnimatingState();
     void updateKeyboardScrollingAnimatingState(MonotonicTime);
 
     void setIsAnimatingRubberBand(bool);
@@ -200,10 +200,14 @@
     bool modifyScrollDeltaForStretching(const PlatformWheelEvent&, FloatSize&, bool isHorizontallyStretched, bool isVerticallyStretched);
     bool applyScrollDeltaWithStretching(const PlatformWheelEvent&, FloatSize, bool isHorizontallyStretched, bool isVerticallyStretched);
 
-    void startRubberbandAnimationIfNecessary();
-    void startRubberbandAnimation();
-    void stopRubberbandAnimation();
+    void startRubberBandAnimationIfNecessary();
 
+    void startRubberBandAnimation(const FloatPoint& targetOffset, const FloatSize& initialVelocity, const FloatSize& initialOverscroll);
+    void stopRubberBandAnimation();
+
+    void willStartRubberBandAnimation();
+    void didStopRubberBandAnimation();
+
     bool shouldRubberBandOnSide(BoxSide) const;
     bool isRubberBandInProgressInternal() const;
     void updateRubberBandingState();
@@ -254,10 +258,6 @@
     std::unique_ptr<ScrollingEffectsControllerTimer> m_statelessSnapTransitionTimer;
 
 #if HAVE(RUBBER_BANDING)
-    // Rubber band state.
-    MonotonicTime m_startTime;
-    FloatSize m_startStretch;
-    FloatSize m_origVelocity;
     RectEdges<bool> m_rubberBandingEdges;
 #endif
 

Added: trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.h (0 => 284136)


--- trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.h	2021-10-14 00:18:01 UTC (rev 284136)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ScrollAnimation.h"
+
+#if HAVE(RUBBER_BANDING)
+
+namespace WebCore {
+
+class ScrollAnimationRubberBand final: public ScrollAnimation {
+public:
+    ScrollAnimationRubberBand(ScrollAnimationClient&);
+    virtual ~ScrollAnimationRubberBand();
+
+    // targetOffset is the scroll offset when the animation has finished (i.e. scrolled to an edge).
+    bool startRubberBandAnimation(const FloatPoint& targetOffset, const FloatSize& initialVelocity, const FloatSize& initialOverscroll);
+
+private:
+    void updateScrollExtents() final;
+    void serviceAnimation(MonotonicTime) final;
+    bool retargetActiveAnimation(const FloatPoint&) final;
+    ScrollClamping clamping() const final { return ScrollClamping::Unclamped; }
+
+    bool animateScroll(MonotonicTime);
+
+    FloatPoint m_targetOffset;
+    FloatSize m_initialVelocity;
+    FloatSize m_initialOverscroll;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_SCROLL_ANIMATION(WebCore::ScrollAnimationRubberBand, type() == WebCore::ScrollAnimation::Type::RubberBand)
+
+#endif // HAVE(RUBBER_BANDING)

Added: trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.mm (0 => 284136)


--- trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimationRubberBand.mm	2021-10-14 00:18:01 UTC (rev 284136)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "ScrollAnimationRubberBand.h"
+
+#if HAVE(RUBBER_BANDING)
+
+#import "FloatPoint.h"
+#import "GeometryUtilities.h"
+#import <pal/spi/mac/NSScrollViewSPI.h>
+
+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, Seconds elapsedTime)
+{
+    return _NSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime.seconds());
+}
+
+namespace WebCore {
+
+static inline float roundTowardZero(float num)
+{
+    return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
+}
+
+static inline float roundToDevicePixelTowardZero(float num)
+{
+    float roundedNum = roundf(num);
+    if (fabs(num - roundedNum) < 0.125)
+        num = roundedNum;
+
+    return roundTowardZero(num);
+}
+
+ScrollAnimationRubberBand::ScrollAnimationRubberBand(ScrollAnimationClient& client)
+    : ScrollAnimation(Type::RubberBand, client)
+{
+}
+
+ScrollAnimationRubberBand::~ScrollAnimationRubberBand() = default;
+
+bool ScrollAnimationRubberBand::startRubberBandAnimation(const FloatPoint& targetOffset, const FloatSize& initialVelocity, const FloatSize& initialOverscroll)
+{
+    m_targetOffset = targetOffset;
+    m_initialVelocity = initialVelocity;
+    m_initialOverscroll = initialOverscroll;
+
+    didStart(MonotonicTime::now());
+    return true;
+}
+
+bool ScrollAnimationRubberBand::retargetActiveAnimation(const FloatPoint&)
+{
+    return false;
+}
+
+void ScrollAnimationRubberBand::updateScrollExtents()
+{
+    // FIXME: If we're rubberbanding at the bottom and the content size changes we should fix up m_targetOffset.
+}
+
+void ScrollAnimationRubberBand::serviceAnimation(MonotonicTime currentTime)
+{
+    auto elapsedTime = timeSinceStart(currentTime);
+
+    // This is very similar to ScrollingMomentumCalculator logic, but I wasn't able to get to ScrollingMomentumCalculator to
+    // give the correct behavior when starting a rubberband with initial velocity (i.e. bouncing).
+
+    auto rubberBandOffset = FloatSize {
+        roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_initialOverscroll.width(), -m_initialVelocity.width(), elapsedTime)),
+        roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_initialOverscroll.height(), -m_initialVelocity.height(), elapsedTime))
+    };
+
+    bool animationComplete = rubberBandOffset.isZero();
+    m_currentOffset = m_targetOffset + rubberBandOffset;
+
+    m_client.scrollAnimationDidUpdate(*this, m_currentOffset);
+
+    if (animationComplete)
+        didEnd();
+}
+
+} // namespace WebCore
+
+#endif // HAVE(RUBBER_BANDING)

Modified: trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm (284135 => 284136)


--- trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-10-14 00:09:18 UTC (rev 284135)
+++ trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-10-14 00:18:01 UTC (rev 284136)
@@ -28,6 +28,7 @@
 
 #import "Logging.h"
 #import "PlatformWheelEvent.h"
+#import "ScrollAnimationRubberBand.h"
 #import "ScrollExtents.h"
 #import "WheelEventTestMonitor.h"
 #import <pal/spi/mac/NSScrollViewSPI.h>
@@ -43,11 +44,6 @@
 static const float rubberbandDirectionLockStretchRatio = 1;
 static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
 
-static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, Seconds elapsedTime)
-{
-    return _NSElasticDeltaForTimeDelta(initialPosition, initialVelocity, elapsedTime.seconds());
-}
-
 static float elasticDeltaForReboundDelta(float delta)
 {
     return _NSElasticDeltaForReboundDelta(delta);
@@ -142,7 +138,7 @@
         m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
         m_unappliedOverscrollDelta = { };
 
-        stopRubberbandAnimation();
+        stopRubberBandAnimation();
         updateRubberBandingState();
         return true;
     }
@@ -149,7 +145,7 @@
 
     if (wheelEvent.phase() == PlatformWheelEventPhase::Ended) {
         // FIXME: This triggers the rubberband timer even when we don't start rubberbanding.
-        startRubberbandAnimationIfNecessary();
+        startRubberBandAnimationIfNecessary();
         updateRubberBandingState();
         return true;
     }
@@ -213,7 +209,7 @@
                 if (canStartAnimation && m_lastMomentumScrollTimestamp) {
                     m_ignoreMomentumScrolls = true;
                     m_momentumScrollInProgress = false;
-                    startRubberbandAnimationIfNecessary();
+                    startRubberBandAnimationIfNecessary();
                 }
             }
         } else {
@@ -346,22 +342,8 @@
     return deltaAlignedToDominantAxis(wheelEvent.delta());
 }
 
-static inline float roundTowardZero(float num)
+void ScrollingEffectsController::updateRubberBandAnimatingState()
 {
-    return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
-}
-
-static inline float roundToDevicePixelTowardZero(float num)
-{
-    float roundedNum = roundf(num);
-    if (fabs(num - roundedNum) < 0.125)
-        num = roundedNum;
-
-    return roundTowardZero(num);
-}
-
-void ScrollingEffectsController::updateRubberBandAnimatingState(MonotonicTime currentTime)
-{
     if (!m_isAnimatingRubberBand)
         return;
 
@@ -368,60 +350,10 @@
     if (isScrollSnapInProgress())
         return;
     
-    if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
-        auto timeDelta = currentTime - m_startTime;
-
-        if (m_startStretch.isZero()) {
-            m_startStretch = m_client.stretchAmount();
-            if (m_startStretch.isZero()) {
-                stopRubberbanding();
-                return;
-            }
-
-            m_origVelocity = m_momentumVelocity;
-
-            // Just like normal scrolling, prefer vertical rubberbanding
-            if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
-                m_origVelocity.setWidth(0);
-
-            // Don't rubber-band horizontally if it's not possible to scroll horizontally
-            if (!m_client.allowsHorizontalScrolling())
-                m_origVelocity.setWidth(0);
-
-            // Don't rubber-band vertically if it's not possible to scroll vertically
-            if (!m_client.allowsVerticalScrolling())
-                m_origVelocity.setHeight(0);
-
-            LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::updateRubberBandAnimatingState() - starting rubbberband with m_origVelocity" << m_origVelocity << " m_startStretch " << m_startStretch);
-        }
-
-        auto rubberBandDelta = FloatSize {
-            roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), timeDelta)),
-            roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), timeDelta))
-        };
-
-        if (fabs(rubberBandDelta.width()) >= 1 || fabs(rubberBandDelta.height()) >= 1) {
-            auto stretchDelta = rubberBandDelta - FloatSize(m_client.stretchAmount());
-
-            LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::updateRubberBandAnimatingState() - rubberBandDelta " << rubberBandDelta << " stretched " << m_client.stretchAmount() << " moving by " << stretchDelta);
-
-            m_client.immediateScrollBy(stretchDelta, ScrollClamping::Unclamped);
-
-            FloatSize newStretch = m_client.stretchAmount();
-
-            m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
-            m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
-        } else {
-            LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::updateRubberBandAnimatingState() - rubber band complete");
-            m_client.adjustScrollPositionToBoundsIfNecessary();
-            stopRubberbanding();
-        }
-    } else {
+    if (m_momentumScrollInProgress && !m_ignoreMomentumScrolls) {
         LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::updateRubberBandAnimatingState() - not animating, momentumScrollInProgress " << m_momentumScrollInProgress << " ignoreMomentumScrolls " << m_ignoreMomentumScrolls);
-        m_startTime = currentTime;
-        m_startStretch = { };
         if (!isRubberBandInProgressInternal())
-            stopRubberbandAnimation();
+            stopRubberBandAnimation();
     }
 
     updateRubberBandingState();
@@ -453,35 +385,45 @@
     return false;
 }
 
-void ScrollingEffectsController::stopRubberbanding()
+void ScrollingEffectsController::stopRubberBanding()
 {
-    stopRubberbandAnimation();
-    m_stretchScrollForce = { };
-    m_startTime = { };
-    m_startStretch = { };
-    m_origVelocity = { };
+    stopRubberBandAnimation();
     updateRubberBandingState();
 }
 
-void ScrollingEffectsController::startRubberbandAnimation()
+void ScrollingEffectsController::startRubberBandAnimation(const FloatPoint& targetOffset, const FloatSize& initialVelocity, const FloatSize& initialOverscroll)
 {
-    m_client.willStartRubberBandSnapAnimation();
+    if (m_currentAnimation)
+        m_currentAnimation->stop();
 
-    setIsAnimatingRubberBand(true);
+    m_currentAnimation = makeUnique<ScrollAnimationRubberBand>(*this);
+    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::startRubberBandAnimation() - starting rubbberband with targetOffset " << targetOffset << " initialVelocity " << initialVelocity << " initialOverscroll " << initialOverscroll);
+    downcast<ScrollAnimationRubberBand>(*m_currentAnimation).startRubberBandAnimation(targetOffset, initialVelocity, initialOverscroll);
+}
 
+void ScrollingEffectsController::stopRubberBandAnimation()
+{
+    if (m_isAnimatingRubberBand)
+        stopAnimatedScroll();
+
+    m_stretchScrollForce = { };
+}
+
+void ScrollingEffectsController::willStartRubberBandAnimation()
+{
+    m_isAnimatingRubberBand = true;
+    m_client.willStartRubberBandAnimation();
     m_client.deferWheelEventTestCompletionForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
 }
 
-void ScrollingEffectsController::stopRubberbandAnimation()
+void ScrollingEffectsController::didStopRubberBandAnimation()
 {
-    m_client.didStopRubberbandSnapAnimation();
-
-    setIsAnimatingRubberBand(false);
-
+    m_isAnimatingRubberBand = false;
+    m_client.didStopRubberBandAnimation();
     m_client.removeWheelEventTestCompletionDeferralForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
 }
 
-void ScrollingEffectsController::startRubberbandAnimationIfNecessary()
+void ScrollingEffectsController::startRubberBandAnimationIfNecessary()
 {
     auto timeDelta = WallTime::now() - m_lastMomentumScrollTimestamp;
     if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
@@ -490,11 +432,33 @@
     if (m_isAnimatingRubberBand)
         return;
 
-    m_startTime = MonotonicTime::now();
-    m_startStretch = { };
-    m_origVelocity = { };
+    auto extents = m_client.scrollExtents();
+    auto targetOffset = m_client.scrollOffset();
+    auto contrainedOffset = targetOffset.constrainedBetween(extents.minimumScrollOffset(), extents.maximumScrollOffset());
+    bool willOverscroll = targetOffset != contrainedOffset;
 
-    startRubberbandAnimation();
+    auto stretchAmount = m_client.stretchAmount();
+
+    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::startRubberBandAnimationIfNecessary() - rubberBandAnimationRunning " << m_isAnimatingRubberBand << " stretchAmount " << stretchAmount << " targetOffset " << targetOffset);
+
+    if (stretchAmount.isZero() && !willOverscroll)
+        return;
+
+    auto initialVelocity = m_momentumVelocity;
+
+    // Just like normal scrolling, prefer vertical rubberbanding
+    if (fabsf(initialVelocity.height()) >= fabsf(initialVelocity.width()))
+        initialVelocity.setWidth(0);
+
+    // Don't rubber-band horizontally if it's not possible to scroll horizontally
+    if (!m_client.allowsHorizontalScrolling())
+        initialVelocity.setWidth(0);
+
+    // Don't rubber-band vertically if it's not possible to scroll vertically
+    if (!m_client.allowsVerticalScrolling())
+        initialVelocity.setHeight(0);
+
+    startRubberBandAnimation(contrainedOffset, initialVelocity, stretchAmount);
 }
 
 bool ScrollingEffectsController::shouldRubberBandOnSide(BoxSide side) const
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to