From b8d9440f3e6fd4e0ec090c39f3d3af739d9431ef Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 20 Jan 2015 00:04:07 +0000 Subject: [PATCH] Bug 1042103 - Allow overscroll to be retained between input blocks. r=botond --- gfx/layers/apz/src/APZCTreeManager.cpp | 4 ++-- gfx/layers/apz/src/APZUtils.h | 5 +++++ gfx/layers/apz/src/AsyncPanZoomController.cpp | 16 ++++++++++++---- gfx/layers/apz/src/AsyncPanZoomController.h | 11 ++++++++++- gfx/layers/apz/src/Axis.cpp | 11 ++++++++++- gfx/layers/apz/src/Axis.h | 4 ++++ gfx/layers/apz/src/HitTestingTreeNode.cpp | 2 +- gfx/layers/apz/src/InputQueue.cpp | 2 +- gfx/layers/apz/src/OverscrollHandoffState.cpp | 7 +++++-- gfx/layers/apz/src/OverscrollHandoffState.h | 3 ++- 10 files changed, 52 insertions(+), 13 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index edf67fb6b44..fd137cec9b0 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -1497,7 +1497,7 @@ APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) c // ancestorUntransform is updated to RC.Inverse() * QC.Inverse() when parent == P ancestorUntransform = parent->GetAncestorTransform().Inverse(); // asyncUntransform is updated to PA.Inverse() when parent == P - Matrix4x4 asyncUntransform = Matrix4x4(parent->GetCurrentAsyncTransform()).Inverse(); + Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransformWithOverscroll().Inverse(); // untransformSinceLastApzc is RC.Inverse() * QC.Inverse() * PA.Inverse() Matrix4x4 untransformSinceLastApzc = ancestorUntransform * asyncUntransform; @@ -1529,7 +1529,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co // leftmost matrix in a multiplication is applied first. // asyncUntransform is LA.Inverse() - Matrix4x4 asyncUntransform = Matrix4x4(aApzc->GetCurrentAsyncTransform()).Inverse(); + Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransformWithOverscroll().Inverse(); // aTransformToGeckoOut is initialized to LA.Inverse() * LD * MC * NC * OC * PC result = asyncUntransform * aApzc->GetTransformToLastDispatchedPaint() * aApzc->GetAncestorTransform(); diff --git a/gfx/layers/apz/src/APZUtils.h b/gfx/layers/apz/src/APZUtils.h index 8742589cab1..ec142d75bdc 100644 --- a/gfx/layers/apz/src/APZUtils.h +++ b/gfx/layers/apz/src/APZUtils.h @@ -16,6 +16,11 @@ enum HitTestResult { HitDispatchToContentRegion, }; +enum CancelAnimationFlags : uint32_t { + Default = 0, /* Cancel all animations */ + ExcludeOverscroll = 1 /* Don't clear overscroll */ +}; + } } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 588d66d6436..dd64c7c0b50 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1147,7 +1147,7 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent case ANIMATING_ZOOM: case SMOOTH_SCROLL: case OVERSCROLL_ANIMATION: - CurrentTouchBlock()->GetOverscrollHandoffChain()->CancelAnimations(); + CurrentTouchBlock()->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll); // Fall through. case NOTHING: { mX.StartTouch(point.x, aEvent.mTime); @@ -1270,7 +1270,11 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) // that were not big enough to trigger scrolling. Clear that out. mX.SetVelocity(0); mY.SetVelocity(0); - SetState(NOTHING); + // It's possible we may be overscrolled if the user tapped during a + // previous overscroll pan. Make sure to snap back in this situation. + if (!SnapBackIfOverscrolled()) { + SetState(NOTHING); + } return nsEventStatus_eIgnore; case PANNING: @@ -2165,7 +2169,7 @@ void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation) ScheduleComposite(); } -void AsyncPanZoomController::CancelAnimation() { +void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) { ReentrantMonitorAutoEnter lock(mMonitor); APZC_LOG("%p running CancelAnimation in state %d\n", this, mState); SetState(NOTHING); @@ -2177,7 +2181,7 @@ void AsyncPanZoomController::CancelAnimation() { // Setting the state to nothing and cancelling the animation can // preempt normal mechanisms for relieving overscroll, so we need to clear // overscroll here. - if (mX.IsOverscrolled() || mY.IsOverscrolled()) { + if (!(aFlags & ExcludeOverscroll) && IsOverscrolled()) { ClearOverscroll(); RequestContentRepaint(); ScheduleComposite(); @@ -2654,6 +2658,10 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { return ViewTransform(mFrameMetrics.GetAsyncZoom(), -translation); } +Matrix4x4 AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll() const { + return Matrix4x4(GetCurrentAsyncTransform()) * GetOverscrollTransform(); +} + Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index c6162688d64..ccacbf67b6d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -20,6 +20,7 @@ #include "InputData.h" #include "Axis.h" #include "InputQueue.h" +#include "APZUtils.h" #include "LayersTypes.h" #include "TaskThrottler.h" #include "mozilla/gfx/Matrix.h" @@ -217,6 +218,12 @@ public: */ ViewTransform GetCurrentAsyncTransform() const; + /** + * Returns the same transform as GetCurrentAsyncTransform(), but includes + * any transform due to axis over-scroll. + */ + Matrix4x4 GetCurrentAsyncTransformWithOverscroll() const; + /** * Returns the transform to take something from the coordinate space of the * last thing we know gecko painted, to the coordinate space of the last thing @@ -285,8 +292,10 @@ public: /** * Cancels any currently running animation. + * aFlags is a bit-field to provide specifics of how to cancel the animation. + * See CancelAnimationFlags. */ - void CancelAnimation(); + void CancelAnimation(CancelAnimationFlags aFlags = Default); /** * Clear any overscroll on this APZC. diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index b5ef2065f6c..a88207ca036 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -126,6 +126,8 @@ bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, return false; } + StopSamplingOverscrollAnimation(); + ParentLayerCoord displacement = aDisplacement; // First consume any overscroll in the opposite direction along this axis. @@ -160,12 +162,13 @@ ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) co // The actual overscroll is the requested overscroll multiplied by this // factor; this should prevent overscrolling by more than the composition // length. - float resistanceFactor = 1 - fabsf(mOverscroll) / GetCompositionLength(); + float resistanceFactor = 1 - fabsf(GetOverscroll()) / GetCompositionLength(); return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor; } void Axis::OverscrollBy(ParentLayerCoord aOverscroll) { MOZ_ASSERT(CanScroll()); + StopSamplingOverscrollAnimation(); aOverscroll = ApplyResistance(aOverscroll); if (aOverscroll > 0) { #ifdef DEBUG @@ -200,6 +203,12 @@ ParentLayerCoord Axis::GetOverscroll() const { return result; } +void Axis::StopSamplingOverscrollAnimation() { + ParentLayerCoord overscroll = GetOverscroll(); + ClearOverscroll(); + mOverscroll = overscroll; +} + void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) { // Apply spring physics to the overscroll as time goes on. // Note: this method of sampling isn't perfectly smooth, as it assumes diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index 4f24262139d..f325034a2c4 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -251,6 +251,10 @@ protected: // actual overscroll amount. ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const; + // Helper function to disable overscroll transformations triggered by + // SampleOverscrollAnimation(). + void StopSamplingOverscrollAnimation(); + // Helper function for SampleOverscrollAnimation(). void StepOverscrollAnimation(double aStepDurationMilliseconds); diff --git a/gfx/layers/apz/src/HitTestingTreeNode.cpp b/gfx/layers/apz/src/HitTestingTreeNode.cpp index 0e7bb1b6b9f..9f43a06d9c4 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.cpp +++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp @@ -174,7 +174,7 @@ HitTestingTreeNode::Untransform(const ParentLayerPoint& aPoint) const // convert into Layer coordinate space gfx::Matrix4x4 localTransform = mTransform; if (mApzc) { - localTransform = localTransform * gfx::Matrix4x4(mApzc->GetCurrentAsyncTransform()); + localTransform = localTransform * mApzc->GetCurrentAsyncTransformWithOverscroll(); } gfx::Point4D point = localTransform.Inverse().ProjectPoint(aPoint.ToUnknownPoint()); return point.HasPositiveWCoord() diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index d5ee9c8a28d..5ecdf47d5d8 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -186,7 +186,7 @@ InputQueue::CancelAnimationsForNewBlock(CancelableBlockState* aBlock) INPQ_LOG("block %p tagged as fast-motion\n", touch); } } - aBlock->GetOverscrollHandoffChain()->CancelAnimations(); + aBlock->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll); } } diff --git a/gfx/layers/apz/src/OverscrollHandoffState.cpp b/gfx/layers/apz/src/OverscrollHandoffState.cpp index b3e8cc04a18..36ffb255e06 100644 --- a/gfx/layers/apz/src/OverscrollHandoffState.cpp +++ b/gfx/layers/apz/src/OverscrollHandoffState.cpp @@ -88,9 +88,12 @@ OverscrollHandoffChain::FlushRepaints() const } void -OverscrollHandoffChain::CancelAnimations() const +OverscrollHandoffChain::CancelAnimations(CancelAnimationFlags aFlags) const { - ForEachApzc(&AsyncPanZoomController::CancelAnimation); + MOZ_ASSERT(Length() > 0); + for (uint32_t i = 0; i < Length(); ++i) { + mChain[i]->CancelAnimation(aFlags); + } } void diff --git a/gfx/layers/apz/src/OverscrollHandoffState.h b/gfx/layers/apz/src/OverscrollHandoffState.h index 60d45f73ca4..a5b0200f779 100644 --- a/gfx/layers/apz/src/OverscrollHandoffState.h +++ b/gfx/layers/apz/src/OverscrollHandoffState.h @@ -11,6 +11,7 @@ #include "nsAutoPtr.h" #include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING #include "Units.h" // for ScreenPoint +#include "APZUtils.h" // for CancelAnimationFlags namespace mozilla { namespace layers { @@ -93,7 +94,7 @@ public: void FlushRepaints() const; // Cancel animations all the way up the chain. - void CancelAnimations() const; + void CancelAnimations(CancelAnimationFlags aFlags = Default) const; // Clear overscroll all the way up the chain. void ClearOverscroll() const;