Diff
Modified: trunk/Source/WebCore/ChangeLog (283067 => 283068)
--- trunk/Source/WebCore/ChangeLog 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/ChangeLog 2021-09-24 23:49:29 UTC (rev 283068)
@@ -1,3 +1,79 @@
+2021-09-24 Simon Fraser <[email protected]>
+
+ Have ScrollingEffectsController drive all the ScrollAnimations
+ https://bugs.webkit.org/show_bug.cgi?id=230739
+
+ Reviewed by Tim Horton.
+
+ Instead of each ScrollAnimation subclass having its own timer code, have them all
+ implement serviceAnimations(), so that ScrollingEffectsController can then drive
+ them all via its existing animationCallback() code.
+
+ Give ScrollingTreeScrollingNodeDelegateNicosia a temporary timer to drive its animations,
+ but leave FIXME comments noting that these animations should move into ScrollingEffectsCoordinator.
+
+ Push a bit more common ScrollAnimation logic into the base class, and add a
+ 'willStart' client function which ScrollingEffectsController can use to
+ start callbacks if necessary.
+
+ ScrollAnimation lifetime is controlled by ScrollingEffectsController; an animation
+ will be deleted in the first animationCallback() where it is no longer active. This
+ avoids potential pitfalls where an animation might be deleted inside the scrollAnimationDidEnd()
+ callback.
+
+ * platform/PlatformWheelEvent.h:
+ (WebCore::PlatformWheelEvent::swipeVelocity const):
+ * platform/ScrollAnimation.h:
+ (WebCore::ScrollAnimationClient::scrollAnimationWillStart):
+ (WebCore::ScrollAnimation::stop):
+ (WebCore::ScrollAnimation::isActive const):
+ (WebCore::ScrollAnimation::currentOffset const):
+ (WebCore::ScrollAnimation::didStart):
+ (WebCore::ScrollAnimation::didEnd):
+ (WebCore::ScrollAnimation::timeSinceStart const):
+ (WebCore::ScrollAnimation::serviceAnimation): Deleted.
+ * platform/ScrollAnimationKinetic.cpp:
+ (WebCore::ScrollAnimationKinetic::PerAxisData::animateScroll):
+ (WebCore::ScrollAnimationKinetic::ScrollAnimationKinetic):
+ (WebCore::ScrollAnimationKinetic::computeVelocity):
+ (WebCore::ScrollAnimationKinetic::startAnimatedScrollWithInitialVelocity):
+ (WebCore::ScrollAnimationKinetic::serviceAnimation):
+ (WebCore::ScrollAnimationKinetic::stop): Deleted.
+ (WebCore::ScrollAnimationKinetic::isActive const): Deleted.
+ (WebCore::ScrollAnimationKinetic::animationTimerFired): Deleted.
+ (WebCore::ScrollAnimationKinetic::deltaToNextFrame): Deleted.
+ * platform/ScrollAnimationKinetic.h:
+ * platform/ScrollAnimationMomentum.cpp:
+ (WebCore::ScrollAnimationMomentum::startAnimatedScrollWithInitialVelocity):
+ (WebCore::ScrollAnimationMomentum::retargetActiveAnimation):
+ (WebCore::ScrollAnimationMomentum::stop):
+ (WebCore::ScrollAnimationMomentum::serviceAnimation):
+ (WebCore::ScrollAnimationMomentum::updateScrollExtents):
+ (WebCore::ScrollAnimationMomentum::isActive const): Deleted.
+ * platform/ScrollAnimationMomentum.h:
+ * platform/ScrollAnimationSmooth.cpp:
+ (WebCore::ScrollAnimationSmooth::ScrollAnimationSmooth):
+ (WebCore::ScrollAnimationSmooth::startOrRetargetAnimation):
+ (WebCore::ScrollAnimationSmooth::serviceAnimation):
+ (WebCore::ScrollAnimationSmooth::stop): Deleted.
+ (WebCore::ScrollAnimationSmooth::animationTimerFired): Deleted.
+ (WebCore::ScrollAnimationSmooth::startNextTimer): Deleted.
+ (WebCore::ScrollAnimationSmooth::isActive const): Deleted.
+ * platform/ScrollAnimationSmooth.h:
+ * platform/ScrollingEffectsController.cpp:
+ (WebCore::ScrollingEffectsController::animationCallback):
+ (WebCore::ScrollingEffectsController::startOrStopAnimationCallbacks):
+ (WebCore::ScrollingEffectsController::startAnimatedScrollToDestination):
+ (WebCore::ScrollingEffectsController::scrollAnimationWillStart):
+ (WebCore::ScrollingEffectsController::scrollAnimationDidEnd):
+ (WebCore::ScrollingEffectsController::updateScrollSnapAnimatingState): Deleted.
+ * platform/ScrollingEffectsController.h:
+ * platform/mac/ScrollingEffectsController.mm:
+ (WebCore::ScrollingEffectsController::processWheelEventForScrollSnap): If transitionToGlideAnimationState()
+ starts an animation we have to call startScrollSnapAnimation() (because the previous stop() will have
+ puts us in a "not animating scroll snap" state).
+ (WebCore::ScrollingEffectsController::updateScrollSnapAnimatingState): Deleted.
+
2021-09-24 Antoine Quint <[email protected]>
[Media Controls] Allow for a close button
Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp (283067 => 283068)
--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.cpp 2021-09-24 23:49:29 UTC (rev 283068)
@@ -32,6 +32,10 @@
#include "NicosiaPlatformLayer.h"
#include "ScrollingTreeFrameScrollingNode.h"
+#if USE(GLIB_EVENT_LOOP)
+#include <wtf/glib/RunLoopSourcePriority.h>
+#endif
+
namespace WebCore {
class ScrollAnimation;
class ScrollAnimationKinetic;
@@ -39,12 +43,18 @@
ScrollingTreeScrollingNodeDelegateNicosia::ScrollingTreeScrollingNodeDelegateNicosia(ScrollingTreeScrollingNode& scrollingNode, bool scrollAnimatorEnabled)
: ScrollingTreeScrollingNodeDelegate(scrollingNode)
, m_scrollAnimatorEnabled(scrollAnimatorEnabled)
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+ , m_animationTimer(RunLoop::current(), this, &ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired)
+#endif
{
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+#if USE(GLIB_EVENT_LOOP)
+ m_animationTimer.setPriority(WTF::RunLoopSourcePriority::DisplayRefreshMonitorTimer);
+#endif
+#endif
}
-ScrollingTreeScrollingNodeDelegateNicosia::~ScrollingTreeScrollingNodeDelegateNicosia()
-{
-}
+ScrollingTreeScrollingNodeDelegateNicosia::~ScrollingTreeScrollingNodeDelegateNicosia() = default;
std::unique_ptr<Nicosia::SceneIntegration::UpdateScope> ScrollingTreeScrollingNodeDelegateNicosia::createUpdateScope()
{
@@ -80,6 +90,7 @@
return;
m_kineticAnimation = makeUnique<ScrollAnimationKinetic>(*this);
+ startTimerIfNecessary();
}
#endif
@@ -90,6 +101,7 @@
return;
m_smoothAnimation = makeUnique<ScrollAnimationSmooth>(*this);
+ startTimerIfNecessary();
}
#endif
@@ -116,6 +128,7 @@
}
#endif
+ // FIXME: This needs to share code with ScrollAnimator::handleWheelEvent(), perhaps by moving code into ScrollingEffectsController::handleWheelEvent().
float deltaX = canHaveHorizontalScrollbar ? wheelEvent.deltaX() : 0;
float deltaY = canHaveVerticalScrollbar ? wheelEvent.deltaY() : 0;
if ((deltaX < 0 && currentScrollPosition().x() >= maximumScrollPosition().x())
@@ -187,6 +200,9 @@
if (m_smoothAnimation)
m_smoothAnimation->stop();
#endif
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+ m_animationTimer.stop();
+#endif
}
float ScrollingTreeScrollingNodeDelegateNicosia::pageScaleFactor()
@@ -197,7 +213,7 @@
downcast<ScrollingTreeFrameScrollingNode>(scrollingNode()).frameScaleFactor() : 1.;
}
-void ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& position)
+void ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidUpdate(ScrollAnimation& animation, const FloatPoint& offset)
{
#if ENABLE(SMOOTH_SCROLLING)
if (&animation == m_kineticAnimation.get()) {
@@ -206,7 +222,9 @@
}
#endif
auto updateScope = createUpdateScope();
- scrollingNode().scrollTo(position);
+
+ // FIXME: Need to convert an offset to a position.
+ scrollingNode().scrollTo(offset);
}
void ScrollingTreeScrollingNodeDelegateNicosia::scrollAnimationDidEnd(ScrollAnimation&)
@@ -221,6 +239,35 @@
};
}
+void ScrollingTreeScrollingNodeDelegateNicosia::startTimerIfNecessary()
+{
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+ if (m_animationTimer.isActive())
+ return;
+
+ static constexpr double frameRate = 60;
+ static constexpr Seconds tickTime = 1_s / frameRate;
+
+ m_animationTimer.startRepeating(tickTime);
+#endif
+}
+
+void ScrollingTreeScrollingNodeDelegateNicosia::animationTimerFired()
+{
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+ auto now = MonotonicTime::now();
+#endif
+
+#if ENABLE(KINETIC_SCROLLING)
+ if (m_kineticAnimation)
+ m_kineticAnimation->serviceAnimation(now);
+#endif
+#if ENABLE(SMOOTH_SCROLLING)
+ if (m_smoothAnimation)
+ m_smoothAnimation->serviceAnimation(now);
+#endif
+}
+
} // namespace WebCore
#endif // ENABLE(ASYNC_SCROLLING) && USE(NICOSIA)
Modified: trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h (283067 => 283068)
--- trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/page/scrolling/nicosia/ScrollingTreeScrollingNodeDelegateNicosia.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -43,8 +43,13 @@
#include "ScrollAnimationSmooth.h"
#endif
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+#include <wtf/RunLoop.h>
+#endif
+
namespace WebCore {
+// FIXME: This should not be a ScrollAnimationClient.
class ScrollingTreeScrollingNodeDelegateNicosia : public ScrollingTreeScrollingNodeDelegate, public ScrollAnimationClient {
public:
explicit ScrollingTreeScrollingNodeDelegateNicosia(ScrollingTreeScrollingNode&, bool scrollAnimatorEnabled);
@@ -67,11 +72,17 @@
void ensureScrollAnimationSmooth();
#endif
+ void animationTimerFired();
+ void startTimerIfNecessary();
+
// ScrollAnimationClient
void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& currentPosition) final;
void scrollAnimationDidEnd(ScrollAnimation&) final;
ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) final;
+ // FIXME: These animations should not live here. They need to be managed by ScrollingEffectsController,
+ // to be coordinated with other kinds of scroll animations, and be referenced by ScrollingEffectsController::m_currentAnimation.
+
#if ENABLE(KINETIC_SCROLLING)
std::unique_ptr<ScrollAnimationKinetic> m_kineticAnimation;
#endif
@@ -78,6 +89,11 @@
#if ENABLE(SMOOTH_SCROLLING)
std::unique_ptr<ScrollAnimationSmooth> m_smoothAnimation;
#endif
+
+#if ENABLE(KINETIC_SCROLLING) || ENABLE(SMOOTH_SCROLLING)
+ // FIXME: When the above two animations are removed, this timer can be removed.
+ RunLoop::Timer<ScrollingTreeScrollingNodeDelegateNicosia> m_animationTimer;
+#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/PlatformWheelEvent.h (283067 => 283068)
--- trunk/Source/WebCore/platform/PlatformWheelEvent.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/PlatformWheelEvent.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -173,7 +173,7 @@
bool isEndOfNonMomentumScroll() const;
bool isTransitioningToMomentumScroll() const;
- FloatPoint swipeVelocity() const;
+ FloatSize swipeVelocity() const;
#endif
#if PLATFORM(WIN)
@@ -262,10 +262,10 @@
return m_phase == PlatformWheelEventPhase::None && m_momentumPhase == PlatformWheelEventPhase::Began;
}
-inline FloatPoint PlatformWheelEvent::swipeVelocity() const
+inline FloatSize PlatformWheelEvent::swipeVelocity() const
{
// The swiping velocity is stored in the deltas of the event declaring it.
- return isTransitioningToMomentumScroll() ? FloatPoint(m_wheelTicksX, m_wheelTicksY) : FloatPoint();
+ return isTransitioningToMomentumScroll() ? FloatSize(m_wheelTicksX, m_wheelTicksY) : FloatSize();
}
#endif // ENABLE(KINETIC_SCROLLING)
Modified: trunk/Source/WebCore/platform/ScrollAnimation.h (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimation.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimation.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -26,6 +26,7 @@
#pragma once
+#include "FloatPoint.h"
#include "ScrollTypes.h"
#include <wtf/FastMalloc.h>
#include <wtf/MonotonicTime.h>
@@ -40,6 +41,7 @@
virtual ~ScrollAnimationClient() = default;
virtual void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& /* currentOffset */) { }
+ virtual void scrollAnimationWillStart(ScrollAnimation&) { }
virtual void scrollAnimationDidEnd(ScrollAnimation&) { }
virtual ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) = 0;
};
@@ -62,16 +64,43 @@
Type type() const { return m_animationType; }
virtual bool retargetActiveAnimation(const FloatPoint& newDestinationOffset) = 0;
- virtual void stop() = 0;
- virtual bool isActive() const = 0;
+ virtual void stop()
+ {
+ if (!m_isActive)
+ return;
+ didEnd();
+ }
+ virtual bool isActive() const { return m_isActive; }
virtual void updateScrollExtents() { };
- // Returns current offset.
- virtual FloatPoint serviceAnimation(MonotonicTime) { return { }; };
+ FloatPoint currentOffset() const { return m_currentOffset; }
+
+ virtual void serviceAnimation(MonotonicTime) = 0;
protected:
+ void didStart(MonotonicTime currentTime)
+ {
+ m_startTime = currentTime;
+ m_isActive = true;
+ m_client.scrollAnimationWillStart(*this);
+ }
+
+ void didEnd()
+ {
+ m_isActive = false;
+ m_client.scrollAnimationDidEnd(*this);
+ }
+
+ Seconds timeSinceStart(MonotonicTime currentTime) const
+ {
+ return currentTime - m_startTime;
+ }
+
ScrollAnimationClient& m_client;
const Type m_animationType;
+ bool m_isActive { false };
+ MonotonicTime m_startTime;
+ FloatPoint m_currentOffset;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationKinetic.cpp 2021-09-24 23:49:29 UTC (rev 283068)
@@ -29,10 +29,6 @@
#include "PlatformWheelEvent.h"
-#if USE(GLIB_EVENT_LOOP)
-#include <wtf/glib/RunLoopSourcePriority.h>
-#endif
-
/*
* PerAxisData is a port of GtkKineticScrolling as of GTK+ 3.20,
* mimicking its API and its behavior.
@@ -67,12 +63,9 @@
*/
static constexpr double decelFriction = 4;
-static constexpr double frameRate = 60;
static constexpr double velocityAccumulationFloor = 0.33;
static constexpr double velocityAccumulationCeil = 1.0;
static constexpr double velocityAccumulationMax = 6.0;
-static constexpr Seconds tickTime = 1_s / frameRate;
-static constexpr Seconds minimumTimerInterval { 1_ms };
static constexpr Seconds scrollCaptureThreshold { 150_ms };
namespace WebCore {
@@ -87,11 +80,11 @@
{
}
-bool ScrollAnimationKinetic::PerAxisData::animateScroll(Seconds timeDelta)
+bool ScrollAnimationKinetic::PerAxisData::animateScroll(Seconds elapsedTime)
{
auto lastOffset = m_offset;
auto lastTime = m_elapsedTime;
- m_elapsedTime += timeDelta;
+ m_elapsedTime = elapsedTime;
double exponentialPart = exp(-decelFriction * m_elapsedTime.value());
m_offset = m_coef1 + m_coef2 * exponentialPart;
@@ -105,7 +98,7 @@
m_offset = m_upper;
}
- if (fabs(m_velocity) < 1 || (lastTime && fabs(m_offset - lastOffset) < 1)) {
+ if (fabs(m_velocity) < 1 || (lastTime > 0_s && fabs(m_offset - lastOffset) < 1)) {
m_offset = round(m_offset);
m_velocity = 0;
}
@@ -115,25 +108,11 @@
ScrollAnimationKinetic::ScrollAnimationKinetic(ScrollAnimationClient& client)
: ScrollAnimation(Type::Kinetic, client)
- , m_animationTimer(RunLoop::current(), this, &ScrollAnimationKinetic::animationTimerFired)
{
-#if USE(GLIB_EVENT_LOOP)
- m_animationTimer.setPriority(WTF::RunLoopSourcePriority::DisplayRefreshMonitorTimer);
-#endif
}
ScrollAnimationKinetic::~ScrollAnimationKinetic() = default;
-void ScrollAnimationKinetic::stop()
-{
- m_animationTimer.stop();
-}
-
-bool ScrollAnimationKinetic::isActive() const
-{
- return m_animationTimer.isActive();
-}
-
void ScrollAnimationKinetic::appendToScrollHistory(const PlatformWheelEvent& event)
{
m_scrollHistory.removeAllMatching([&event] (PlatformWheelEvent& otherEvent) -> bool {
@@ -148,7 +127,7 @@
m_scrollHistory.clear();
}
-FloatPoint ScrollAnimationKinetic::computeVelocity()
+FloatSize ScrollAnimationKinetic::computeVelocity()
{
if (m_scrollHistory.isEmpty())
return { };
@@ -166,25 +145,24 @@
// 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());
+ return FloatSize(accumDelta.x() * -1 / (last - first).value(), accumDelta.y() * -1 / (last - first).value());
}
-bool ScrollAnimationKinetic::startAnimatedScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll)
+bool ScrollAnimationKinetic::startAnimatedScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatSize& velocity, bool mayHScroll, bool mayVScroll)
{
stop();
- if (!velocity.x() && !velocity.y()) {
- m_offset = initialOffset;
+ if (velocity.isZero()) {
m_horizontalData = std::nullopt;
m_verticalData = std::nullopt;
return false;
}
- auto delta = deltaToNextFrame();
+ auto elapsedTime = 0_s;
auto extents = m_client.scrollExtentsForAnimation(*this);
auto accumulateVelocity = [&](double velocity, std::optional<PerAxisData> axisData) -> double {
- if (axisData && axisData.value().animateScroll(delta)) {
+ if (axisData && axisData.value().animateScroll(elapsedTime)) {
double lastVelocity = axisData.value().velocity();
if ((std::signbit(lastVelocity) == std::signbit(velocity))
&& (std::abs(velocity) >= std::abs(lastVelocity * velocityAccumulationFloor))) {
@@ -201,7 +179,7 @@
if (mayHScroll) {
m_horizontalData = PerAxisData(extents.minimumScrollOffset().x(),
extents.maximumScrollOffset().x(),
- initialOffset.x(), accumulateVelocity(velocity.x(), m_horizontalData));
+ initialOffset.x(), accumulateVelocity(velocity.width(), m_horizontalData));
} else
m_horizontalData = std::nullopt;
@@ -208,13 +186,12 @@
if (mayVScroll) {
m_verticalData = PerAxisData(extents.minimumScrollOffset().y(),
extents.maximumScrollOffset().y(),
- initialOffset.y(), accumulateVelocity(velocity.y(), m_verticalData));
+ initialOffset.y(), accumulateVelocity(velocity.height(), m_verticalData));
} else
m_verticalData = std::nullopt;
- m_offset = initialOffset;
- m_startTime = MonotonicTime::now() - tickTime / 2.;
- animationTimerFired();
+ m_currentOffset = initialOffset;
+ didStart(MonotonicTime::now());
return true;
}
@@ -227,30 +204,23 @@
return false;
}
-void ScrollAnimationKinetic::animationTimerFired()
+void ScrollAnimationKinetic::serviceAnimation(MonotonicTime currentTime)
{
- auto delta = deltaToNextFrame();
+ auto elapsedTime = timeSinceStart(currentTime);
- if (m_horizontalData && !m_horizontalData.value().animateScroll(delta))
+ if (m_horizontalData && !m_horizontalData.value().animateScroll(elapsedTime))
m_horizontalData = std::nullopt;
- if (m_verticalData && !m_verticalData.value().animateScroll(delta))
+ if (m_verticalData && !m_verticalData.value().animateScroll(elapsedTime))
m_verticalData = std::nullopt;
- // If one of the axes didn't finish its animation we must continue it.
- if (m_horizontalData || m_verticalData)
- m_animationTimer.startOneShot(std::max(minimumTimerInterval, delta));
+ double x = m_horizontalData ? m_horizontalData.value().offset() : m_currentOffset.x();
+ double y = m_verticalData ? m_verticalData.value().offset() : m_currentOffset.y();
+ m_currentOffset = FloatPoint(x, y);
+ m_client.scrollAnimationDidUpdate(*this, m_currentOffset);
- double x = m_horizontalData ? m_horizontalData.value().offset() : m_offset.x();
- double y = m_verticalData ? m_verticalData.value().offset() : m_offset.y();
- m_offset = FloatPoint(x, y);
- m_client.scrollAnimationDidUpdate(*this, m_offset);
+ if (!m_horizontalData && !m_verticalData)
+ didEnd();
}
-Seconds ScrollAnimationKinetic::deltaToNextFrame()
-{
- MonotonicTime currentTime = MonotonicTime::now();
- return 1_s * ceil((currentTime - m_startTime).value() * frameRate) / frameRate - (currentTime - m_startTime);
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimationKinetic.h (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationKinetic.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationKinetic.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -28,7 +28,6 @@
#include "FloatPoint.h"
#include "ScrollAnimation.h"
-#include <wtf/RunLoop.h>
namespace WebCore {
@@ -61,28 +60,21 @@
ScrollAnimationKinetic(ScrollAnimationClient&);
virtual ~ScrollAnimationKinetic();
- // FIXME: Velocity should be a FloatSize.
- bool startAnimatedScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatPoint& velocity, bool mayHScroll, bool mayVScroll);
-
+ bool startAnimatedScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatSize& velocity, bool mayHScroll, bool mayVScroll);
bool retargetActiveAnimation(const FloatPoint& newOffset) final;
- void stop() final;
- bool isActive() const final;
+ // FIXME: only public for ScrollingTreeScrollingNodeDelegateNicosia.
+ void serviceAnimation(MonotonicTime) final;
+
void appendToScrollHistory(const PlatformWheelEvent&);
void clearScrollHistory();
- FloatPoint computeVelocity();
+ FloatSize computeVelocity();
private:
- void animationTimerFired();
- Seconds deltaToNextFrame();
-
std::optional<PerAxisData> m_horizontalData;
std::optional<PerAxisData> m_verticalData;
- MonotonicTime m_startTime;
- RunLoop::Timer<ScrollAnimationKinetic> m_animationTimer;
- FloatPoint m_offset;
Vector<PlatformWheelEvent> m_scrollHistory;
};
Modified: trunk/Source/WebCore/platform/ScrollAnimationMomentum.cpp (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationMomentum.cpp 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationMomentum.cpp 2021-09-24 23:49:29 UTC (rev 283068)
@@ -27,7 +27,6 @@
#include "Logging.h"
#include "ScrollingMomentumCalculator.h"
-#include <wtf/text/TextStream.h>
namespace WebCore {
@@ -52,23 +51,25 @@
if (predictedScrollOffset == initialOffset) {
m_momentumCalculator = nullptr;
- m_animationComplete = true;
return false;
}
- m_startTime = MonotonicTime::now();
- m_animationComplete = false;
+ didStart(MonotonicTime::now());
return true;
}
bool ScrollAnimationMomentum::retargetActiveAnimation(const FloatPoint& newDestination)
{
- if (m_momentumCalculator) {
+ if (m_momentumCalculator && isActive()) {
m_momentumCalculator->setRetargetedScrollOffset(newDestination);
auto newDuration = m_momentumCalculator->animationDuration();
- m_animationComplete = newDuration > 0_s;
- return !m_animationComplete;
+ bool animationComplete = newDuration > 0_s;
+ if (animationComplete)
+ didEnd();
+
+ return !animationComplete;
}
+
return false;
}
@@ -75,32 +76,24 @@
void ScrollAnimationMomentum::stop()
{
m_momentumCalculator = nullptr;
- m_animationComplete = true;
- m_client.scrollAnimationDidEnd(*this);
+ ScrollAnimation::stop();
}
-bool ScrollAnimationMomentum::isActive() const
+void ScrollAnimationMomentum::serviceAnimation(MonotonicTime currentTime)
{
- return !m_animationComplete;
-}
-
-FloatPoint ScrollAnimationMomentum::serviceAnimation(MonotonicTime currentTime)
-{
if (!m_momentumCalculator) {
ASSERT_NOT_REACHED();
- return { };
+ return;
}
- auto elapsedTime = currentTime - m_startTime;
- m_animationComplete = elapsedTime >= m_momentumCalculator->animationDuration();
+ auto elapsedTime = timeSinceStart(currentTime);
+ bool animationComplete = elapsedTime >= m_momentumCalculator->animationDuration();
auto newOffset = m_momentumCalculator->scrollOffsetAfterElapsedTime(elapsedTime);
m_client.scrollAnimationDidUpdate(*this, newOffset);
- if (m_animationComplete)
- m_client.scrollAnimationDidEnd(*this);
-
- return newOffset;
+ if (animationComplete)
+ didEnd();
}
void ScrollAnimationMomentum::updateScrollExtents()
@@ -108,11 +101,8 @@
auto extents = m_client.scrollExtentsForAnimation(*this);
auto predictedScrollOffset = m_momentumCalculator->predictedDestinationOffset();
auto constrainedOffset = predictedScrollOffset.constrainedBetween(extents.minimumScrollOffset(), extents.maximumScrollOffset());
- if (constrainedOffset != predictedScrollOffset) {
+ if (constrainedOffset != predictedScrollOffset)
retargetActiveAnimation(constrainedOffset);
- if (m_animationComplete)
- m_client.scrollAnimationDidEnd(*this);
- }
}
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimationMomentum.h (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationMomentum.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationMomentum.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -36,18 +36,13 @@
virtual ~ScrollAnimationMomentum();
bool startAnimatedScrollWithInitialVelocity(const FloatPoint& initialOffset, const FloatSize& initialVelocity, const FloatSize& initialDelta, const WTF::Function<FloatPoint(const FloatPoint&)>& destinationModifier);
-
bool retargetActiveAnimation(const FloatPoint& newDestination) final;
void stop() final;
- bool isActive() const final;
- FloatPoint serviceAnimation(MonotonicTime) final;
+ void serviceAnimation(MonotonicTime) final;
void updateScrollExtents() final;
private:
std::unique_ptr<ScrollingMomentumCalculator> m_momentumCalculator;
-
- MonotonicTime m_startTime;
- bool m_animationComplete { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationSmooth.cpp 2021-09-24 23:49:29 UTC (rev 283068)
@@ -33,25 +33,15 @@
#include "ScrollableArea.h"
#include "TimingFunction.h"
-#if USE(GLIB_EVENT_LOOP)
-#include <wtf/glib/RunLoopSourcePriority.h>
-#endif
-
namespace WebCore {
-static const double frameRate = 60;
static const float animationSpeed { 1000.0f };
-static constexpr Seconds minimumTimerInterval { 1_ms };
static const Seconds maxAnimationDuration { 200_ms };
ScrollAnimationSmooth::ScrollAnimationSmooth(ScrollAnimationClient& client)
: ScrollAnimation(Type::Smooth, client)
- , m_animationTimer(RunLoop::current(), this, &ScrollAnimationSmooth::animationTimerFired)
, m_easeInOutTimingFunction(CubicBezierTimingFunction::create(CubicBezierTimingFunction::TimingFunctionPreset::EaseInOut))
{
-#if USE(GLIB_EVENT_LOOP)
- m_animationTimer.setPriority(WTF::RunLoopSourcePriority::DisplayRefreshMonitorTimer);
-#endif
}
ScrollAnimationSmooth::~ScrollAnimationSmooth() = default;
@@ -79,19 +69,12 @@
m_destinationOffset = destinationOffset.constrainedBetween(extents.minimumScrollOffset(), extents.maximumScrollOffset());
bool needToScroll = m_startOffset != m_destinationOffset;
- if (needToScroll && !isActive()) {
- m_startTime = MonotonicTime::now();
- animationTimerFired();
- }
+ if (needToScroll && !isActive())
+ didStart(MonotonicTime::now());
+
return needToScroll;
}
-void ScrollAnimationSmooth::stop()
-{
- m_animationTimer.stop();
- m_client.scrollAnimationDidEnd(*this);
-}
-
void ScrollAnimationSmooth::updateScrollExtents()
{
auto extents = m_client.scrollExtentsForAnimation(*this);
@@ -110,6 +93,14 @@
return a + progress * (b - a);
}
+void ScrollAnimationSmooth::serviceAnimation(MonotonicTime currentTime)
+{
+ bool animationActive = animateScroll(currentTime);
+ m_client.scrollAnimationDidUpdate(*this, m_currentOffset);
+ if (!animationActive)
+ didEnd();
+}
+
bool ScrollAnimationSmooth::animateScroll(MonotonicTime currentTime)
{
MonotonicTime endTime = m_startTime + m_duration;
@@ -126,29 +117,4 @@
return currentTime < endTime;
}
-void ScrollAnimationSmooth::animationTimerFired()
-{
- MonotonicTime currentTime = MonotonicTime::now();
- Seconds deltaToNextFrame = 1_s * ceil((currentTime - m_startTime).value() * frameRate) / frameRate - (currentTime - m_startTime);
- currentTime += deltaToNextFrame;
-
- bool continueAnimation = animateScroll(currentTime);
- if (continueAnimation)
- startNextTimer(std::max(minimumTimerInterval, deltaToNextFrame));
-
- m_client.scrollAnimationDidUpdate(*this, m_currentOffset);
- if (!continueAnimation)
- m_client.scrollAnimationDidEnd(*this);
-}
-
-void ScrollAnimationSmooth::startNextTimer(Seconds delay)
-{
- m_animationTimer.startOneShot(delay);
-}
-
-bool ScrollAnimationSmooth::isActive() const
-{
- return m_animationTimer.isActive();
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollAnimationSmooth.h (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollAnimationSmooth.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollAnimationSmooth.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -28,8 +28,6 @@
#include "ScrollAnimation.h"
-#include <wtf/RunLoop.h>
-
namespace WebCore {
class FloatPoint;
@@ -41,33 +39,25 @@
virtual ~ScrollAnimationSmooth();
bool startAnimatedScrollToDestination(const FloatPoint& fromOffset, const FloatPoint& destinationOffset);
+ bool retargetActiveAnimation(const FloatPoint& newOffset) final;
- bool retargetActiveAnimation(const FloatPoint& newOffset) final;
- void stop() final;
+ // FIXME: only public for ScrollingTreeScrollingNodeDelegateNicosia.
void updateScrollExtents() final;
- bool isActive() const final;
+ void serviceAnimation(MonotonicTime) final;
+private:
-private:
bool startOrRetargetAnimation(const ScrollExtents&, const FloatPoint& destinationOffset);
-
- void requestAnimationTimerFired();
- void startNextTimer(Seconds delay);
- void animationTimerFired();
Seconds durationFromDistance(const FloatSize&) const;
bool animateScroll(MonotonicTime);
- MonotonicTime m_startTime;
Seconds m_duration;
FloatPoint m_startOffset;
FloatPoint m_destinationOffset;
- FloatPoint m_currentOffset;
-
- // FIXME: Should not have timer here, and instead use serviceAnimation().
- RunLoop::Timer<ScrollAnimationSmooth> m_animationTimer;
+
RefPtr<TimingFunction> m_easeInOutTimingFunction;
};
Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.cpp (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollingEffectsController.cpp 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.cpp 2021-09-24 23:49:29 UTC (rev 283068)
@@ -48,14 +48,23 @@
{
LOG_WITH_STREAM(Scrolling, stream << "ScrollingEffectsController " << this << " animationCallback: isAnimatingRubberBand " << m_isAnimatingRubberBand << " isAnimatingScrollSnap " << m_isAnimatingScrollSnap << "isAnimatingKeyboardScrolling" << m_isAnimatingKeyboardScrolling);
- updateScrollSnapAnimatingState(currentTime);
+ if (m_currentAnimation) {
+ if (m_currentAnimation->isActive())
+ m_currentAnimation->serviceAnimation(currentTime);
+
+ if (m_currentAnimation && !m_currentAnimation->isActive())
+ m_currentAnimation = nullptr;
+ }
+
updateRubberBandAnimatingState(currentTime);
updateKeyboardScrollingAnimatingState(currentTime);
+
+ startOrStopAnimationCallbacks();
}
void ScrollingEffectsController::startOrStopAnimationCallbacks()
{
- bool needsCallbacks = m_isAnimatingRubberBand || m_isAnimatingScrollSnap || m_isAnimatingKeyboardScrolling;
+ bool needsCallbacks = m_isAnimatingRubberBand || m_isAnimatingKeyboardScrolling || m_currentAnimation;
if (needsCallbacks == m_isRunningAnimatingCallback)
return;
@@ -84,6 +93,8 @@
if (m_currentAnimation)
m_currentAnimation->stop();
+ // We always create and attempt to start the animation. If it turns out to not need animating, then the animation
+ // remains inactive, and we'll remove it on the next animationCallback().
m_currentAnimation = makeUnique<ScrollAnimationSmooth>(*this);
return downcast<ScrollAnimationSmooth>(*m_currentAnimation).startAnimatedScrollToDestination(startOffset, destinationOffset);
}
@@ -254,6 +265,35 @@
m_activeScrollSnapIndexDidChange = true;
}
+void ScrollingEffectsController::startScrollSnapAnimation()
+{
+ if (m_isAnimatingScrollSnap)
+ return;
+
+ LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " startScrollSnapAnimation (main thread " << isMainThread() << ")");
+
+#if PLATFORM(MAC)
+ startDeferringWheelEventTestCompletionDueToScrollSnapping();
+#endif
+ m_client.willStartScrollSnapAnimation();
+ setIsAnimatingScrollSnap(true);
+}
+
+void ScrollingEffectsController::stopScrollSnapAnimation()
+{
+ if (!m_isAnimatingScrollSnap)
+ return;
+
+ LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " stopScrollSnapAnimation (main thread " << isMainThread() << ")");
+
+#if PLATFORM(MAC)
+ stopDeferringWheelEventTestCompletionDueToScrollSnapping();
+#endif
+ m_client.didStopScrollSnapAnimation();
+
+ setIsAnimatingScrollSnap(false);
+}
+
void ScrollingEffectsController::updateKeyboardScrollingAnimatingState(MonotonicTime currentTime)
{
if (!m_isAnimatingKeyboardScrolling)
@@ -274,9 +314,20 @@
scrollToOffsetForAnimation(currentOffset);
}
+void ScrollingEffectsController::scrollAnimationWillStart(ScrollAnimation&)
+{
+ startOrStopAnimationCallbacks();
+}
+
void ScrollingEffectsController::scrollAnimationDidEnd(ScrollAnimation&)
{
+ if (usesScrollSnap() && m_isAnimatingScrollSnap) {
+ m_scrollSnapState->transitionToDestinationReachedState();
+ stopScrollSnapAnimation();
+ }
+
m_client.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
+ startOrStopAnimationCallbacks();
}
ScrollExtents ScrollingEffectsController::scrollExtentsForAnimation(ScrollAnimation&)
@@ -299,14 +350,8 @@
{
}
-void ScrollingEffectsController::updateScrollSnapAnimatingState(MonotonicTime)
-{
-
-}
-
void ScrollingEffectsController::updateRubberBandAnimatingState(MonotonicTime)
{
-
}
#endif // PLATFORM(MAC)
Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.h (283067 => 283068)
--- trunk/Source/WebCore/platform/ScrollingEffectsController.h 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.h 2021-09-24 23:49:29 UTC (rev 283068)
@@ -183,7 +183,6 @@
#endif
private:
- void updateScrollSnapAnimatingState(MonotonicTime);
void updateRubberBandAnimatingState(MonotonicTime);
void updateKeyboardScrollingAnimatingState(MonotonicTime);
@@ -191,10 +190,10 @@
void setIsAnimatingScrollSnap(bool);
void setIsAnimatingKeyboardScrolling(bool);
-#if PLATFORM(MAC)
void startScrollSnapAnimation();
void stopScrollSnapAnimation();
+#if PLATFORM(MAC)
bool shouldOverrideMomentumScrolling() const;
void statelessSnapTransitionTimerFired();
void scheduleStatelessScrollSnap();
@@ -217,6 +216,7 @@
// ScrollAnimationClient
void scrollAnimationDidUpdate(ScrollAnimation&, const FloatPoint& /* currentOffset */) final;
+ void scrollAnimationWillStart(ScrollAnimation&) final;
void scrollAnimationDidEnd(ScrollAnimation&) final;
ScrollExtents scrollExtentsForAnimation(ScrollAnimation&) final;
Modified: trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm (283067 => 283068)
--- trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm 2021-09-24 23:17:00 UTC (rev 283067)
+++ trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm 2021-09-24 23:49:29 UTC (rev 283068)
@@ -690,8 +690,10 @@
startScrollSnapAnimation();
break;
case WheelEventStatus::MomentumScrollBegin:
- if (m_scrollSnapState->transitionToGlideAnimationState(m_client.scrollExtents(), m_client.pageScaleFactor(), m_client.scrollOffset(), m_dragEndedScrollingVelocity, FloatSize(-wheelEvent.deltaX(), -wheelEvent.deltaY())))
+ if (m_scrollSnapState->transitionToGlideAnimationState(m_client.scrollExtents(), m_client.pageScaleFactor(), m_client.scrollOffset(), m_dragEndedScrollingVelocity, FloatSize(-wheelEvent.deltaX(), -wheelEvent.deltaY()))) {
+ startScrollSnapAnimation();
isMomentumScrolling = true;
+ }
m_dragEndedScrollingVelocity = { };
break;
case WheelEventStatus::MomentumScrolling:
@@ -720,62 +722,6 @@
updateRubberBandingState();
}
-void ScrollingEffectsController::startScrollSnapAnimation()
-{
- if (m_isAnimatingScrollSnap)
- return;
-
- LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " startScrollSnapAnimation (main thread " << isMainThread() << ")");
-
- startDeferringWheelEventTestCompletionDueToScrollSnapping();
- m_client.willStartScrollSnapAnimation();
- setIsAnimatingScrollSnap(true);
-}
-
-void ScrollingEffectsController::stopScrollSnapAnimation()
-{
- if (!m_isAnimatingScrollSnap)
- return;
-
- LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " stopScrollSnapAnimation (main thread " << isMainThread() << ")");
-
- stopDeferringWheelEventTestCompletionDueToScrollSnapping();
- m_client.didStopScrollSnapAnimation();
-
- setIsAnimatingScrollSnap(false);
-}
-
-void ScrollingEffectsController::updateScrollSnapAnimatingState(MonotonicTime currentTime)
-{
- if (!m_isAnimatingScrollSnap)
- return;
-
- if (!usesScrollSnap()) {
- ASSERT_NOT_REACHED();
- return;
- }
-
- if (!is<ScrollAnimationMomentum>(m_currentAnimation.get())) {
- m_scrollSnapState->transitionToDestinationReachedState();
- stopScrollSnapAnimation();
- return;
- }
-
- auto& momentumScrollAnimation = downcast<ScrollAnimationMomentum>(*m_currentAnimation);
-
- auto animationOffset = momentumScrollAnimation.serviceAnimation(currentTime);
- bool isAnimationComplete = !momentumScrollAnimation.isActive();
-
- LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " updateScrollSnapAnimatingState - isAnimationComplete " << isAnimationComplete << " animationOffset " << animationOffset << " (main thread " << isMainThread() << ")");
-
- scrollToOffsetForAnimation(animationOffset);
-
- if (isAnimationComplete) {
- m_scrollSnapState->transitionToDestinationReachedState();
- stopScrollSnapAnimation();
- }
-}
-
} // namespace WebCore
#endif // PLATFORM(MAC)