summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/AutoscrollAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/apz/src/AutoscrollAnimation.cpp')
-rw-r--r--gfx/layers/apz/src/AutoscrollAnimation.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/AutoscrollAnimation.cpp b/gfx/layers/apz/src/AutoscrollAnimation.cpp
new file mode 100644
index 0000000000..8d4b8fca10
--- /dev/null
+++ b/gfx/layers/apz/src/AutoscrollAnimation.cpp
@@ -0,0 +1,93 @@
+/* -*- 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 "AutoscrollAnimation.h"
+
+#include <cmath> // for sqrtf()
+
+#include "AsyncPanZoomController.h"
+#include "APZCTreeManager.h"
+#include "FrameMetrics.h"
+#include "mozilla/Telemetry.h" // for Telemetry
+
+namespace mozilla {
+namespace layers {
+
+// Helper function for AutoscrollAnimation::DoSample().
+// Basically copied as-is from toolkit/actors/AutoScrollChild.jsm.
+static float Accelerate(ScreenCoord curr, ScreenCoord start) {
+ static const int speed = 12;
+ float val = (curr - start) / speed;
+ if (val > 1) {
+ return val * sqrtf(val) - 1;
+ }
+ if (val < -1) {
+ return val * sqrtf(-val) + 1;
+ }
+ return 0;
+}
+
+AutoscrollAnimation::AutoscrollAnimation(AsyncPanZoomController& aApzc,
+ const ScreenPoint& aAnchorLocation)
+ : mApzc(aApzc), mAnchorLocation(aAnchorLocation) {}
+
+bool AutoscrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
+ const TimeDuration& aDelta) {
+ APZCTreeManager* treeManager = mApzc.GetApzcTreeManager();
+ if (!treeManager) {
+ return false;
+ }
+
+ ScreenPoint mouseLocation = treeManager->GetCurrentMousePosition();
+
+ // The implementation of this function closely mirrors that of its main-
+ // thread equivalent, the autoscrollLoop() function in
+ // toolkit/actors/AutoScrollChild.jsm.
+
+ // Avoid long jumps when the browser hangs for more than |maxTimeDelta| ms.
+ static const TimeDuration maxTimeDelta = TimeDuration::FromMilliseconds(100);
+ TimeDuration timeDelta = TimeDuration::Min(aDelta, maxTimeDelta);
+
+ float timeCompensation = timeDelta.ToMilliseconds() / 20;
+
+ // Notes:
+ // - The main-thread implementation rounds the scroll delta to an integer,
+ // and keeps track of the fractional part as an "error". It does this
+ // because it uses Window.scrollBy() or Element.scrollBy() to perform
+ // the scrolling, and those functions truncate the fractional part of
+ // the offset. APZ does no such truncation, so there's no need to keep
+ // track of the fractional part separately.
+ // - The Accelerate() function takes Screen coordinates as inputs, but
+ // its output is interpreted as CSS coordinates. This is intentional,
+ // insofar as autoscrollLoop() does the same thing.
+ CSSPoint scrollDelta{
+ Accelerate(mouseLocation.x, mAnchorLocation.x) * timeCompensation,
+ Accelerate(mouseLocation.y, mAnchorLocation.y) * timeCompensation};
+
+ mApzc.ScrollByAndClamp(scrollDelta);
+
+ // An autoscroll animation never ends of its own accord.
+ // It can be stopped in response to various input events, in which case
+ // AsyncPanZoomController::StopAutoscroll() will stop it via
+ // CancelAnimation().
+ return true;
+}
+
+void AutoscrollAnimation::Cancel(CancelAnimationFlags aFlags) {
+ // The cancellation was initiated by browser.js, so there's no need to
+ // notify it.
+ if (aFlags & TriggeredExternally) {
+ return;
+ }
+
+ if (RefPtr<GeckoContentController> controller =
+ mApzc.GetGeckoContentController()) {
+ controller->CancelAutoscroll(mApzc.GetGuid());
+ }
+}
+
+} // namespace layers
+} // namespace mozilla