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 : #include "ScrollVelocityQueue.h"
8 :
9 : #include "gfxPrefs.h"
10 : #include "nsPresContext.h"
11 : #include "nsRefreshDriver.h"
12 :
13 : namespace mozilla {
14 : namespace layout {
15 :
16 : void
17 0 : ScrollVelocityQueue::Sample(const nsPoint& aScrollPosition)
18 : {
19 0 : float flingSensitivity = gfxPrefs::ScrollSnapPredictionSensitivity();
20 0 : int maxVelocity = gfxPrefs::ScrollSnapPredictionMaxVelocity();
21 0 : maxVelocity = nsPresContext::CSSPixelsToAppUnits(maxVelocity);
22 0 : int maxOffset = maxVelocity * flingSensitivity;
23 0 : TimeStamp currentRefreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
24 0 : if (mSampleTime.IsNull()) {
25 0 : mAccumulator = nsPoint();
26 : } else {
27 0 : uint32_t durationMs = (currentRefreshTime - mSampleTime).ToMilliseconds();
28 0 : if (durationMs > gfxPrefs::APZVelocityRelevanceTime()) {
29 0 : mAccumulator = nsPoint();
30 0 : mQueue.Clear();
31 0 : } else if (durationMs == 0) {
32 0 : mAccumulator += aScrollPosition - mLastPosition;
33 : } else {
34 0 : nsPoint velocity = mAccumulator * 1000 / durationMs;
35 0 : velocity.Clamp(maxVelocity);
36 0 : mQueue.AppendElement(std::make_pair(durationMs, velocity));
37 0 : mAccumulator = aScrollPosition - mLastPosition;
38 : }
39 : }
40 0 : mAccumulator.Clamp(maxOffset);
41 0 : mSampleTime = currentRefreshTime;
42 0 : mLastPosition = aScrollPosition;
43 0 : TrimQueue();
44 0 : }
45 :
46 : void
47 0 : ScrollVelocityQueue::TrimQueue()
48 : {
49 0 : if (mSampleTime.IsNull()) {
50 : // There are no samples, nothing to do here.
51 0 : return;
52 : }
53 :
54 0 : TimeStamp currentRefreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
55 0 : nsPoint velocity;
56 0 : uint32_t timeDelta = (currentRefreshTime - mSampleTime).ToMilliseconds();
57 0 : for (int i = mQueue.Length() - 1; i >= 0; i--) {
58 0 : timeDelta += mQueue[i].first;
59 0 : if (timeDelta >= gfxPrefs::APZVelocityRelevanceTime()) {
60 : // The rest of the samples have expired and should be dropped
61 0 : for (; i >= 0; i--) {
62 0 : mQueue.RemoveElementAt(0);
63 : }
64 : }
65 : }
66 : }
67 :
68 : void
69 0 : ScrollVelocityQueue::Reset()
70 : {
71 0 : mAccumulator = nsPoint();
72 0 : mSampleTime = TimeStamp();
73 0 : mQueue.Clear();
74 0 : }
75 :
76 : /**
77 : Calculate the velocity of the scroll frame, in appunits / second.
78 : */
79 : nsPoint
80 0 : ScrollVelocityQueue::GetVelocity()
81 : {
82 0 : TrimQueue();
83 0 : if (mQueue.Length() == 0) {
84 : // If getting the scroll velocity before any scrolling has occurred,
85 : // the velocity must be (0, 0)
86 0 : return nsPoint();
87 : }
88 0 : nsPoint velocity;
89 0 : for (int i = mQueue.Length() - 1; i >= 0; i--) {
90 0 : velocity += mQueue[i].second;
91 : }
92 0 : return velocity / mQueue.Length();;
93 : }
94 :
95 : } // namespace layout
96 : } // namespace mozilla
97 :
|