1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef ScrollVelocityQueue_h_ 8 #define ScrollVelocityQueue_h_ 9 10 #include "nsTArray.h" 11 #include "nsPoint.h" 12 #include "mozilla/TimeStamp.h" 13 14 class nsPresContext; 15 16 namespace mozilla { 17 namespace layout { 18 19 /** 20 * ScrollVelocityQueue is used to determine the current velocity of a 21 * scroll frame, derived from scroll position samples. 22 * 23 * Using the last iteration's scroll position, stored in mLastPosition, a 24 * delta of the scroll position is calculated and accumulated in mAccumulator 25 * until the refresh driver returns a new timestamp for MostRecentRefresh(). 26 * 27 * When there is a new timestamp from the refresh driver, the accumulated 28 * change in scroll position is divided by the delta of the timestamp to 29 * get an average velocity over that period. This velocity is pushed into 30 * mQueue as a std::pair associating each velocity with the 31 * duration over which it was sampled. 32 * 33 * Samples are removed from mQueue, leaving only those necessary to determine 34 * the average velocity over the recent relevant period, which has a duration 35 * set by the apz.velocity_relevance_time_ms preference. 36 * 37 * The velocity of each sample is clamped to a value set by the 38 * layout.css.scroll-snap.prediction-max-velocity. 39 * 40 * As the average velocity will later be integrated over a duration set by 41 * the layout.css.scroll-snap.prediction-sensitivity preference and the 42 * velocity samples are clamped to a set value, the maximum expected scroll 43 * offset can be calculated. This maximum offset is used to clamp 44 * mAccumulator, eliminating samples that would otherwise result in scroll 45 * snap position selection that is not consistent with the user's perception 46 * of scroll velocity. 47 */ 48 49 class ScrollVelocityQueue final { 50 public: ScrollVelocityQueue(nsPresContext * aPresContext)51 explicit ScrollVelocityQueue(nsPresContext* aPresContext) 52 : mPresContext(aPresContext) {} 53 54 // Sample() is to be called periodically when scroll movement occurs, to 55 // record samples of scroll position used later by GetVelocity(). 56 void Sample(const nsPoint& aScrollPosition); 57 58 // Discards velocity samples, resulting in velocity of 0 returned by 59 // GetVelocity until move scroll position updates. 60 void Reset(); 61 62 // Get scroll velocity averaged from recent movement, in appunits / second 63 nsPoint GetVelocity(); 64 65 private: 66 // A queue of (duration, velocity) pairs; these are the historical average 67 // velocities over the given durations. Durations are in milliseconds, 68 // velocities are in app units per second. 69 nsTArray<std::pair<uint32_t, nsPoint> > mQueue; 70 71 // Accumulates the distance and direction travelled by the scroll frame since 72 // mSampleTime. 73 nsPoint mAccumulator; 74 75 // Time that mAccumulator was last reset and began accumulating. 76 TimeStamp mSampleTime; 77 78 // Scroll offset at the mAccumulator was last reset and began 79 // accumulating. 80 nsPoint mLastPosition; 81 82 // PresContext of the containing frame, used to get timebase 83 nsPresContext* mPresContext; 84 85 // Remove samples from mQueue that no longer contribute to GetVelocity() 86 // due to their age 87 void TrimQueue(); 88 }; 89 90 } // namespace layout 91 } // namespace mozilla 92 93 #endif /* !defined(ScrollVelocityQueue_h_) */ 94