Bug 1292034 - Improve the controls over when flywheel/fling acceleration kicks in. r?rbarker
This patch adds a new pref, which controls the minimum velocity required on a fling
for it to accelerate a previous fling. This makes it so that a fast fling followed
by a very slow fling doesn't get accelerated. Also, update the AndroidAPZ code
to respect the pre-existing fling acceleration interval pref, which disallows
fling acceleration/flywheel if the two flings are too far apart in time.
MozReview-Commit-ID: IPHmAQ2ZZQK
--- a/gfx/layers/apz/src/AndroidAPZ.cpp
+++ b/gfx/layers/apz/src/AndroidAPZ.cpp
@@ -115,21 +115,28 @@ AndroidFlingAnimation::AndroidFlingAnima
}
}
mPreviousVelocity = velocity;
int32_t originX = ClampStart(mStartOffset.x, scrollRangeStartX, scrollRangeEndX);
int32_t originY = ClampStart(mStartOffset.y, scrollRangeStartY, scrollRangeEndY);
if (!state->mLastFling.IsNull()) {
- // If we had a fling going previously, we should update the timestamp on
- // it because otherwise it may have a stale velocity
+ // If it's been too long since the previous fling, or if the new fling's
+ // velocity is too low, don't allow flywheel to kick in. If we do allow
+ // flywheel to kick in, then we need to update the timestamp on the
+ // StackScroller because otherwise it might use a stale velocity.
TimeDuration flingDuration = TimeStamp::Now() - state->mLastFling;
- bool unused = false;
- mOverScroller->ComputeScrollOffset(flingDuration.ToMilliseconds(), &unused);
+ if (flingDuration.ToMilliseconds() < gfxPrefs::APZFlingAccelInterval()
+ && velocity.Length() >= gfxPrefs::APZFlingAccelMinVelocity()) {
+ bool unused = false;
+ mOverScroller->ComputeScrollOffset(flingDuration.ToMilliseconds(), &unused);
+ } else {
+ mOverScroller->ForceFinished(true);
+ }
}
mOverScroller->Fling(originX, originY,
// Android needs the velocity in pixels per second and it is in pixels per ms.
(int32_t)(velocity.x * 1000.0f), (int32_t)(velocity.y * 1000.0f),
(int32_t)floor(scrollRangeStartX), (int32_t)ceil(scrollRangeEndX),
(int32_t)floor(scrollRangeStartY), (int32_t)ceil(scrollRangeEndY),
0, 0, 0);
state->mLastFling = TimeStamp::Now();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -196,16 +196,21 @@ typedef GenericFlingAnimation FlingAnima
*
* \li\b apz.fling_accel_interval_ms
* The time that determines whether a second fling will be treated as
* accelerated. If two flings are started within this interval, the second one
* will be accelerated. Setting an interval of 0 means that acceleration will
* be disabled.\n
* Units: milliseconds
*
+ * \li\b apz.fling_accel_min_velocity
+ * The minimum velocity of the second fling for it to be considered for fling
+ * acceleration.
+ * Units: screen pixels per milliseconds
+ *
* \li\b apz.fling_accel_base_mult
* \li\b apz.fling_accel_supplemental_mult
* When applying an acceleration on a fling, the new computed velocity is
* (new_fling_velocity * base_mult) + (old_velocity * supplemental_mult).
* The base_mult and supplemental_mult multiplier values are controlled by
* these prefs. Note that "old_velocity" here is the initial velocity of the
* previous fling _after_ acceleration was applied to it (if applicable).
*
--- a/gfx/layers/apz/src/GenericFlingAnimation.h
+++ b/gfx/layers/apz/src/GenericFlingAnimation.h
@@ -62,17 +62,18 @@ public:
// on the opposite side of zero, and we still want the y-fling to get accelerated.
// Note that the acceleration code is only applied on the APZC that initiates
// the fling; the accelerated velocities are then handed off using the
// normal DispatchFling codepath.
// Acceleration is only applied in the APZC that originated the fling,
// not in APZCs further down the handoff chain during handoff.
bool applyAcceleration = !aFlingIsHandedOff;
if (applyAcceleration && !mApzc.mLastFlingTime.IsNull()
- && (now - mApzc.mLastFlingTime).ToMilliseconds() < gfxPrefs::APZFlingAccelInterval()) {
+ && (now - mApzc.mLastFlingTime).ToMilliseconds() < gfxPrefs::APZFlingAccelInterval()
+ && velocity.Length() >= gfxPrefs::APZFlingAccelMinVelocity()) {
if (SameDirection(velocity.x, mApzc.mLastFlingVelocity.x)) {
velocity.x = Accelerate(velocity.x, mApzc.mLastFlingVelocity.x);
FLING_LOG("%p Applying fling x-acceleration from %f to %f (delta %f)\n",
&mApzc, mApzc.mX.GetVelocity(), velocity.x, mApzc.mLastFlingVelocity.x);
mApzc.mX.SetVelocity(velocity.x);
}
if (SameDirection(velocity.y, mApzc.mLastFlingVelocity.y)) {
velocity.y = Accelerate(velocity.y, mApzc.mLastFlingVelocity.y);
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -257,16 +257,17 @@ private:
DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100);
DECL_GFX_PREF(Live, "apz.disable_for_scroll_linked_effects", APZDisableForScrollLinkedEffects, bool, false);
DECL_GFX_PREF(Live, "apz.displayport_expiry_ms", APZDisplayPortExpiryTime, uint32_t, 15000);
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false);
DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f);
DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500);
DECL_GFX_PREF(Live, "apz.fling_accel_supplemental_mult", APZFlingAccelSupplementalMultiplier, float, 1.0f);
+ DECL_GFX_PREF(Live, "apz.fling_accel_min_velocity", APZFlingAccelMinVelocity, float, 1.5f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_x1", APZCurveFunctionX1, float, 0.0f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_x2", APZCurveFunctionX2, float, 1.0f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_y1", APZCurveFunctionY1, float, 0.0f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_y2", APZCurveFunctionY2, float, 1.0f);
DECL_GFX_PREF(Live, "apz.fling_curve_threshold_inches_per_ms", APZCurveThreshold, float, -1.0f);
DECL_GFX_PREF(Live, "apz.fling_friction", APZFlingFriction, float, 0.002f);
DECL_GFX_PREF(Live, "apz.fling_min_velocity_threshold", APZFlingMinVelocityThreshold, float, 0.5f);
DECL_GFX_PREF(Live, "apz.fling_stop_on_tap_threshold", APZFlingStopOnTapThreshold, float, 0.05f);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -626,18 +626,19 @@ pref("apz.axis_lock.breakout_angle", "0.
pref("apz.axis_lock.direct_pan_angle", "1.047197"); // PI / 3 (60 degrees)
pref("apz.content_response_timeout", 400);
pref("apz.drag.enabled", false);
pref("apz.danger_zone_x", 50);
pref("apz.danger_zone_y", 100);
pref("apz.disable_for_scroll_linked_effects", false);
pref("apz.displayport_expiry_ms", 15000);
pref("apz.enlarge_displayport_when_clipped", false);
+pref("apz.fling_accel_interval_ms", 500);
+pref("apz.fling_accel_min_velocity", "1.5");
pref("apz.fling_accel_base_mult", "1.0");
-pref("apz.fling_accel_interval_ms", 500);
pref("apz.fling_accel_supplemental_mult", "1.0");
pref("apz.fling_curve_function_x1", "0.0");
pref("apz.fling_curve_function_y1", "0.0");
pref("apz.fling_curve_function_x2", "1.0");
pref("apz.fling_curve_function_y2", "1.0");
pref("apz.fling_curve_threshold_inches_per_ms", "-1.0");
pref("apz.fling_friction", "0.002");
pref("apz.fling_min_velocity_threshold", "0.5");