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 mozilla_layers_DesktopFlingPhysics_h_
8 #define mozilla_layers_DesktopFlingPhysics_h_
9 
10 #include "AsyncPanZoomController.h"
11 #include "Units.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/StaticPrefs_apz.h"
14 
15 namespace mozilla {
16 namespace layers {
17 
18 class DesktopFlingPhysics {
19  public:
Init(const ParentLayerPoint & aStartingVelocity,float aPLPPI)20   void Init(const ParentLayerPoint& aStartingVelocity,
21             float aPLPPI /* unused */) {
22     mVelocity = aStartingVelocity;
23   }
Sample(const TimeDuration & aDelta,ParentLayerPoint * aOutVelocity,ParentLayerPoint * aOutOffset)24   void Sample(const TimeDuration& aDelta, ParentLayerPoint* aOutVelocity,
25               ParentLayerPoint* aOutOffset) {
26     float friction = StaticPrefs::apz_fling_friction();
27     float threshold = StaticPrefs::apz_fling_stopped_threshold();
28 
29     mVelocity = ParentLayerPoint(
30         ApplyFrictionOrCancel(mVelocity.x, aDelta, friction, threshold),
31         ApplyFrictionOrCancel(mVelocity.y, aDelta, friction, threshold));
32 
33     *aOutVelocity = mVelocity;
34     *aOutOffset = mVelocity * aDelta.ToMilliseconds();
35   }
36 
37  private:
38   /**
39    * Applies friction to the given velocity and returns the result, or
40    * returns zero if the velocity is too low.
41    * |aVelocity| is the incoming velocity.
42    * |aDelta| is the amount of time that has passed since the last time
43    * friction was applied.
44    * |aFriction| is the amount of friction to apply.
45    * |aThreshold| is the velocity below which the fling is cancelled.
46    */
ApplyFrictionOrCancel(float aVelocity,const TimeDuration & aDelta,float aFriction,float aThreshold)47   static float ApplyFrictionOrCancel(float aVelocity,
48                                      const TimeDuration& aDelta,
49                                      float aFriction, float aThreshold) {
50     if (fabsf(aVelocity) <= aThreshold) {
51       // If the velocity is very low, just set it to 0 and stop the fling,
52       // otherwise we'll just asymptotically approach 0 and the user won't
53       // actually see any changes.
54       return 0.0f;
55     }
56 
57     aVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
58     return aVelocity;
59   }
60 
61   ParentLayerPoint mVelocity;
62 };
63 
64 }  // namespace layers
65 }  // namespace mozilla
66 
67 #endif  // mozilla_layers_DesktopFlingPhysics_h_
68