summaryrefslogtreecommitdiffstats
path: root/layout/generic/ScrollVelocityQueue.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/ScrollVelocityQueue.h')
-rw-r--r--layout/generic/ScrollVelocityQueue.h92
1 files changed, 92 insertions, 0 deletions
diff --git a/layout/generic/ScrollVelocityQueue.h b/layout/generic/ScrollVelocityQueue.h
new file mode 100644
index 000000000..ca0e5a83a
--- /dev/null
+++ b/layout/generic/ScrollVelocityQueue.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* 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/. */
+
+#ifndef ScrollVelocityQueue_h_
+#define ScrollVelocityQueue_h_
+
+#include "nsTArray.h"
+#include "nsPoint.h"
+#include "mozilla/TimeStamp.h"
+
+class nsPresContext;
+
+namespace mozilla {
+namespace layout {
+
+/**
+ * ScrollVelocityQueue is used to determine the current velocity of a
+ * scroll frame, derived from scroll position samples.
+ *
+ * Using the last iteration's scroll position, stored in mLastPosition, a
+ * delta of the scroll position is calculated and accumulated in mAccumulator
+ * until the refresh driver returns a new timestamp for MostRecentRefresh().
+ *
+ * When there is a new timestamp from the refresh driver, the accumulated
+ * change in scroll position is divided by the delta of the timestamp to
+ * get an average velocity over that period. This velocity is pushed into
+ * mQueue as a std::pair associating each velocity with the
+ * duration over which it was sampled.
+ *
+ * Samples are removed from mQueue, leaving only those necessary to determine
+ * the average velocity over the recent relevant period, which has a duration
+ * set by the apz.velocity_relevance_time_ms preference.
+ *
+ * The velocity of each sample is clamped to a value set by the
+ * layout.css.scroll-snap.prediction-max-velocity.
+ *
+ * As the average velocity will later be integrated over a duration set by
+ * the layout.css.scroll-snap.prediction-sensitivity preference and the
+ * velocity samples are clamped to a set value, the maximum expected scroll
+ * offset can be calculated. This maximum offset is used to clamp
+ * mAccumulator, eliminating samples that would otherwise result in scroll
+ * snap position selection that is not consistent with the user's perception
+ * of scroll velocity.
+ */
+
+class ScrollVelocityQueue final {
+public:
+ explicit ScrollVelocityQueue(nsPresContext *aPresContext)
+ : mPresContext(aPresContext) {}
+
+ // Sample() is to be called periodically when scroll movement occurs, to
+ // record samples of scroll position used later by GetVelocity().
+ void Sample(const nsPoint& aScrollPosition);
+
+ // Discards velocity samples, resulting in velocity of 0 returned by
+ // GetVelocity until move scroll position updates.
+ void Reset();
+
+ // Get scroll velocity averaged from recent movement, in appunits / second
+ nsPoint GetVelocity();
+private:
+ // A queue of (duration, velocity) pairs; these are the historical average
+ // velocities over the given durations. Durations are in milliseconds,
+ // velocities are in app units per second.
+ nsTArray<std::pair<uint32_t, nsPoint> > mQueue;
+
+ // Accumulates the distance and direction travelled by the scroll frame since
+ // mSampleTime.
+ nsPoint mAccumulator;
+
+ // Time that mAccumulator was last reset and began accumulating.
+ TimeStamp mSampleTime;
+
+ // Scroll offset at the mAccumulator was last reset and began
+ // accumulating.
+ nsPoint mLastPosition;
+
+ // PresContext of the containing frame, used to get timebase
+ nsPresContext* mPresContext;
+
+ // Remove samples from mQueue that no longer contribute to GetVelocity()
+ // due to their age
+ void TrimQueue();
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif /* !defined(ScrollVelocityQueue_h_) */