Diff
Modified: trunk/Source/WebCore/ChangeLog (282696 => 282697)
--- trunk/Source/WebCore/ChangeLog 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/ChangeLog 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,3 +1,85 @@
+2021-09-17 Simon Fraser <[email protected]>
+
+ Make ScrollAnimation a little more generic
+ https://bugs.webkit.org/show_bug.cgi?id=230385
+
+ Reviewed by Tim Horton.
+
+ Prepare for new ScrollAnimation subclasses by making it a little more generic. Rather
+ than the function callbacks, use a virtual client class, implemented by ScrollAnimator
+ and ScrollingTreeScrollingNodeDelegateNicosia. Remove the generic 'scroll' methods
+ from the base class, since they only apply to ScrollAnimationSmooth (clients need
+ to keep derived class pointers, and most already do).
+
+ Remove ambiguity around the currentPosition by requiring it for every 'start' call.
+ Remove ambiguity around setCurrentPosition() by removing it. Clients just call stop().
+ Remove ambiguity around retargeting by making it explicit.
+
+ Do per-axis setup when starting animations, not when creating one, so the animation starts
+ out stateless.
+
+ * Sources.txt: Build platform/ScrollAnimationKinetic.cpp for macOS, mostly to catch
+ build errors (it's currently unused).
+ * WebCore.xcodeproj/project.pbxproj:
+ * page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp:
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::resetCurrentPosition):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::ensureScrollAnimationKinetic):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::ensureScrollAnimationSmooth):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::handleWheelEvent):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidUpdate):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidEnd):
+ (WebCore::ScrollingTreeScrollingNodeDelegateNicosia::scrollExtentsForAnimation):
+ * page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h:
+ * platform/ScrollAnimation.h:
+ (WebCore::ScrollAnimation::ScrollAnimation):
+ (WebCore::ScrollAnimation::updateScrollExtents):
+ (WebCore::ScrollAnimation::serviceAnimation):
+ (WebCore::ScrollAnimation::~ScrollAnimation): Deleted.
+ (WebCore::ScrollAnimation::scroll): Deleted.
+ (WebCore::ScrollAnimation::updateVisibleLengths): Deleted.
+ (WebCore::ScrollAnimation::setCurrentPosition): Deleted.
+ * platform/ScrollAnimationKinetic.cpp:
+ (WebCore::ScrollAnimationKinetic::ScrollAnimationKinetic):
+ (WebCore::ScrollAnimationKinetic::startAnimatedScrollWithInitialVelocity):
+ (WebCore::ScrollAnimationKinetic::animationTimerFired):
+ (WebCore::ScrollAnimationKinetic::start): Deleted.
+ * platform/ScrollAnimationKinetic.h:
+ * platform/ScrollAnimationSmooth.cpp:
+ (WebCore::ScrollAnimationSmooth::ScrollAnimationSmooth):
+ (WebCore::ScrollAnimationSmooth::startAnimatedScroll):
+ (WebCore::ScrollAnimationSmooth::startAnimatedScrollToDestination):
+ (WebCore::ScrollAnimationSmooth::stop):
+ (WebCore::ScrollAnimationSmooth::updateScrollExtents):
+ (WebCore::ScrollAnimationSmooth::initializeAxesData):
+ (WebCore::ScrollAnimationSmooth::animationTimerFired):
+ (WebCore::ScrollAnimationSmooth::PerAxisData::PerAxisData): Deleted.
+ (WebCore::ScrollAnimationSmooth::scroll): Deleted.
+ (WebCore::ScrollAnimationSmooth::updateVisibleLengths): Deleted.
+ (WebCore::ScrollAnimationSmooth::setCurrentPosition): Deleted.
+ * platform/ScrollAnimationSmooth.h: Rename some "time" variables to "duration" for clarity
+ * platform/ScrollAnimator.cpp:
+ (WebCore::ScrollAnimator::ScrollAnimator):
+ (WebCore::ScrollAnimator::scroll):
+ (WebCore::ScrollAnimator::scrollToPositionWithoutAnimation):
+ (WebCore::ScrollAnimator::scrollToPositionWithAnimation):
+ (WebCore::ScrollAnimator::retargetRunningAnimation):
+ (WebCore::ScrollAnimator::contentsResized const):
+ (WebCore::ScrollAnimator::willEndLiveResize):
+ (WebCore::ScrollAnimator::didAddVerticalScrollbar):
+ (WebCore::ScrollAnimator::didAddHorizontalScrollbar):
+ (WebCore::ScrollAnimator::scrollAnimationDidUpdate):
+ (WebCore::ScrollAnimator::scrollAnimationDidEnd):
+ (WebCore::ScrollAnimator::scrollExtentsForAnimation):
+ (): Deleted.
+ (WebCore::m_keyboardScrollingAnimator): Deleted.
+ * platform/ScrollAnimator.h:
+ * platform/generic/ScrollAnimatorGeneric.cpp:
+ (WebCore::ScrollAnimatorGeneric::ScrollAnimatorGeneric):
+ (WebCore::ScrollAnimatorGeneric::handleWheelEvent):
+ (WebCore::ScrollAnimatorGeneric::updatePosition):
+ (WebCore::ScrollAnimatorGeneric::scrollAnimationDidUpdate):
+ * platform/generic/ScrollAnimatorGeneric.h:
+
2021-09-17 Cameron McCormack <[email protected]>
Preserve color space when creating ImageBuffers for ImageBitmaps
Modified: trunk/Source/WebCore/Sources.txt (282696 => 282697)
--- trunk/Source/WebCore/Sources.txt 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/Sources.txt 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1811,6 +1811,7 @@
platform/RemoteCommandListener.cpp
platform/RuntimeApplicationChecks.cpp
platform/SSLKeyGenerator.cpp
+platform/ScrollAnimationKinetic.cpp
platform/ScrollAnimationSmooth.cpp
platform/ScrollAnimator.cpp
platform/ScrollingEffectsController.cpp
Modified: trunk/Source/WebCore/SourcesGTK.txt (282696 => 282697)
--- trunk/Source/WebCore/SourcesGTK.txt 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/SourcesGTK.txt 2021-09-17 21:43:47 UTC (rev 282697)
@@ -69,7 +69,6 @@
page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp
page/scrolling/nicosia/ScrollingTreeStickyNode.cpp
-platform/ScrollAnimationKinetic.cpp
platform/UserAgentQuirks.cpp
platform/adwaita/ScrollbarThemeAdwaita.cpp
Modified: trunk/Source/WebCore/SourcesWPE.txt (282696 => 282697)
--- trunk/Source/WebCore/SourcesWPE.txt 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/SourcesWPE.txt 2021-09-17 21:43:47 UTC (rev 282697)
@@ -58,7 +58,6 @@
page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp
page/scrolling/nicosia/ScrollingTreeStickyNode.cpp
-platform/ScrollAnimationKinetic.cpp
platform/UserAgentQuirks.cpp
platform/adwaita/ScrollbarThemeAdwaita.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282696 => 282697)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-09-17 21:43:47 UTC (rev 282697)
@@ -352,6 +352,7 @@
0F94F37E23661626003AA5C7 /* StyleRuleType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F94F37C23661131003AA5C7 /* StyleRuleType.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9DAA0F1FD1C66A0079C5B2 /* DOMGCOutputConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9DAA0E1FD1C6640079C5B2 /* DOMGCOutputConstraint.h */; };
0FA24D7A162DF91900A3F4C0 /* GraphicsLayerUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA24D78162DF91900A3F4C0 /* GraphicsLayerUpdater.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0FA61B0E26F43213001AADB6 /* ScrollAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA61B0C26F43212001AADB6 /* ScrollAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB6252F18DE1B1500A07C05 /* GeometryUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB6252D18DE1B1500A07C05 /* GeometryUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB8890F167D30160010CDA5 /* ScrollingStateStickyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB8890D167D30160010CDA5 /* ScrollingStateStickyNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FBB5FBE260991D20054572C /* DisplayRefreshMonitorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBB5FBD26095A9C0054572C /* DisplayRefreshMonitorFactory.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6324,6 +6325,7 @@
0FA0A0E523AEAA35000EEB94 /* dialog.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = dialog.css; sourceTree = "<group>"; };
0FA24D77162DF91900A3F4C0 /* GraphicsLayerUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsLayerUpdater.cpp; sourceTree = "<group>"; };
0FA24D78162DF91900A3F4C0 /* GraphicsLayerUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsLayerUpdater.h; sourceTree = "<group>"; };
+ 0FA61B0C26F43212001AADB6 /* ScrollAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollAnimation.h; sourceTree = "<group>"; };
0FB0689425243B90001E8E75 /* DisplayTextBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayTextBox.cpp; sourceTree = "<group>"; };
0FB0689625243B90001E8E75 /* DisplayTextBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayTextBox.h; sourceTree = "<group>"; };
0FB6252C18DE1B1500A07C05 /* GeometryUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeometryUtilities.cpp; sourceTree = "<group>"; };
@@ -28043,6 +28045,7 @@
411223B8260244FE00B0A0B6 /* ScriptExecutionContextIdentifier.h */,
BC8AE34C12EA096A00EB3AE6 /* ScrollableArea.cpp */,
BC8AE34D12EA096A00EB3AE6 /* ScrollableArea.h */,
+ 0FA61B0C26F43212001AADB6 /* ScrollAnimation.h */,
0FC692BC257C0F410098E3F9 /* ScrollAnimationKinetic.cpp */,
0FC692BA257C0F400098E3F9 /* ScrollAnimationKinetic.h */,
0FC692BD257C0F410098E3F9 /* ScrollAnimationSmooth.cpp */,
@@ -33132,7 +33135,6 @@
BC6932740D7E293900AE44D1 /* JSDOMWindowBase.h in Headers */,
652FBBBC0DE27CB60001D386 /* JSDOMWindowCustom.h in Headers */,
460CBF361D4BCD0E0092E88E /* JSDOMWindowProperties.h in Headers */,
- 410BCF5626F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.h in Headers */,
65E0E9441133C89F00B4CB10 /* JSDOMWrapper.h in Headers */,
7C45C9D31E3FCBD700AAB558 /* JSDOMWrapperCache.h in Headers */,
93A8061E1E03B585008A1F26 /* JSDoubleRange.h in Headers */,
@@ -34742,6 +34744,7 @@
07AB996B18DA3C010018771E /* RTCIceServer.h in Headers */,
313591081E7DDC7300F30630 /* RTCIceTransportPolicy.h in Headers */,
313591091E7DDC7300F30630 /* RTCIceTransportState.h in Headers */,
+ 410BCF5626F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.h in Headers */,
41C14BC626DE6DE800685BF5 /* RTCNetworkManager.h in Headers */,
073794FE19F5864E00E5A045 /* RTCNotifiersMock.h in Headers */,
073794DE19EE2C5200E5A045 /* RTCOfferAnswerOptions.h in Headers */,
@@ -34814,6 +34817,7 @@
1400D7A817136EA70077CE05 /* ScriptWrappableInlines.h in Headers */,
BC8AE34F12EA096A00EB3AE6 /* ScrollableArea.h in Headers */,
5D925B680F64D4DD00B847F0 /* ScrollAlignment.h in Headers */,
+ 0FA61B0E26F43213001AADB6 /* ScrollAnimation.h in Headers */,
CA3BF67E10D99BAE00E6CE53 /* ScrollAnimator.h in Headers */,
0F1774801378B772009DA76A /* ScrollAnimatorIOS.h in Headers */,
BCAE1FA712939DB7004CB026 /* ScrollAnimatorMac.h in Headers */,
Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp (282696 => 282697)
--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp 2021-09-17 21:43:47 UTC (rev 282697)
@@ -61,7 +61,7 @@
{
#if ENABLE(SMOOTH_SCROLLING)
if (m_smoothAnimation)
- m_smoothAnimation->setCurrentPosition(scrollingNode().currentScrollPosition());
+ m_smoothAnimation->stop();
#endif
}
@@ -69,7 +69,7 @@
{
#if ENABLE(SMOOTH_SCROLLING)
if (m_smoothAnimation)
- m_smoothAnimation->updateVisibleLengths();
+ m_smoothAnimation->updateScrollExtents();
#endif
}
@@ -79,18 +79,7 @@
if (m_kineticAnimation)
return;
- m_kineticAnimation = makeUnique<ScrollAnimationKinetic>(
- [this]() -> ScrollExtents {
- return { IntPoint(minimumScrollPosition()), IntPoint(maximumScrollPosition()), IntSize(scrollableAreaSize()) };
- },
- [this](FloatPoint&& position) {
-#if ENABLE(SMOOTH_SCROLLING)
- if (m_smoothAnimation)
- m_smoothAnimation->setCurrentPosition(position);
-#endif
- auto updateScope = createUpdateScope();
- scrollingNode().scrollTo(position);
- });
+ m_kineticAnimation = makeUnique<ScrollAnimationKinetic>(*this);
}
#endif
@@ -100,16 +89,7 @@
if (m_smoothAnimation)
return;
- m_smoothAnimation = makeUnique<ScrollAnimationSmooth>(
- [this]() -> ScrollExtents {
- return { IntPoint(minimumScrollPosition()), IntPoint(maximumScrollPosition()), IntSize(scrollableAreaSize()) };
- },
- currentScrollPosition(),
- [this](FloatPoint&& position) {
- auto updateScope = createUpdateScope();
- scrollingNode().scrollTo(position);
- },
- [] { });
+ m_smoothAnimation = makeUnique<ScrollAnimationSmooth>(*this);
}
#endif
@@ -125,12 +105,12 @@
m_kineticAnimation->appendToScrollHistory(wheelEvent);
m_kineticAnimation->stop();
if (wheelEvent.isEndOfNonMomentumScroll()) {
- m_kineticAnimation->start(currentScrollPosition(), m_kineticAnimation->computeVelocity(), canHaveHorizontalScrollbar, canHaveVerticalScrollbar);
+ m_kineticAnimation->startAnimatedScrollWithInitialVelocity(currentScrollPosition(), m_kineticAnimation->computeVelocity(), canHaveHorizontalScrollbar, canHaveVerticalScrollbar);
m_kineticAnimation->clearScrollHistory();
return WheelEventHandlingResult::handled();
}
if (wheelEvent.isTransitioningToMomentumScroll()) {
- m_kineticAnimation->start(currentScrollPosition(), wheelEvent.swipeVelocity(), canHaveHorizontalScrollbar, canHaveVerticalScrollbar);
+ m_kineticAnimation->startAnimatedScrollWithInitialVelocity(currentScrollPosition(), wheelEvent.swipeVelocity(), canHaveHorizontalScrollbar, canHaveVerticalScrollbar);
m_kineticAnimation->clearScrollHistory();
return WheelEventHandlingResult::handled();
}
@@ -182,8 +162,8 @@
#if ENABLE(SMOOTH_SCROLLING)
if (m_scrollAnimatorEnabled && !wheelEvent.hasPreciseScrollingDeltas()) {
ensureScrollAnimationSmooth();
- m_smoothAnimation->scroll(HorizontalScrollbar, ScrollByPixel, 1, deltaX);
- m_smoothAnimation->scroll(VerticalScrollbar, ScrollByPixel, 1, deltaY);
+ m_smoothAnimation->startAnimatedScroll(HorizontalScrollbar, ScrollByPixel, currentScrollPosition(), 1, deltaX);
+ m_smoothAnimation->startAnimatedScroll(VerticalScrollbar, ScrollByPixel, currentScrollPosition(), 1, deltaY);
return WheelEventHandlingResult::handled();
}
#endif
@@ -216,6 +196,31 @@
downcast<ScrollingTreeFrameScrollingNode>(scrollingNode()).frameScaleFactor() : 1.;
}
+void ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& position)
+{
+#if ENABLE(SMOOTH_SCROLLING)
+ if (&animation == m_kineticAnimation.get()) {
+ if (m_smoothAnimation)
+ m_smoothAnimation->stop();
+ }
+#endif
+ auto updateScope = createUpdateScope();
+ scrollingNode().scrollTo(position);
+}
+
+void ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidEnd(ScrollAnimation&)
+{
+}
+
+ScrollExtents ScrollingTreeScrollingNodeDelegateNicosia::scrollExtentsForAnimation(ScrollAnimation&)
+{
+ return {
+ IntPoint(minimumScrollPosition()),
+ IntPoint(maximumScrollPosition()),
+ IntSize(scrollableAreaSize())
+ };
+}
+
} // namespace WebCore
#endif // ENABLE(ASYNC_SCROLLING) && USE(NICOSIA)
Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h (282696 => 282697)
--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -31,6 +31,7 @@
#if ENABLE(ASYNC_SCROLLING) && USE(NICOSIA)
#include "NicosiaPlatformLayer.h"
+#include "ScrollAnimation.h"
#include "ScrollingStateOverflowScrollingNode.h"
#include "ThreadedScrollingTree.h"
@@ -44,7 +45,7 @@
namespace WebCore {
-class ScrollingTreeScrollingNodeDelegateNicosia : public ScrollingTreeScrollingNodeDelegate {
+class ScrollingTreeScrollingNodeDelegateNicosia : public ScrollingTreeScrollingNodeDelegate, public ScrollAnimationClient {
public:
explicit ScrollingTreeScrollingNodeDelegateNicosia(ScrollingTreeScrollingNode&, bool scrollAnimatorEnabled);
virtual ~ScrollingTreeScrollingNodeDelegateNicosia();
@@ -66,11 +67,16 @@
void ensureScrollAnimationSmooth();
#endif
+ // ScrollAnimationClient
+ void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& currentPosition) final;
+ void scrollAnimationDidEnd(ScrollAnimation&) final;
+ ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) final;
+
#if ENABLE(KINETIC_SCROLLING)
std::unique_ptr<ScrollAnimationKinetic> m_kineticAnimation;
#endif
#if ENABLE(SMOOTH_SCROLLING)
- std::unique_ptr<ScrollAnimation> m_smoothAnimation;
+ std::unique_ptr<ScrollAnimationSmooth> m_smoothAnimation;
#endif
};
Modified: trunk/Source/WebCore/platform/ScrollAnimation.h (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimation.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimation.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Igalia S.L.
+ * 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
@@ -23,16 +24,15 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScrollAnimation_h
-#define ScrollAnimation_h
+#pragma once
#include "ScrollTypes.h"
+#include <wtf/FastMalloc.h>
namespace WebCore {
class FloatPoint;
-class ScrollableArea;
-enum class ScrollClamping : bool;
+class ScrollAnimation;
struct ScrollExtents {
ScrollPosition minimumScrollPosition;
@@ -40,19 +40,33 @@
IntSize visibleSize;
};
+class ScrollAnimationClient {
+public:
+ virtual ~ScrollAnimationClient() = default;
+
+ virtual void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& currentPosition) = 0;
+ virtual void scrollAnimationDidEnd(ScrollAnimation&) = 0;
+ virtual ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) = 0;
+};
+
class ScrollAnimation {
WTF_MAKE_FAST_ALLOCATED;
public:
- virtual ~ScrollAnimation() { };
- virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float /* step */, float /* multiplier */) { return true; };
- virtual void scroll(const FloatPoint&) { };
+ ScrollAnimation(ScrollAnimationClient& client)
+ : m_client(client)
+ { }
+ virtual ~ScrollAnimation() = default;
+
+ virtual bool retargetActiveAnimation(const FloatPoint& newDestination) = 0;
virtual void stop() = 0;
- virtual void updateVisibleLengths() { };
- virtual void setCurrentPosition(const FloatPoint&) { };
+ virtual bool isActive() const = 0;
+ virtual void updateScrollExtents() { };
+
+ // FIXME: No-op. Need to use this instead of subclasses having timers.
virtual void serviceAnimation() { };
- virtual bool isActive() const = 0;
+
+protected:
+ ScrollAnimationClient& m_client;
};
} // namespace WebCore
-
-#endif // ScrollAnimation_h
Modified: trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Igalia S.L.
+ * 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
@@ -112,9 +113,8 @@
return m_velocity;
}
-ScrollAnimationKinetic::ScrollAnimationKinetic(ScrollExtentsCallback&& scrollExtentsFunction, NotifyPositionChangedCallback&& notifyPositionChangedFunction)
- : m_scrollExtentsFunction(WTFMove(scrollExtentsFunction))
- , m_notifyPositionChangedFunction(WTFMove(notifyPositionChangedFunction))
+ScrollAnimationKinetic::ScrollAnimationKinetic(ScrollAnimationClient& client)
+ : ScrollAnimation(client)
, m_animationTimer(RunLoop::current(), this, &ScrollAnimationKinetic::animationTimerFired)
{
#if USE(GLIB_EVENT_LOOP)
@@ -163,12 +163,13 @@
for (const auto& scrollEvent : m_scrollHistory)
accumDelta += FloatPoint(scrollEvent.deltaX(), scrollEvent.deltaY());
+ // FIXME: It's odd that computeVelocity() has the side effect of clearing history.
m_scrollHistory.clear();
return FloatPoint(accumDelta.x() * -1 / (last - first).value(), accumDelta.y() * -1 / (last - first).value());
}
-void ScrollAnimationKinetic::start(const FloatPoint& initialPosition, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll)
+bool ScrollAnimationKinetic::startAnimatedScrollWithInitialVelocity(const FloatPoint& initialPosition, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll)
{
stop();
@@ -176,11 +177,11 @@
m_position = initialPosition;
m_horizontalData = std::nullopt;
m_verticalData = std::nullopt;
- return;
+ return false;
}
auto delta = deltaToNextFrame();
- auto extents = m_scrollExtentsFunction();
+ auto extents = m_client.scrollExtentsForAnimation(*this);
auto accumulateVelocity = [&](double velocity, std::optional<PerAxisData> axisData) -> double {
if (axisData && axisData.value().animateScroll(delta)) {
@@ -214,8 +215,18 @@
m_position = initialPosition;
m_startTime = MonotonicTime::now() - tickTime / 2.;
animationTimerFired();
+ return true;
}
+bool ScrollAnimationKinetic::retargetActiveAnimation(const FloatPoint&)
+{
+ if (!isActive())
+ return false;
+
+ // FIXME: Implement retargeting.
+ return false;
+}
+
void ScrollAnimationKinetic::animationTimerFired()
{
auto delta = deltaToNextFrame();
@@ -233,7 +244,7 @@
double x = m_horizontalData ? m_horizontalData.value().position() : m_position.x();
double y = m_verticalData ? m_verticalData.value().position() : m_position.y();
m_position = FloatPoint(x, y);
- m_notifyPositionChangedFunction(FloatPoint(m_position));
+ m_client.scrollAnimationDidUpdate(*this, FloatPoint(m_position));
}
Seconds ScrollAnimationKinetic::deltaToNextFrame()
Modified: trunk/Source/WebCore/platform/ScrollAnimationKinetic.h (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimationKinetic.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimationKinetic.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Igalia S.L.
+ * 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
@@ -57,27 +58,24 @@
};
public:
- using ScrollExtentsCallback = WTF::Function<ScrollExtents(void)>;
- using NotifyPositionChangedCallback = WTF::Function<void(FloatPoint&&)>;
-
- ScrollAnimationKinetic(ScrollExtentsCallback&&, NotifyPositionChangedCallback&&);
+ ScrollAnimationKinetic(ScrollAnimationClient&);
virtual ~ScrollAnimationKinetic();
+ bool startAnimatedScrollWithInitialVelocity(const FloatPoint& initialPosition, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll);
+
+ bool retargetActiveAnimation(const FloatPoint& newDestination) final;
+ void stop() final;
+ bool isActive() const final;
+
void appendToScrollHistory(const PlatformWheelEvent&);
void clearScrollHistory();
+
FloatPoint computeVelocity();
- void start(const FloatPoint& initialPosition, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll);
- void stop() override;
- bool isActive() const override;
-
private:
void animationTimerFired();
Seconds deltaToNextFrame();
- ScrollExtentsCallback m_scrollExtentsFunction;
- NotifyPositionChangedCallback m_notifyPositionChangedFunction;
-
std::optional<PerAxisData> m_horizontalData;
std::optional<PerAxisData> m_verticalData;
Modified: trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2016 Igalia S.L.
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
* Copyright (c) 2011, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,29 +42,8 @@
static const Seconds minimumTimerInterval { 1_ms };
static const double smoothFactorForProgrammaticScroll = 1;
-ScrollAnimationSmooth::PerAxisData::PerAxisData(ScrollbarOrientation orientation, const FloatPoint& position, ScrollExtentsCallback& extentsCallback)
-{
- auto extents = extentsCallback();
- switch (orientation) {
- case HorizontalScrollbar:
- currentPosition = position.x();
- visibleLength = extents.visibleSize.width();
- break;
- case VerticalScrollbar:
- currentPosition = position.y();
- visibleLength = extents.visibleSize.height();
- break;
- }
-
- desiredPosition = currentPosition;
-}
-
-ScrollAnimationSmooth::ScrollAnimationSmooth(ScrollExtentsCallback&& scrollExtentsFunction, const FloatPoint& position, NotifyPositionChangedCallback&& notifyPositionChangedFunction, NotifyAnimationStoppedCallback&& notifyAnimationStoppedFunction)
- : m_scrollExtentsFunction(WTFMove(scrollExtentsFunction))
- , m_notifyPositionChangedFunction(WTFMove(notifyPositionChangedFunction))
- , m_notifyAnimationStoppedFunction(WTFMove(notifyAnimationStoppedFunction))
- , m_horizontalData(HorizontalScrollbar, position, m_scrollExtentsFunction)
- , m_verticalData(VerticalScrollbar, position, m_scrollExtentsFunction)
+ScrollAnimationSmooth::ScrollAnimationSmooth(ScrollAnimationClient& client)
+ : ScrollAnimation(client)
, m_animationTimer(RunLoop::current(), this, &ScrollAnimationSmooth::animationTimerFired)
{
#if USE(GLIB_EVENT_LOOP)
@@ -72,11 +51,15 @@
#endif
}
-bool ScrollAnimationSmooth::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
+ScrollAnimationSmooth::~ScrollAnimationSmooth() = default;
+
+bool ScrollAnimationSmooth::startAnimatedScroll(ScrollbarOrientation orientation, ScrollGranularity granularity, const FloatPoint& fromPosition, float step, float multiplier)
{
float minScrollPosition;
float maxScrollPosition;
- auto extents = m_scrollExtentsFunction();
+ auto extents = m_client.scrollExtentsForAnimation(*this);
+ initializeAxesData(extents, fromPosition);
+
if (orientation == HorizontalScrollbar) {
minScrollPosition = extents.minimumScrollPosition.x();
maxScrollPosition = extents.maximumScrollPosition.x();
@@ -93,41 +76,55 @@
return needToScroll;
}
-void ScrollAnimationSmooth::scroll(const FloatPoint& position)
+bool ScrollAnimationSmooth::startAnimatedScrollToDestination(const FloatPoint& fromPosition, const FloatPoint& destinationPosition)
{
- ScrollGranularity granularity = ScrollByPage;
- auto extents = m_scrollExtentsFunction();
- bool needToScroll = updatePerAxisData(m_horizontalData, granularity, position.x(), extents.minimumScrollPosition.x(), extents.maximumScrollPosition.x(), smoothFactorForProgrammaticScroll);
+ auto extents = m_client.scrollExtentsForAnimation(*this);
+ initializeAxesData(extents, fromPosition);
+
+ return startOrRetargetAnimation(extents, destinationPosition);
+}
+
+bool ScrollAnimationSmooth::retargetActiveAnimation(const FloatPoint& newDestination)
+{
+ if (!isActive())
+ return false;
+
+ auto extents = m_client.scrollExtentsForAnimation(*this);
+ return startOrRetargetAnimation(extents, newDestination);
+}
+
+bool ScrollAnimationSmooth::startOrRetargetAnimation(const ScrollExtents& extents, const FloatPoint& destinationPosition)
+{
+ auto granularity = ScrollByPage;
+ bool needToScroll = updatePerAxisData(m_horizontalData, granularity, destinationPosition.x(), extents.minimumScrollPosition.x(), extents.maximumScrollPosition.x(), smoothFactorForProgrammaticScroll);
needToScroll |=
- updatePerAxisData(m_verticalData, granularity, position.y(), extents.minimumScrollPosition.y(), extents.maximumScrollPosition.y(), smoothFactorForProgrammaticScroll);
+ updatePerAxisData(m_verticalData, granularity, destinationPosition.y(), extents.minimumScrollPosition.y(), extents.maximumScrollPosition.y(), smoothFactorForProgrammaticScroll);
if (needToScroll && !isActive()) {
- m_startTime = m_horizontalData.startTime;
+ m_startTime = m_verticalData.startTime;
animationTimerFired();
}
-};
+ return needToScroll;
+}
void ScrollAnimationSmooth::stop()
{
m_animationTimer.stop();
- m_notifyAnimationStoppedFunction();
+ m_client.scrollAnimationDidEnd(*this);
}
-void ScrollAnimationSmooth::updateVisibleLengths()
+void ScrollAnimationSmooth::updateScrollExtents()
{
- auto extents = m_scrollExtentsFunction();
+ auto extents = m_client.scrollExtentsForAnimation(*this);
m_horizontalData.visibleLength = extents.visibleSize.width();
m_verticalData.visibleLength = extents.visibleSize.height();
}
-void ScrollAnimationSmooth::setCurrentPosition(const FloatPoint& position)
+void ScrollAnimationSmooth::initializeAxesData(const ScrollExtents& extents, const FloatPoint& startPosition)
{
- stop();
- m_horizontalData = PerAxisData(position.x(), m_horizontalData.visibleLength);
- m_verticalData = PerAxisData(position.y(), m_verticalData.visibleLength);
+ m_horizontalData = PerAxisData(startPosition.x(), extents.visibleSize.width());
+ m_verticalData = PerAxisData(startPosition.y(), extents.visibleSize.height());
}
-ScrollAnimationSmooth::~ScrollAnimationSmooth() = default;
-
static inline double curveAt(ScrollAnimationSmooth::Curve curve, double t)
{
switch (curve) {
@@ -248,38 +245,38 @@
return endValue - startValue;
}
-static inline void getAnimationParametersForGranularity(ScrollGranularity granularity, Seconds& animationTime, Seconds& repeatMinimumSustainTime, Seconds& attackTime, Seconds& releaseTime, ScrollAnimationSmooth::Curve& coastTimeCurve, Seconds& maximumCoastTime)
+static inline void getAnimationParametersForGranularity(ScrollGranularity granularity, Seconds& animationDuration, Seconds& repeatMinimumSustainTime, Seconds& attackDuration, Seconds& releaseDuration, ScrollAnimationSmooth::Curve& coastTimeCurve, Seconds& maximumCoastTime)
{
switch (granularity) {
case ScrollByDocument:
- animationTime = tickTime * 10;
+ animationDuration = tickTime * 10;
repeatMinimumSustainTime = tickTime * 10;
- attackTime = tickTime * 10;
- releaseTime = tickTime * 10;
+ attackDuration = tickTime * 10;
+ releaseDuration = tickTime * 10;
coastTimeCurve = ScrollAnimationSmooth::Curve::Linear;
maximumCoastTime = 1_s;
break;
case ScrollByLine:
- animationTime = tickTime * 10;
+ animationDuration = tickTime * 10;
repeatMinimumSustainTime = tickTime * 7;
- attackTime = tickTime * 3;
- releaseTime = tickTime * 3;
+ attackDuration = tickTime * 3;
+ releaseDuration = tickTime * 3;
coastTimeCurve = ScrollAnimationSmooth::Curve::Linear;
maximumCoastTime = 1_s;
break;
case ScrollByPage:
- animationTime = tickTime * 15;
+ animationDuration = tickTime * 15;
repeatMinimumSustainTime = tickTime * 10;
- attackTime = tickTime * 5;
- releaseTime = tickTime * 5;
+ attackDuration = tickTime * 5;
+ releaseDuration = tickTime * 5;
coastTimeCurve = ScrollAnimationSmooth::Curve::Linear;
maximumCoastTime = 1_s;
break;
case ScrollByPixel:
- animationTime = tickTime * 11;
+ animationDuration = tickTime * 11;
repeatMinimumSustainTime = tickTime * 2;
- attackTime = tickTime * 3;
- releaseTime = tickTime * 3;
+ attackDuration = tickTime * 3;
+ releaseDuration = tickTime * 3;
coastTimeCurve = ScrollAnimationSmooth::Curve::Quadratic;
maximumCoastTime = 1250_ms;
break;
@@ -299,27 +296,27 @@
if (newPosition == data.desiredPosition)
return false;
- Seconds animationTime, repeatMinimumSustainTime, attackTime, releaseTime, maximumCoastTime;
+ Seconds animationDuration, repeatMinimumSustainTime, attackDuration, releaseDuration, maximumCoastTime;
Curve coastTimeCurve;
- getAnimationParametersForGranularity(granularity, animationTime, repeatMinimumSustainTime, attackTime, releaseTime, coastTimeCurve, maximumCoastTime);
+ getAnimationParametersForGranularity(granularity, animationDuration, repeatMinimumSustainTime, attackDuration, releaseDuration, coastTimeCurve, maximumCoastTime);
- animationTime *= smoothFactor;
+ animationDuration *= smoothFactor;
repeatMinimumSustainTime *= smoothFactor;
- attackTime *= smoothFactor;
- releaseTime *= smoothFactor;
+ attackDuration *= smoothFactor;
+ releaseDuration *= smoothFactor;
maximumCoastTime *= smoothFactor;
data.desiredPosition = newPosition;
if (!data.startTime)
- data.attackTime = attackTime;
- data.animationTime = animationTime;
- data.releaseTime = releaseTime;
+ data.attackDuration = attackDuration;
+ data.animationDuration = animationDuration;
+ data.releaseDuration = releaseDuration;
// Prioritize our way out of over constraint.
- if (data.attackTime + data.releaseTime > data.animationTime) {
- if (data.releaseTime > data.animationTime)
- data.releaseTime = data.animationTime;
- data.attackTime = data.animationTime - data.releaseTime;
+ if (data.attackDuration + data.releaseDuration > data.animationDuration) {
+ if (data.releaseDuration > data.animationDuration)
+ data.releaseDuration = data.animationDuration;
+ data.attackDuration = data.animationDuration - data.releaseDuration;
}
if (!data.startTime) {
@@ -333,15 +330,15 @@
double remainingDelta = data.desiredPosition - data.currentPosition;
double attackAreaLeft = 0;
Seconds deltaTime = data.lastAnimationTime - data.startTime;
- Seconds attackTimeLeft = std::max(0_s, data.attackTime - deltaTime);
- Seconds timeLeft = data.animationTime - deltaTime;
- Seconds minTimeLeft = data.releaseTime + std::min(repeatMinimumSustainTime, data.animationTime - data.releaseTime - attackTimeLeft);
+ Seconds attackTimeLeft = std::max(0_s, data.attackDuration - deltaTime);
+ Seconds timeLeft = data.animationDuration - deltaTime;
+ Seconds minTimeLeft = data.releaseDuration + std::min(repeatMinimumSustainTime, data.animationDuration - data.releaseDuration - attackTimeLeft);
if (timeLeft < minTimeLeft) {
- data.animationTime = deltaTime + minTimeLeft;
+ data.animationDuration = deltaTime + minTimeLeft;
timeLeft = minTimeLeft;
}
- if (maximumCoastTime > (repeatMinimumSustainTime + releaseTime)) {
+ if (maximumCoastTime > (repeatMinimumSustainTime + releaseDuration)) {
double targetMaxCoastVelocity = data.visibleLength * .25 * frameRate;
// This needs to be as minimal as possible while not being intrusive to page up/down.
double minCoastDelta = data.visibleLength;
@@ -354,23 +351,23 @@
Seconds coastMinTimeLeft = std::min(maximumCoastTime, minTimeLeft + (maximumCoastTime - minTimeLeft) * coastCurve(coastTimeCurve, coastFactor));
if (Seconds additionalTime = std::max(0_s, coastMinTimeLeft - minTimeLeft)) {
- Seconds additionalReleaseTime = std::min(additionalTime, additionalTime * (releaseTime / (releaseTime + repeatMinimumSustainTime)));
- data.releaseTime = releaseTime + additionalReleaseTime;
- data.animationTime = deltaTime + coastMinTimeLeft;
+ Seconds additionalReleaseTime = std::min(additionalTime, additionalTime * (releaseDuration / (releaseDuration + repeatMinimumSustainTime)));
+ data.releaseDuration = releaseDuration + additionalReleaseTime;
+ data.animationDuration = deltaTime + coastMinTimeLeft;
timeLeft = coastMinTimeLeft;
}
}
}
- Seconds releaseTimeLeft = std::min(timeLeft, data.releaseTime);
+ Seconds releaseTimeLeft = std::min(timeLeft, data.releaseDuration);
Seconds sustainTimeLeft = std::max(0_s, timeLeft - releaseTimeLeft - attackTimeLeft);
if (attackTimeLeft) {
- double attackSpot = deltaTime / data.attackTime;
- attackAreaLeft = attackArea(Curve::Cubic, attackSpot, 1) * data.attackTime.value();
+ double attackSpot = deltaTime / data.attackDuration;
+ attackAreaLeft = attackArea(Curve::Cubic, attackSpot, 1) * data.attackDuration.value();
}
- double releaseSpot = (data.releaseTime - releaseTimeLeft) / data.releaseTime;
- double releaseAreaLeft = releaseArea(Curve::Cubic, releaseSpot, 1) * data.releaseTime.value();
+ double releaseSpot = (data.releaseDuration - releaseTimeLeft) / data.releaseDuration;
+ double releaseAreaLeft = releaseArea(Curve::Cubic, releaseSpot, 1) * data.releaseDuration.value();
data.desiredVelocity = remainingDelta / (attackAreaLeft + sustainTimeLeft.value() + releaseAreaLeft);
data.releasePosition = data.desiredPosition - data.desiredVelocity * releaseAreaLeft;
@@ -377,7 +374,7 @@
if (attackAreaLeft)
data.attackPosition = data.startPosition + data.desiredVelocity * attackAreaLeft;
else
- data.attackPosition = data.releasePosition - (data.animationTime - data.releaseTime - data.attackTime).value() * data.desiredVelocity;
+ data.attackPosition = data.releasePosition - (data.animationDuration - data.releaseDuration - data.attackDuration).value() * data.desiredVelocity;
if (sustainTimeLeft) {
double roundOff = data.releasePosition - ((attackAreaLeft ? data.attackPosition : data.currentPosition) + data.desiredVelocity * sustainTimeLeft.value());
@@ -401,18 +398,18 @@
Seconds deltaTime = currentTime - data.startTime;
double newPosition = data.currentPosition;
- if (deltaTime > data.animationTime) {
+ if (deltaTime > data.animationDuration) {
data = "" data.visibleLength);
return false;
}
- if (deltaTime < data.attackTime)
- newPosition = attackCurve(Curve::Cubic, deltaTime.value(), data.attackTime.value(), data.startPosition, data.attackPosition);
- else if (deltaTime < (data.animationTime - data.releaseTime))
- newPosition = data.attackPosition + (deltaTime - data.attackTime).value() * data.desiredVelocity;
+ if (deltaTime < data.attackDuration)
+ newPosition = attackCurve(Curve::Cubic, deltaTime.value(), data.attackDuration.value(), data.startPosition, data.attackPosition);
+ else if (deltaTime < (data.animationDuration - data.releaseDuration))
+ newPosition = data.attackPosition + (deltaTime - data.attackDuration).value() * data.desiredVelocity;
else {
// release is based on targeting the exact final position.
- Seconds releaseDeltaT = deltaTime - (data.animationTime - data.releaseTime);
- newPosition = releaseCurve(Curve::Cubic, releaseDeltaT.value(), data.releaseTime.value(), data.releasePosition, data.desiredPosition);
+ Seconds releaseDeltaT = deltaTime - (data.animationDuration - data.releaseDuration);
+ newPosition = releaseCurve(Curve::Cubic, releaseDeltaT.value(), data.releaseDuration.value(), data.releasePosition, data.desiredPosition);
}
// Normalize velocity to a per second amount. Could be used to check for jank.
@@ -437,10 +434,10 @@
if (continueAnimation)
startNextTimer(std::max(minimumTimerInterval, deltaToNextFrame));
- else
- m_notifyAnimationStoppedFunction();
- m_notifyPositionChangedFunction(FloatPoint(m_horizontalData.currentPosition, m_verticalData.currentPosition));
+ m_client.scrollAnimationDidUpdate(*this, { m_horizontalData.currentPosition, m_verticalData.currentPosition });
+ if (!continueAnimation)
+ m_client.scrollAnimationDidEnd(*this);
}
void ScrollAnimationSmooth::startNextTimer(Seconds delay)
Modified: trunk/Source/WebCore/platform/ScrollAnimationSmooth.h (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimationSmooth.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimationSmooth.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 Igalia S.L.
+ * 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
@@ -32,16 +33,11 @@
namespace WebCore {
class FloatPoint;
-class ScrollableArea;
enum class ScrollClamping : bool;
class ScrollAnimationSmooth final: public ScrollAnimation {
public:
- using ScrollExtentsCallback = WTF::Function<ScrollExtents(void)>;
- using NotifyPositionChangedCallback = WTF::Function<void(FloatPoint&&)>;
- using NotifyAnimationStoppedCallback = WTF::Function<void(void)>;
-
- ScrollAnimationSmooth(ScrollExtentsCallback&&, const FloatPoint& position, NotifyPositionChangedCallback&&, NotifyAnimationStoppedCallback&&);
+ ScrollAnimationSmooth(ScrollAnimationClient&);
virtual ~ScrollAnimationSmooth();
enum class Curve {
@@ -52,19 +48,17 @@
Bounce
};
+ bool startAnimatedScroll(ScrollbarOrientation, ScrollGranularity, const FloatPoint& fromPosition, float step, float multiplier);
+ bool startAnimatedScrollToDestination(const FloatPoint& fromPosition, const FloatPoint& destinationPosition);
+
+ bool retargetActiveAnimation(const FloatPoint& newDestination) final;
+ void stop() final;
+ void updateScrollExtents() final;
+ bool isActive() const final;
+
private:
- bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
- void scroll(const FloatPoint&) override;
- void stop() override;
- void updateVisibleLengths() override;
- void setCurrentPosition(const FloatPoint&) override;
- bool isActive() const override;
-
struct PerAxisData {
- PerAxisData() = delete;
-
- PerAxisData(ScrollbarOrientation, const FloatPoint& position, ScrollExtentsCallback&);
-
+ PerAxisData() = default;
PerAxisData(float position, int length)
: currentPosition(position)
, desiredPosition(position)
@@ -82,35 +76,36 @@
MonotonicTime startTime;
double startVelocity { 0 };
- Seconds animationTime;
+ Seconds animationDuration;
MonotonicTime lastAnimationTime;
double attackPosition { 0 };
- Seconds attackTime;
+ Seconds attackDuration;
Curve attackCurve { Curve::Quadratic };
double releasePosition { 0 };
- Seconds releaseTime;
+ Seconds releaseDuration;
Curve releaseCurve { Curve::Quadratic };
int visibleLength { 0 };
};
+ bool startOrRetargetAnimation(const ScrollExtents&, const FloatPoint& destination);
+
bool updatePerAxisData(PerAxisData&, ScrollGranularity, float newPosition, float minScrollPosition, float maxScrollPosition, double smoothFactor = 1);
bool animateScroll(PerAxisData&, MonotonicTime currentTime);
+
+ void initializeAxesData(const ScrollExtents&, const FloatPoint& startPosition);
void requestAnimationTimerFired();
void startNextTimer(Seconds delay);
void animationTimerFired();
- ScrollExtentsCallback m_scrollExtentsFunction;
- NotifyPositionChangedCallback m_notifyPositionChangedFunction;
- NotifyAnimationStoppedCallback m_notifyAnimationStoppedFunction;
-
PerAxisData m_horizontalData;
PerAxisData m_verticalData;
MonotonicTime m_startTime;
+ // FIXME: Should not have timer here, and instead use serviceAnimation().
RunLoop::Timer<ScrollAnimationSmooth> m_animationTimer;
};
Modified: trunk/Source/WebCore/platform/ScrollAnimator.cpp (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimator.cpp 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimator.cpp 2021-09-17 21:43:47 UTC (rev 282697)
@@ -54,20 +54,7 @@
: m_scrollableArea(scrollableArea)
, m_scrollController(*this)
, m_scrollControllerAnimationTimer(*this, &ScrollAnimator::scrollControllerAnimationTimerFired)
- , m_scrollAnimation(makeUnique<ScrollAnimationSmooth>(
- [this]() -> ScrollExtents {
- return { m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition(), m_scrollableArea.visibleSize() };
- },
- m_currentPosition,
- [this](FloatPoint&& position) {
- FloatSize delta = position - m_currentPosition;
- m_currentPosition = WTFMove(position);
- notifyPositionChanged(delta);
- updateActiveScrollSnapIndexForOffset();
- },
- [this] {
- m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
- }))
+ , m_scrollAnimation(makeUnique<ScrollAnimationSmooth>(*this))
, m_keyboardScrollingAnimator(makeUnique<KeyboardScrollingAnimator>(*this, m_scrollController))
{
}
@@ -99,11 +86,8 @@
}
#if ENABLE(SMOOTH_SCROLLING) && !PLATFORM(IOS_FAMILY)
- if (m_scrollableArea.scrollAnimatorEnabled() && !behavior.contains(ScrollBehavior::NeverAnimate)) {
- if (!m_scrollAnimation->isActive())
- m_scrollAnimation->setCurrentPosition(m_currentPosition);
- return m_scrollAnimation->scroll(orientation, granularity, step, multiplier);
- }
+ if (m_scrollableArea.scrollAnimatorEnabled() && !behavior.contains(ScrollBehavior::NeverAnimate))
+ return m_scrollAnimation->startAnimatedScroll(orientation, granularity, m_currentPosition, step, multiplier);
#endif
return scrollToPositionWithoutAnimation(currentPosition() + delta);
@@ -124,7 +108,7 @@
if (adjustedPosition == currentPosition && adjustedPosition == scrollableArea().scrollPosition() && !scrollableArea().scrollOriginChanged())
return false;
- m_scrollAnimation->setCurrentPosition(adjustedPosition);
+ m_scrollAnimation->stop();
m_currentPosition = adjustedPosition;
notifyPositionChanged(adjustedPosition - currentPosition);
updateActiveScrollSnapIndexForOffset();
@@ -142,8 +126,7 @@
if (!positionChanged && !scrollableArea().scrollOriginChanged())
return false;
- m_scrollAnimation->setCurrentPosition(m_currentPosition);
- m_scrollAnimation->scroll(newPosition);
+ m_scrollAnimation->startAnimatedScrollToDestination(m_currentPosition, newPosition);
scrollableArea().setScrollBehaviorStatus(ScrollBehaviorStatus::InNonNativeAnimation);
return true;
}
@@ -152,7 +135,7 @@
{
ASSERT(scrollableArea().currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation);
ASSERT(m_scrollAnimation->isActive());
- m_scrollAnimation->scroll(newPosition);
+ m_scrollAnimation->retargetActiveAnimation(newPosition);
}
FloatPoint ScrollAnimator::offsetFromPosition(const FloatPoint& position)
@@ -375,22 +358,22 @@
void ScrollAnimator::contentsResized() const
{
- m_scrollAnimation->updateVisibleLengths();
+ m_scrollAnimation->updateScrollExtents();
}
void ScrollAnimator::willEndLiveResize()
{
- m_scrollAnimation->updateVisibleLengths();
+ m_scrollAnimation->updateScrollExtents();
}
void ScrollAnimator::didAddVerticalScrollbar(Scrollbar*)
{
- m_scrollAnimation->updateVisibleLengths();
+ m_scrollAnimation->updateScrollExtents();
}
void ScrollAnimator::didAddHorizontalScrollbar(Scrollbar*)
{
- m_scrollAnimation->updateVisibleLengths();
+ m_scrollAnimation->updateScrollExtents();
}
FloatPoint ScrollAnimator::adjustScrollOffsetForSnappingIfNeeded(const FloatPoint& offset, ScrollSnapPointSelectionMethod method)
@@ -422,5 +405,27 @@
return m_scrollController.adjustScrollDestination(axis, newOffset, velocityInScrollAxis, originalOffset);
}
+void ScrollAnimator::scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& position)
+{
+ FloatSize delta = position - m_currentPosition;
+ m_currentPosition = position;
+ notifyPositionChanged(delta);
+ updateActiveScrollSnapIndexForOffset();
+}
+void ScrollAnimator::scrollAnimationDidEnd(ScrollAnimation&)
+{
+ m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
+}
+
+ScrollExtents ScrollAnimator::scrollExtentsForAnimation(ScrollAnimation&)
+{
+ return {
+ m_scrollableArea.minimumScrollPosition(),
+ m_scrollableArea.maximumScrollPosition(),
+ m_scrollableArea.visibleSize()
+ };
+}
+
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimator.h (282696 => 282697)
--- trunk/Source/WebCore/platform/ScrollAnimator.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/ScrollAnimator.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -33,6 +33,7 @@
#include "FloatPoint.h"
#include "PlatformWheelEvent.h"
+#include "ScrollAnimation.h"
#include "ScrollingEffectsController.h"
#include "Timer.h"
#include "WheelEventTestMonitor.h"
@@ -44,7 +45,7 @@
class FloatPoint;
class KeyboardScrollingAnimator;
class PlatformTouchEvent;
-class ScrollAnimation;
+class ScrollAnimationSmooth;
class ScrollableArea;
class Scrollbar;
class WheelEventTestMonitor;
@@ -51,7 +52,7 @@
class ScrollingEffectsControllerTimer;
-class ScrollAnimator : private ScrollingEffectsControllerClient {
+class ScrollAnimator : private ScrollingEffectsControllerClient, public ScrollAnimationClient {
WTF_MAKE_FAST_ALLOCATED;
public:
static std::unique_ptr<ScrollAnimator> create(ScrollableArea&);
@@ -133,6 +134,11 @@
virtual String horizontalScrollbarStateForTesting() const { return emptyString(); }
virtual String verticalScrollbarStateForTesting() const { return emptyString(); }
+ // ScrollAnimationClient
+ void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& currentPosition) override;
+ void scrollAnimationDidEnd(ScrollAnimation&) override;
+ ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) override;
+
void setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&& testMonitor) { m_wheelEventTestMonitor = testMonitor; }
FloatPoint adjustScrollOffsetForSnappingIfNeeded(const FloatPoint& offset, ScrollSnapPointSelectionMethod);
@@ -179,7 +185,7 @@
Timer m_scrollControllerAnimationTimer;
FloatPoint m_currentPosition;
- std::unique_ptr<ScrollAnimation> m_scrollAnimation;
+ std::unique_ptr<ScrollAnimationSmooth> m_scrollAnimation;
std::unique_ptr<KeyboardScrollingAnimator> m_keyboardScrollingAnimator;
};
Modified: trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.cpp (282696 => 282697)
--- trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.cpp 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.cpp 2021-09-17 21:43:47 UTC (rev 282697)
@@ -48,16 +48,9 @@
ScrollAnimatorGeneric::ScrollAnimatorGeneric(ScrollableArea& scrollableArea)
: ScrollAnimator(scrollableArea)
+ , m_kineticAnimation(makeUnique<ScrollAnimationKinetic>(*this))
, m_overlayScrollbarAnimationTimer(*this, &ScrollAnimatorGeneric::overlayScrollbarAnimationTimerFired)
{
- m_kineticAnimation = makeUnique<ScrollAnimationKinetic>(
- [this]() -> ScrollExtents {
- return { m_scrollableArea.minimumScrollPosition(), m_scrollableArea.maximumScrollPosition(), m_scrollableArea.visibleSize() };
- },
- [this](FloatPoint&& position) {
- m_scrollAnimation->setCurrentPosition(position);
- updatePosition(WTFMove(position));
- });
}
ScrollAnimatorGeneric::~ScrollAnimatorGeneric() = default;
@@ -76,12 +69,12 @@
m_kineticAnimation->appendToScrollHistory(event);
if (event.isEndOfNonMomentumScroll()) {
- m_kineticAnimation->start(m_currentPosition, m_kineticAnimation->computeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
+ m_kineticAnimation->startAnimatedScrollWithInitialVelocity(m_currentPosition, m_kineticAnimation->computeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
return true;
}
if (event.isTransitioningToMomentumScroll()) {
m_kineticAnimation->clearScrollHistory();
- m_kineticAnimation->start(m_currentPosition, event.swipeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
+ m_kineticAnimation->startAnimatedScrollWithInitialVelocity(m_currentPosition, event.swipeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
return true;
}
#endif
@@ -89,10 +82,10 @@
return ScrollAnimator::handleWheelEvent(event);
}
-void ScrollAnimatorGeneric::updatePosition(FloatPoint&& position)
+void ScrollAnimatorGeneric::updatePosition(const FloatPoint& position)
{
FloatSize delta = position - m_currentPosition;
- m_currentPosition = WTFMove(position);
+ m_currentPosition = position;
notifyPositionChanged(delta);
updateActiveScrollSnapIndexForOffset();
}
@@ -288,5 +281,18 @@
}
}
+// FIXME: Can we just use the base class implementation?
+void ScrollAnimatorGeneric::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& position)
+{
+ if (&animation == m_kineticAnimation.get()) {
+ // FIXME: Clarify how animations interact. There should never be more than one active at a time.
+ m_scrollAnimation->stop();
+ updatePosition(position);
+ return;
+ }
+
+ ScrollAnimator::scrollAnimationDidUpdate(animation, position);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.h (282696 => 282697)
--- trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.h 2021-09-17 21:42:50 UTC (rev 282696)
+++ trunk/Source/WebCore/platform/generic/ScrollAnimatorGeneric.h 2021-09-17 21:43:47 UTC (rev 282697)
@@ -61,8 +61,11 @@
void notifyContentAreaScrolled(const FloatSize& delta) override;
void lockOverlayScrollbarStateToHidden(bool) override;
- void updatePosition(FloatPoint&&);
+ // ScrollAnimationClient
+ void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& currentPosition) override;
+ void updatePosition(const FloatPoint&);
+
void overlayScrollbarAnimationTimerFired();
void showOverlayScrollbars();
void hideOverlayScrollbars();