Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
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 7 : class ScrollVelocityQueue final {
50 : public:
51 43 : explicit ScrollVelocityQueue(nsPresContext *aPresContext)
52 43 : : 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 : private:
65 : // A queue of (duration, velocity) pairs; these are the historical average
66 : // velocities over the given durations. Durations are in milliseconds,
67 : // velocities are in app units per second.
68 : nsTArray<std::pair<uint32_t, nsPoint> > mQueue;
69 :
70 : // Accumulates the distance and direction travelled by the scroll frame since
71 : // mSampleTime.
72 : nsPoint mAccumulator;
73 :
74 : // Time that mAccumulator was last reset and began accumulating.
75 : TimeStamp mSampleTime;
76 :
77 : // Scroll offset at the mAccumulator was last reset and began
78 : // accumulating.
79 : nsPoint mLastPosition;
80 :
81 : // PresContext of the containing frame, used to get timebase
82 : nsPresContext* mPresContext;
83 :
84 : // Remove samples from mQueue that no longer contribute to GetVelocity()
85 : // due to their age
86 : void TrimQueue();
87 : };
88 :
89 : } // namespace layout
90 : } // namespace mozilla
91 :
92 : #endif /* !defined(ScrollVelocityQueue_h_) */
|