Bug 951793 - Light refactoring to the fling handoff code. r=kats

Passing FlingHandoffState around as an in-out parameter was making
the next change (respecting overscroll-behavior) messy.

MozReview-Commit-ID: 4wuoll20Jt7

--HG--
extra : rebase_source : c5d843254a38196547119419d1a2ad1fd0f3ef09
This commit is contained in:
Botond Ballo 2017-11-03 13:07:48 -04:00
Родитель d561386618
Коммит 2f514da8d8
4 изменённых файлов: 67 добавлений и 78 удалений

Просмотреть файл

@ -2029,16 +2029,16 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
}
}
void
ParentLayerPoint
APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
FlingHandoffState& aHandoffState)
const FlingHandoffState& aHandoffState)
{
// If immediate handoff is disallowed, do not allow handoff beyond the
// single APZC that's scrolled by the input block that triggered this fling.
if (aHandoffState.mIsHandoff &&
!gfxPrefs::APZAllowImmediateHandoff() &&
aHandoffState.mScrolledApzc == aPrev) {
return;
return aHandoffState.mVelocity;
}
const OverscrollHandoffChain* chain = aHandoffState.mChain;
@ -2046,9 +2046,6 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
uint32_t overscrollHandoffChainLength = chain->Length();
uint32_t startIndex;
// This will store any velocity left over after the entire handoff.
ParentLayerPoint finalResidualVelocity = aHandoffState.mVelocity;
// The fling's velocity needs to be transformed from the screen coordinates
// of |aPrev| to the screen coordinates of |next|. To transform a velocity
// correctly, we need to convert it to a displacement. For now, we do this
@ -2065,64 +2062,63 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
// IndexOf will return aOverscrollHandoffChain->Length() if
// |aPrev| is not found.
if (startIndex >= overscrollHandoffChainLength) {
return;
return aHandoffState.mVelocity;
}
} else {
startIndex = 0;
}
// This will store any velocity left over after the entire handoff.
ParentLayerPoint finalResidualVelocity = aHandoffState.mVelocity;
ParentLayerPoint currentVelocity = aHandoffState.mVelocity;
for (; startIndex < overscrollHandoffChainLength; startIndex++) {
current = chain->GetApzcAtIndex(startIndex);
// Make sure the apcz about to be handled can be handled
// Make sure the apzc about to be handled can be handled
if (current == nullptr || current->IsDestroyed()) {
return;
break;
}
endPoint = startPoint + aHandoffState.mVelocity;
endPoint = startPoint + currentVelocity;
// Only transform when current apcz can be transformed with previous
// Only transform when current apzc can be transformed with previous
if (startIndex > 0) {
if (!TransformDisplacement(this,
chain->GetApzcAtIndex(startIndex - 1),
current,
startPoint,
endPoint)) {
return;
}
}
ParentLayerPoint transformedVelocity = endPoint - startPoint;
aHandoffState.mVelocity = transformedVelocity;
if (current->AttemptFling(aHandoffState)) {
// Coming out of AttemptFling(), the handoff state's velocity is the
// residual velocity after attempting to fling |current|.
ParentLayerPoint residualVelocity = aHandoffState.mVelocity;
// If there's no residual velocity, there's nothing more to hand off.
if (IsZero(residualVelocity)) {
finalResidualVelocity = ParentLayerPoint();
break;
}
// If there is residual velocity, subtract the proportion of used
// velocity from finalResidualVelocity and continue handoff along the
// chain.
if (!FuzzyEqualsAdditive(transformedVelocity.x,
residualVelocity.x, COORDINATE_EPSILON)) {
finalResidualVelocity.x *= (residualVelocity.x / transformedVelocity.x);
}
if (!FuzzyEqualsAdditive(transformedVelocity.y,
residualVelocity.y, COORDINATE_EPSILON)) {
finalResidualVelocity.y *= (residualVelocity.y / transformedVelocity.y);
}
}
FlingHandoffState transformedHandoffState = aHandoffState;
transformedHandoffState.mVelocity = (endPoint - startPoint);
ParentLayerPoint 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,
residualVelocity.x, COORDINATE_EPSILON)) {
finalResidualVelocity.x *= (residualVelocity.x / transformedHandoffState.mVelocity.x);
}
if (!FuzzyEqualsAdditive(transformedHandoffState.mVelocity.y,
residualVelocity.y, COORDINATE_EPSILON)) {
finalResidualVelocity.y *= (residualVelocity.y / transformedHandoffState.mVelocity.y);
}
currentVelocity = residualVelocity;
}
// Set the handoff state's velocity to any residual velocity left over
// after the entire handoff process.
aHandoffState.mVelocity = finalResidualVelocity;
// Return any residual velocity left over after the entire handoff process.
return finalResidualVelocity;
}
bool

Просмотреть файл

@ -422,13 +422,14 @@ public:
* start a fling (in this case the fling is given to the
* first APZC in the chain)
*
* aHandoffState.mVelocity will be modified depending on how much of that
* velocity has been consumed by APZCs in the overscroll hand-off chain.
* The return value is the "residual velocity", the portion of
* |aHandoffState.mVelocity| that was not consumed by APZCs in the
* handoff chain doing flings.
* The caller can use this value to determine whether it should consume
* the excess velocity by going into an overscroll fling.
* the excess velocity by going into overscroll.
*/
void DispatchFling(AsyncPanZoomController* aApzc,
FlingHandoffState& aHandoffState);
ParentLayerPoint DispatchFling(AsyncPanZoomController* aApzc,
const FlingHandoffState& aHandoffState);
void StartScrollbarDrag(
const ScrollableLayerGuid& aGuid,

Просмотреть файл

@ -1592,10 +1592,10 @@ nsEventStatus AsyncPanZoomController::HandleEndOfPan()
// null before calling DispatchFling(). This is necessary because Destroy(),
// which nulls out mTreeManager, could be called concurrently.
if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
FlingHandoffState handoffState{flingVelocity,
GetCurrentTouchBlock()->GetOverscrollHandoffChain(),
false /* not handoff */,
GetCurrentTouchBlock()->GetScrolledApzc()};
const FlingHandoffState handoffState{flingVelocity,
GetCurrentTouchBlock()->GetOverscrollHandoffChain(),
false /* not handoff */,
GetCurrentTouchBlock()->GetScrolledApzc()};
treeManagerLocal->DispatchFling(this, handoffState);
}
return nsEventStatus_eConsumeNoDefault;
@ -2787,20 +2787,25 @@ RefPtr<const OverscrollHandoffChain> AsyncPanZoomController::BuildOverscrollHand
return result;
}
void AsyncPanZoomController::AcceptFling(FlingHandoffState& aHandoffState) {
ParentLayerPoint AsyncPanZoomController::AttemptFling(const FlingHandoffState& aHandoffState) {
RecursiveMutexAutoLock lock(mRecursiveMutex);
if (!IsPannable()) {
return aHandoffState.mVelocity;
}
// We may have a pre-existing velocity for whatever reason (for example,
// a previously handed off fling). We don't want to clobber that.
APZC_LOG("%p accepting fling with velocity %s\n", this,
Stringify(aHandoffState.mVelocity).c_str());
ParentLayerPoint residualVelocity = aHandoffState.mVelocity;
if (mX.CanScroll()) {
mX.SetVelocity(mX.GetVelocity() + aHandoffState.mVelocity.x);
aHandoffState.mVelocity.x = 0;
residualVelocity.x = 0;
}
if (mY.CanScroll()) {
mY.SetVelocity(mY.GetVelocity() + aHandoffState.mVelocity.y);
aHandoffState.mVelocity.y = 0;
residualVelocity.y = 0;
}
// If there's a scroll snap point near the predicted fling destination,
@ -2816,16 +2821,8 @@ void AsyncPanZoomController::AcceptFling(FlingHandoffState& aHandoffState) {
aHandoffState.mScrolledApzc);
StartAnimation(fling);
}
}
bool AsyncPanZoomController::AttemptFling(FlingHandoffState& aHandoffState) {
// If we are pannable, take over the fling ourselves.
if (IsPannable()) {
AcceptFling(aHandoffState);
return true;
}
return false;
return residualVelocity;
}
void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
@ -2833,13 +2830,13 @@ void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelo
const RefPtr<const AsyncPanZoomController>& aScrolledApzc) {
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
if (treeManagerLocal) {
FlingHandoffState handoffState{aVelocity,
aOverscrollHandoffChain,
true /* handoff */,
aScrolledApzc};
treeManagerLocal->DispatchFling(this, handoffState);
if (!IsZero(handoffState.mVelocity) && IsPannable() && gfxPrefs::APZOverscrollEnabled()) {
mOverscrollEffect->HandleFlingOverscroll(handoffState.mVelocity);
const FlingHandoffState handoffState{aVelocity,
aOverscrollHandoffChain,
true /* handoff */,
aScrolledApzc};
ParentLayerPoint residualVelocity = treeManagerLocal->DispatchFling(this, handoffState);
if (!IsZero(residualVelocity) && IsPannable() && gfxPrefs::APZOverscrollEnabled()) {
mOverscrollEffect->HandleFlingOverscroll(residualVelocity);
}
}
}

Просмотреть файл

@ -1002,16 +1002,14 @@ private:
public:
/**
* Attempt a fling with the velocity specified in |aHandoffState|.
* If we are not pannable, the fling is handed off to the next APZC in
* the handoff chain via mTreeManager->DispatchFling().
* Returns true iff. the entire velocity of the fling was consumed by
* this APZC. |aHandoffState.mVelocity| is modified to contain any
* unused, residual velocity.
* |aHandoffState.mIsHandoff| should be true iff. the fling was handed off
* 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.
*/
bool AttemptFling(FlingHandoffState& aHandoffState);
ParentLayerPoint AttemptFling(const FlingHandoffState& aHandoffState);
private:
friend class AndroidFlingAnimation;
@ -1044,9 +1042,6 @@ private:
void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity);
// Helper function used by AttemptFling().
void AcceptFling(FlingHandoffState& aHandoffState);
// Start an overscroll animation with the given initial velocity.
void StartOverscrollAnimation(const ParentLayerPoint& aVelocity);