Bug 951793 - Obey overscroll-behavior for fling handoff. r=kats
MozReview-Commit-ID: 9i2AgmW3Inm
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -2077,46 +2077,61 @@ APZCTreeManager::DispatchFling(AsyncPanZ
// Make sure the apzc about to be handled can be handled
if (current == nullptr || current->IsDestroyed()) {
break;
}
endPoint = startPoint + currentVelocity;
+ RefPtr<AsyncPanZoomController> prevApzc = (startIndex > 0)
+ ? chain->GetApzcAtIndex(startIndex - 1)
+ : nullptr;
+
// Only transform when current apzc can be transformed with previous
- if (startIndex > 0) {
+ if (prevApzc) {
if (!TransformDisplacement(this,
- chain->GetApzcAtIndex(startIndex - 1),
+ prevApzc,
current,
startPoint,
endPoint)) {
break;
}
}
+ ParentLayerPoint availableVelocity = (endPoint - startPoint);
+ ParentLayerPoint residualVelocity;
+
FlingHandoffState transformedHandoffState = aHandoffState;
- transformedHandoffState.mVelocity = (endPoint - startPoint);
+ transformedHandoffState.mVelocity = availableVelocity;
- ParentLayerPoint residualVelocity = current->AttemptFling(transformedHandoffState);
+ // Obey overscroll-behavior.
+ if (prevApzc) {
+ residualVelocity += prevApzc->AdjustHandoffVelocityForOverscrollBehavior(transformedHandoffState.mVelocity);
+ }
+
+ residualVelocity += current->AttemptFling(transformedHandoffState);
// If there's no residual velocity, there's nothing more to hand off.
if (IsZero(residualVelocity)) {
return ParentLayerPoint();
}
// If any of the velocity available to be handed off was consumed,
// subtract the proportion of consumed velocity from finalResidualVelocity.
- if (!FuzzyEqualsAdditive(transformedHandoffState.mVelocity.x,
+ // Note: it's important to compare |residualVelocity| to |availableVelocity|
+ // here and not to |transformedHandoffState.mVelocity|, since the latter
+ // may have been modified by AdjustHandoffVelocityForOverscrollBehavior().
+ if (!FuzzyEqualsAdditive(availableVelocity.x,
residualVelocity.x, COORDINATE_EPSILON)) {
- finalResidualVelocity.x *= (residualVelocity.x / transformedHandoffState.mVelocity.x);
+ finalResidualVelocity.x *= (residualVelocity.x / availableVelocity.x);
}
- if (!FuzzyEqualsAdditive(transformedHandoffState.mVelocity.y,
+ if (!FuzzyEqualsAdditive(availableVelocity.y,
residualVelocity.y, COORDINATE_EPSILON)) {
- finalResidualVelocity.y *= (residualVelocity.y / transformedHandoffState.mVelocity.y);
+ finalResidualVelocity.y *= (residualVelocity.y / availableVelocity.y);
}
currentVelocity = residualVelocity;
}
// Return any residual velocity left over after the entire handoff process.
return finalResidualVelocity;
}
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2820,16 +2820,32 @@ ParentLayerPoint AsyncPanZoomController:
aHandoffState.mIsHandoff,
aHandoffState.mScrolledApzc);
StartAnimation(fling);
}
return residualVelocity;
}
+ParentLayerPoint AsyncPanZoomController::AdjustHandoffVelocityForOverscrollBehavior(ParentLayerPoint& aHandoffVelocity) const
+{
+ RecursiveMutexAutoLock lock(mRecursiveMutex);
+ ParentLayerPoint residualVelocity;
+ if (!mX.OverscrollBehaviorAllowsHandoff()) {
+ residualVelocity.x = aHandoffVelocity.x;
+ aHandoffVelocity.x = 0;
+ }
+ if (!mY.OverscrollBehaviorAllowsHandoff()) {
+ residualVelocity.y = aHandoffVelocity.y;
+ aHandoffVelocity.y = 0;
+ }
+ return residualVelocity;
+}
+
+
void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
const RefPtr<const AsyncPanZoomController>& aScrolledApzc) {
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
if (treeManagerLocal) {
const FlingHandoffState handoffState{aVelocity,
aOverscrollHandoffChain,
true /* handoff */,
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1006,16 +1006,18 @@ public:
* from a previous APZC, and determines whether acceleration is applied
* to the fling.
* We only accept the fling in the direction(s) in which we are pannable.
* Returns the "residual velocity", i.e. the portion of
* |aHandoffState.mVelocity| that this APZC did not consume.
*/
ParentLayerPoint AttemptFling(const FlingHandoffState& aHandoffState);
+ ParentLayerPoint AdjustHandoffVelocityForOverscrollBehavior(ParentLayerPoint& aHandoffVelocity) const;
+
private:
friend class AndroidFlingAnimation;
friend class AutoscrollAnimation;
friend class GenericFlingAnimation;
friend class OverscrollAnimation;
friend class SmoothScrollAnimation;
friend class GenericScrollAnimation;
friend class WheelScrollAnimation;