mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 21:05:36 +00:00
Bug 1034376 - Avoid APZC being stuck in overscrolled state when CancelAnimation() is called during panning. r=kats
--HG-- extra : rebase_source : bbc3a02d6be7081be77b58cb2795aa57ce794002
This commit is contained in:
parent
e5d3086227
commit
6770de9ed0
@ -412,34 +412,13 @@ GetFrameTime() {
|
||||
return sFrameTime;
|
||||
}
|
||||
|
||||
// This is a base class for animations that can deal with
|
||||
// overscroll states. In particular, it ensures that overscroll
|
||||
// states are cleared when the animation is cancelled.
|
||||
class OverscrollableAnimation: public AsyncPanZoomAnimation {
|
||||
public:
|
||||
OverscrollableAnimation(AsyncPanZoomController& aApzc,
|
||||
const TimeDuration& aRepaintInterval = TimeDuration::Forever())
|
||||
: AsyncPanZoomAnimation(aRepaintInterval)
|
||||
, mApzc(aApzc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Cancel() MOZ_OVERRIDE
|
||||
{
|
||||
mApzc.mX.ClearOverscroll();
|
||||
mApzc.mY.ClearOverscroll();
|
||||
}
|
||||
|
||||
protected:
|
||||
AsyncPanZoomController& mApzc;
|
||||
};
|
||||
|
||||
class FlingAnimation: public OverscrollableAnimation {
|
||||
class FlingAnimation: public AsyncPanZoomAnimation {
|
||||
public:
|
||||
FlingAnimation(AsyncPanZoomController& aApzc,
|
||||
bool aApplyAcceleration,
|
||||
bool aAllowOverscroll)
|
||||
: OverscrollableAnimation(aApzc, TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
|
||||
: AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval()))
|
||||
, mApzc(aApzc)
|
||||
, mAllowOverscroll(aAllowOverscroll)
|
||||
{
|
||||
TimeStamp now = GetFrameTime();
|
||||
@ -594,6 +573,7 @@ private:
|
||||
+ (aSupplemental * gfxPrefs::APZFlingAccelSupplementalMultiplier());
|
||||
}
|
||||
|
||||
AsyncPanZoomController& mApzc;
|
||||
bool mAllowOverscroll;
|
||||
};
|
||||
|
||||
@ -656,10 +636,10 @@ private:
|
||||
CSSToScreenScale mEndZoom;
|
||||
};
|
||||
|
||||
class OverscrollSnapBackAnimation: public OverscrollableAnimation {
|
||||
class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
|
||||
public:
|
||||
OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
|
||||
: OverscrollableAnimation(aApzc)
|
||||
: mApzc(aApzc)
|
||||
{
|
||||
}
|
||||
|
||||
@ -671,6 +651,8 @@ public:
|
||||
bool continueY = mApzc.mY.SampleSnapBack(aDelta);
|
||||
return continueX || continueY;
|
||||
}
|
||||
private:
|
||||
AsyncPanZoomController& mApzc;
|
||||
};
|
||||
|
||||
void
|
||||
@ -1771,10 +1753,13 @@ void AsyncPanZoomController::CancelAnimation() {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
APZC_LOG("%p running CancelAnimation in state %d\n", this, mState);
|
||||
SetState(NOTHING);
|
||||
if (mAnimation) {
|
||||
mAnimation->Cancel();
|
||||
mAnimation = nullptr;
|
||||
// mAnimation->Cancel() may have done something that requires a repaint.
|
||||
mAnimation = nullptr;
|
||||
// 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()) {
|
||||
mX.ClearOverscroll();
|
||||
mY.ClearOverscroll();
|
||||
RequestContentRepaint();
|
||||
ScheduleComposite();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
|
@ -800,7 +800,6 @@ public:
|
||||
bool TakeOverFling(ScreenPoint aVelocity);
|
||||
|
||||
private:
|
||||
friend class OverscrollableAnimation;
|
||||
friend class FlingAnimation;
|
||||
friend class OverscrollSnapBackAnimation;
|
||||
// The initial velocity of the most recent fling.
|
||||
@ -1039,9 +1038,6 @@ public:
|
||||
virtual bool Sample(FrameMetrics& aFrameMetrics,
|
||||
const TimeDuration& aDelta) = 0;
|
||||
|
||||
// Called if the animation is cancelled before it ends.
|
||||
virtual void Cancel() {}
|
||||
|
||||
/**
|
||||
* Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
|
||||
* for more information.
|
||||
|
@ -212,7 +212,8 @@ void ApzcPan(AsyncPanZoomController* apzc,
|
||||
int aTouchEndY,
|
||||
bool expectIgnoredPan = false,
|
||||
bool hasTouchListeners = false,
|
||||
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr) {
|
||||
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
|
||||
bool aKeepFingerDown = false) {
|
||||
|
||||
const int TIME_BETWEEN_TOUCH_EVENT = 100;
|
||||
const int OVERCOME_TOUCH_TOLERANCE = 100;
|
||||
@ -272,11 +273,13 @@ void ApzcPan(AsyncPanZoomController* apzc,
|
||||
status = apzc->ReceiveInputEvent(mti);
|
||||
EXPECT_EQ(touchMoveStatus, status);
|
||||
|
||||
mti =
|
||||
MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0);
|
||||
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
||||
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0));
|
||||
status = apzc->ReceiveInputEvent(mti);
|
||||
if (!aKeepFingerDown) {
|
||||
mti =
|
||||
MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0);
|
||||
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
||||
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0));
|
||||
status = apzc->ReceiveInputEvent(mti);
|
||||
}
|
||||
|
||||
// Since we've explicitly built the overscroll handoff chain before
|
||||
// touch-start, we need to explicitly clear it after touch-end.
|
||||
@ -966,6 +969,36 @@ TEST_F(AsyncPanZoomControllerTester, OverScrollAbort) {
|
||||
apzc->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(AsyncPanZoomControllerTester, OverScrollPanningAbort) {
|
||||
TestScopedBoolPref overscrollEnabledPref("apz.overscroll.enabled", true);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
|
||||
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc, tm);
|
||||
|
||||
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
// Pan sufficiently to hit overscroll behaviour. Keep the finger down so
|
||||
// the pan does not end.
|
||||
int time = 0;
|
||||
int touchStart = 500;
|
||||
int touchEnd = 10;
|
||||
ApzcPan(apzc, tm, time, touchStart, touchEnd,
|
||||
false, false, nullptr, // filling it defaults, wish we had named arguments
|
||||
true); // keep finger down
|
||||
EXPECT_TRUE(apzc->IsOverscrolled());
|
||||
|
||||
// Check that calling CancelAnimation() while the user is still panning
|
||||
// (and thus no fling or snap-back animation has had a chance to start)
|
||||
// clears the overscroll.
|
||||
apzc->CancelAnimation();
|
||||
EXPECT_FALSE(apzc->IsOverscrolled());
|
||||
apzc->AssertStateIsReset();
|
||||
|
||||
apzc->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(AsyncPanZoomControllerTester, ShortPress) {
|
||||
nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
|
||||
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
|
||||
|
Loading…
Reference in New Issue
Block a user