summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/GenericScrollAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/apz/src/GenericScrollAnimation.cpp')
-rw-r--r--gfx/layers/apz/src/GenericScrollAnimation.cpp120
1 files changed, 120 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/GenericScrollAnimation.cpp b/gfx/layers/apz/src/GenericScrollAnimation.cpp
new file mode 100644
index 0000000000..9320482295
--- /dev/null
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GenericScrollAnimation.h"
+
+#include "AsyncPanZoomController.h"
+#include "FrameMetrics.h"
+#include "nsPoint.h"
+#include "ScrollAnimationPhysics.h"
+#include "ScrollAnimationBezierPhysics.h"
+#include "ScrollAnimationMSDPhysics.h"
+#include "mozilla/StaticPrefs_general.h"
+
+namespace mozilla {
+namespace layers {
+
+GenericScrollAnimation::GenericScrollAnimation(
+ AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition,
+ const ScrollAnimationBezierPhysicsSettings& aSettings)
+ : mApzc(aApzc), mFinalDestination(aInitialPosition) {
+ // ScrollAnimationBezierPhysics (despite it's name) handles the case of
+ // general.smoothScroll being disabled whereas ScrollAnimationMSDPhysics does
+ // not (ie it scrolls smoothly).
+ if (StaticPrefs::general_smoothScroll() &&
+ StaticPrefs::general_smoothScroll_msdPhysics_enabled()) {
+ mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(aInitialPosition);
+ } else {
+ mAnimationPhysics =
+ MakeUnique<ScrollAnimationBezierPhysics>(aInitialPosition, aSettings);
+ }
+}
+
+void GenericScrollAnimation::UpdateDelta(TimeStamp aTime, const nsPoint& aDelta,
+ const nsSize& aCurrentVelocity) {
+ mFinalDestination += aDelta;
+
+ Update(aTime, aCurrentVelocity);
+}
+
+void GenericScrollAnimation::UpdateDestination(TimeStamp aTime,
+ const nsPoint& aDestination,
+ const nsSize& aCurrentVelocity) {
+ mFinalDestination = aDestination;
+
+ Update(aTime, aCurrentVelocity);
+}
+
+void GenericScrollAnimation::Update(TimeStamp aTime,
+ const nsSize& aCurrentVelocity) {
+ // Clamp the final destination to the scrollable area.
+ CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
+ clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
+ clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
+ mFinalDestination = CSSPoint::ToAppUnits(clamped);
+
+ mAnimationPhysics->Update(aTime, mFinalDestination, aCurrentVelocity);
+}
+
+bool GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
+ const TimeDuration& aDelta) {
+ TimeStamp now = mApzc.GetFrameTime().Time();
+ CSSToParentLayerScale zoom(aFrameMetrics.GetZoom());
+ if (zoom == CSSToParentLayerScale(0)) {
+ return false;
+ }
+
+ // If the animation is finished, make sure the final position is correct by
+ // using one last displacement. Otherwise, compute the delta via the timing
+ // function as normal.
+ bool finished = mAnimationPhysics->IsFinished(now);
+ nsPoint sampledDest = mAnimationPhysics->PositionAt(now);
+ ParentLayerPoint displacement = (CSSPoint::FromAppUnits(sampledDest) -
+ aFrameMetrics.GetVisualScrollOffset()) *
+ zoom;
+
+ if (finished) {
+ mApzc.mX.SetVelocity(0);
+ mApzc.mY.SetVelocity(0);
+ } else if (!IsZero(displacement / zoom)) {
+ // Convert velocity from AppUnits/Seconds to ParentLayerCoords/Milliseconds
+ nsSize velocity = mAnimationPhysics->VelocityAt(now);
+ ParentLayerPoint velocityPL =
+ CSSPoint::FromAppUnits(nsPoint(velocity.width, velocity.height)) * zoom;
+ mApzc.mX.SetVelocity(velocityPL.x / 1000.0);
+ mApzc.mY.SetVelocity(velocityPL.y / 1000.0);
+ }
+ // Note: we ignore overscroll for generic animations.
+ ParentLayerPoint adjustedOffset, overscroll;
+ mApzc.mX.AdjustDisplacement(
+ displacement.x, adjustedOffset.x, overscroll.x,
+ mDirectionForcedToOverscroll == Some(ScrollDirection::eHorizontal));
+ mApzc.mY.AdjustDisplacement(
+ displacement.y, adjustedOffset.y, overscroll.y,
+ mDirectionForcedToOverscroll == Some(ScrollDirection::eVertical));
+ // If we expected to scroll, but there's no more scroll range on either axis,
+ // then end the animation early. Note that the initial displacement could be 0
+ // if the compositor ran very quickly (<1ms) after the animation was created.
+ // When that happens we want to make sure the animation continues.
+ if (!IsZero(displacement / zoom) && IsZero(adjustedOffset / zoom)) {
+ // Nothing more to do - end the animation.
+ return false;
+ }
+ mApzc.ScrollBy(adjustedOffset / zoom);
+ return !finished;
+}
+
+bool GenericScrollAnimation::HandleScrollOffsetUpdate(
+ const Maybe<CSSPoint>& aRelativeDelta) {
+ if (aRelativeDelta) {
+ mAnimationPhysics->ApplyContentShift(*aRelativeDelta);
+ return true;
+ }
+ return false;
+}
+
+} // namespace layers
+} // namespace mozilla