/* -*- 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_) */