diff options
Diffstat (limited to 'layout/generic/ScrollVelocityQueue.h')
-rw-r--r-- | layout/generic/ScrollVelocityQueue.h | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/layout/generic/ScrollVelocityQueue.h b/layout/generic/ScrollVelocityQueue.h new file mode 100644 index 0000000000..86791e866d --- /dev/null +++ b/layout/generic/ScrollVelocityQueue.h @@ -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/. */ + +#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_) */ |