FlingAccelerator.cpp (4736B)
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 "FlingAccelerator.h" 8 9 #include "mozilla/StaticPrefs_apz.h" 10 11 #include "GenericFlingAnimation.h" // for FLING_LOG and FlingHandoffState 12 13 namespace mozilla { 14 namespace layers { 15 16 void FlingAccelerator::Reset() { 17 mPreviousFlingStartingVelocity = ParentLayerPoint{}; 18 mPreviousFlingCancelVelocity = ParentLayerPoint{}; 19 mIsTracking = false; 20 } 21 22 static bool SameDirection(float aVelocity1, float aVelocity2) { 23 return (aVelocity1 == 0.0f) || (aVelocity2 == 0.0f) || 24 (IsNegative(aVelocity1) == IsNegative(aVelocity2)); 25 } 26 27 static float Accelerate(float aBase, float aSupplemental) { 28 return (aBase * StaticPrefs::apz_fling_accel_base_mult()) + 29 (aSupplemental * StaticPrefs::apz_fling_accel_supplemental_mult()); 30 } 31 32 ParentLayerPoint FlingAccelerator::GetFlingStartingVelocity( 33 const SampleTime& aNow, const ParentLayerPoint& aVelocity, 34 const FlingHandoffState& aHandoffState) { 35 // If the fling should be accelerated and is in the same direction as the 36 // previous fling, boost the velocity to be the sum of the two. Check separate 37 // axes separately because we could have two vertical flings with small 38 // horizontal components on the opposite side of zero, and we still want the 39 // y-fling to get accelerated. 40 ParentLayerPoint velocity = aVelocity; 41 if (ShouldAccelerate(aNow, aVelocity, aHandoffState)) { 42 if (velocity.x != 0 && 43 SameDirection(velocity.x, mPreviousFlingStartingVelocity.x)) { 44 velocity.x = Accelerate(velocity.x, mPreviousFlingStartingVelocity.x); 45 FLING_LOG("%p Applying fling x-acceleration from %f to %f (delta %f)\n", 46 this, aVelocity.x.value, velocity.x.value, 47 mPreviousFlingStartingVelocity.x.value); 48 } 49 if (velocity.y != 0 && 50 SameDirection(velocity.y, mPreviousFlingStartingVelocity.y)) { 51 velocity.y = Accelerate(velocity.y, mPreviousFlingStartingVelocity.y); 52 FLING_LOG("%p Applying fling y-acceleration from %f to %f (delta %f)\n", 53 this, aVelocity.y.value, velocity.y.value, 54 mPreviousFlingStartingVelocity.y.value); 55 } 56 } 57 58 Reset(); 59 60 mPreviousFlingStartingVelocity = velocity; 61 mIsTracking = true; 62 63 return velocity; 64 } 65 66 bool FlingAccelerator::ShouldAccelerate( 67 const SampleTime& aNow, const ParentLayerPoint& aVelocity, 68 const FlingHandoffState& aHandoffState) const { 69 if (!IsTracking()) { 70 FLING_LOG("%p Fling accelerator was reset, not accelerating.\n", this); 71 return false; 72 } 73 74 if (!aHandoffState.mTouchStartRestingTime) { 75 FLING_LOG("%p Don't have a touch start resting time, not accelerating.\n", 76 this); 77 return false; 78 } 79 80 double msBetweenTouchStartAndPanStart = 81 aHandoffState.mTouchStartRestingTime->ToMilliseconds(); 82 FLING_LOG( 83 "%p ShouldAccelerate with pan velocity %f pixels/ms, min pan velocity %f " 84 "pixels/ms, previous fling cancel velocity %f pixels/ms, time elapsed " 85 "since starting previous time between touch start and pan " 86 "start %fms.\n", 87 this, float(aVelocity.Length()), float(aHandoffState.mMinPanVelocity), 88 float(mPreviousFlingCancelVelocity.Length()), 89 float(msBetweenTouchStartAndPanStart)); 90 91 if (aVelocity.Length() < StaticPrefs::apz_fling_accel_min_fling_velocity()) { 92 FLING_LOG("%p Fling velocity too low (%f), not accelerating.\n", this, 93 float(aVelocity.Length())); 94 return false; 95 } 96 97 if (aHandoffState.mMinPanVelocity < 98 StaticPrefs::apz_fling_accel_min_pan_velocity()) { 99 FLING_LOG( 100 "%p Panning velocity was too slow at some point during the pan (%f), " 101 "not accelerating.\n", 102 this, float(aHandoffState.mMinPanVelocity)); 103 return false; 104 } 105 106 if (mPreviousFlingCancelVelocity.Length() < 107 StaticPrefs::apz_fling_accel_min_fling_velocity()) { 108 FLING_LOG( 109 "%p The previous fling animation had slowed down too much when it was " 110 "interrupted (%f), not accelerating.\n", 111 this, float(mPreviousFlingCancelVelocity.Length())); 112 return false; 113 } 114 115 if (msBetweenTouchStartAndPanStart >= 116 StaticPrefs::apz_fling_accel_max_pause_interval_ms()) { 117 FLING_LOG( 118 "%p Too much time (%fms) elapsed between touch start and pan start, " 119 "not accelerating.\n", 120 this, msBetweenTouchStartAndPanStart); 121 return false; 122 } 123 124 return true; 125 } 126 127 } // namespace layers 128 } // namespace mozilla