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