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