Bug 1037591 - Move a bunch of boilerplate code into the tester classes. r=botond

This commit is contained in:
Kartikaya Gupta 2014-07-14 19:07:54 -04:00
parent d586e07c49
commit 83d46f0c1b

View File

@ -181,6 +181,62 @@ TestFrameMetrics()
return fm;
}
class APZCBasicTester : public AsyncPanZoomControllerTester {
public:
APZCBasicTester(AsyncPanZoomController::GestureBehavior aGestureBehavior = AsyncPanZoomController::DEFAULT_GESTURES)
: mGestureBehavior(aGestureBehavior)
{
}
protected:
virtual void SetUp()
{
testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
mcc = new NiceMock<MockContentControllerDelayed>();
tm = new TestAPZCTreeManager();
apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior);
apzc->SetFrameMetrics(TestFrameMetrics());
}
virtual void TearDown()
{
apzc->Destroy();
}
void UseTouchListenerMetrics()
{
FrameMetrics frameMetrics(TestFrameMetrics());
frameMetrics.mMayHaveTouchListeners = true;
apzc->SetFrameMetrics(frameMetrics);
}
void MakeApzcZoomable()
{
apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25f), CSSToScreenScale(4.0f)));
}
void MakeApzcUnzoomable()
{
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
}
AsyncPanZoomController::GestureBehavior mGestureBehavior;
TimeStamp testStartTime;
nsRefPtr<MockContentControllerDelayed> mcc;
nsRefPtr<TestAPZCTreeManager> tm;
nsRefPtr<TestAsyncPanZoomController> apzc;
};
class APZCGestureDetectorTester : public APZCBasicTester {
public:
APZCGestureDetectorTester()
: APZCBasicTester(AsyncPanZoomController::USE_GESTURE_DETECTOR)
{
}
};
static nsEventStatus
ApzcDown(AsyncPanZoomController* apzc, int aX, int aY, int& aTime)
{
@ -267,7 +323,7 @@ ApzcPan(AsyncPanZoomController* aApzc,
if (!aKeepFingerDown) {
status = ApzcUp(aApzc, 10, aTouchEndY, aTime);
} else {
status = -1;
status = (nsEventStatus)-1;
}
if (aOutEventStatuses) {
(*aOutEventStatuses)[3] = status;
@ -433,84 +489,93 @@ ApzcPinchWithTouchInputAndCheckStatus(AsyncPanZoomController* aApzc,
EXPECT_EQ(statuses[2], expectedStatus);
}
static
void DoPinchTest(bool aUseGestureRecognizer, bool aShouldTriggerPinch,
nsTArray<uint32_t> *aAllowedTouchBehaviors = nullptr) {
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc, tm,
aUseGestureRecognizer
? AsyncPanZoomController::USE_GESTURE_DETECTOR
: AsyncPanZoomController::DEFAULT_GESTURES);
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 980, 480);
fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200);
fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
fm.SetScrollOffset(CSSPoint(300, 300));
fm.SetZoom(CSSToScreenScale(2.0));
apzc->SetFrameMetrics(fm);
apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
if (aShouldTriggerPinch) {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
} else {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtMost(2));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
class APZCPinchTester : public APZCBasicTester {
public:
APZCPinchTester(AsyncPanZoomController::GestureBehavior aGestureBehavior = AsyncPanZoomController::DEFAULT_GESTURES)
: APZCBasicTester(aGestureBehavior)
{
}
int touchInputId = 0;
if (aUseGestureRecognizer) {
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 1.25, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 1.25, aShouldTriggerPinch);
protected:
void DoPinchTest(bool aShouldTriggerPinch,
nsTArray<uint32_t> *aAllowedTouchBehaviors = nullptr)
{
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 980, 480);
fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200);
fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
fm.SetScrollOffset(CSSPoint(300, 300));
fm.SetZoom(CSSToScreenScale(2.0));
apzc->SetFrameMetrics(fm);
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
MakeApzcZoomable();
if (aShouldTriggerPinch) {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
} else {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtMost(2));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
}
int touchInputId = 0;
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 1.25, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 1.25, aShouldTriggerPinch);
}
fm = apzc->GetFrameMetrics();
if (aShouldTriggerPinch) {
// the visible area of the document in CSS pixels is now x=305 y=310 w=40 h=80
EXPECT_EQ(2.5f, fm.GetZoom().scale);
EXPECT_EQ(305, fm.GetScrollOffset().x);
EXPECT_EQ(310, fm.GetScrollOffset().y);
} else {
// The frame metrics should stay the same since touch-action:none makes
// apzc ignore pinch gestures.
EXPECT_EQ(2.0f, fm.GetZoom().scale);
EXPECT_EQ(300, fm.GetScrollOffset().x);
EXPECT_EQ(300, fm.GetScrollOffset().y);
}
// part 2 of the test, move to the top-right corner of the page and pinch and
// make sure we stay in the correct spot
fm.SetZoom(CSSToScreenScale(2.0));
fm.SetScrollOffset(CSSPoint(930, 5));
apzc->SetFrameMetrics(fm);
// the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 0.5, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 0.5, aShouldTriggerPinch);
}
fm = apzc->GetFrameMetrics();
if (aShouldTriggerPinch) {
// the visible area of the document in CSS pixels is now x=880 y=0 w=100 h=200
EXPECT_EQ(1.0f, fm.GetZoom().scale);
EXPECT_EQ(880, fm.GetScrollOffset().x);
EXPECT_EQ(0, fm.GetScrollOffset().y);
} else {
EXPECT_EQ(2.0f, fm.GetZoom().scale);
EXPECT_EQ(930, fm.GetScrollOffset().x);
EXPECT_EQ(5, fm.GetScrollOffset().y);
}
}
};
fm = apzc->GetFrameMetrics();
if (aShouldTriggerPinch) {
// the visible area of the document in CSS pixels is now x=305 y=310 w=40 h=80
EXPECT_EQ(2.5f, fm.GetZoom().scale);
EXPECT_EQ(305, fm.GetScrollOffset().x);
EXPECT_EQ(310, fm.GetScrollOffset().y);
} else {
// The frame metrics should stay the same since touch-action:none makes
// apzc ignore pinch gestures.
EXPECT_EQ(2.0f, fm.GetZoom().scale);
EXPECT_EQ(300, fm.GetScrollOffset().x);
EXPECT_EQ(300, fm.GetScrollOffset().y);
class APZCPinchGestureDetectorTester : public APZCPinchTester {
public:
APZCPinchGestureDetectorTester()
: APZCPinchTester(AsyncPanZoomController::USE_GESTURE_DETECTOR)
{
}
// part 2 of the test, move to the top-right corner of the page and pinch and
// make sure we stay in the correct spot
fm.SetZoom(CSSToScreenScale(2.0));
fm.SetScrollOffset(CSSPoint(930, 5));
apzc->SetFrameMetrics(fm);
// the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100
if (aUseGestureRecognizer) {
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 0.5, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
} else {
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 0.5, aShouldTriggerPinch);
}
fm = apzc->GetFrameMetrics();
if (aShouldTriggerPinch) {
// the visible area of the document in CSS pixels is now x=880 y=0 w=100 h=200
EXPECT_EQ(1.0f, fm.GetZoom().scale);
EXPECT_EQ(880, fm.GetScrollOffset().x);
EXPECT_EQ(0, fm.GetScrollOffset().y);
} else {
EXPECT_EQ(2.0f, fm.GetZoom().scale);
EXPECT_EQ(930, fm.GetScrollOffset().x);
EXPECT_EQ(5, fm.GetScrollOffset().y);
}
apzc->Destroy();
}
};
TEST_F(AsyncPanZoomControllerTester, Constructor) {
// RefCounted class can't live in the stack
@ -519,42 +584,40 @@ TEST_F(AsyncPanZoomControllerTester, Constructor) {
apzc->SetFrameMetrics(TestFrameMetrics());
}
TEST_F(AsyncPanZoomControllerTester, Pinch_DefaultGestures_NoTouchAction) {
DoPinchTest(false, true);
TEST_F(APZCPinchTester, Pinch_DefaultGestures_NoTouchAction) {
DoPinchTest(true);
}
TEST_F(AsyncPanZoomControllerTester, Pinch_UseGestureDetector_NoTouchAction) {
DoPinchTest(true, true);
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_NoTouchAction) {
DoPinchTest(true);
}
TEST_F(AsyncPanZoomControllerTester, Pinch_UseGestureDetector_TouchActionNone) {
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNone) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
nsTArray<uint32_t> behaviors;
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::NONE);
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::NONE);
DoPinchTest(true, false, &behaviors);
DoPinchTest(false, &behaviors);
}
TEST_F(AsyncPanZoomControllerTester, Pinch_UseGestureDetector_TouchActionZoom) {
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionZoom) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
nsTArray<uint32_t> behaviors;
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
DoPinchTest(true, true, &behaviors);
DoPinchTest(true, &behaviors);
}
TEST_F(AsyncPanZoomControllerTester, Pinch_UseGestureDetector_TouchActionNotAllowZoom) {
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNotAllowZoom) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
nsTArray<uint32_t> behaviors;
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
DoPinchTest(true, false, &behaviors);
DoPinchTest(false, &behaviors);
}
TEST_F(AsyncPanZoomControllerTester, Overzoom) {
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
TEST_F(APZCBasicTester, Overzoom) {
// the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 100, 100);
fm.mCompositionBounds = ParentLayerRect(0, 0, 100, 100);
@ -562,8 +625,8 @@ TEST_F(AsyncPanZoomControllerTester, Overzoom) {
fm.SetScrollOffset(CSSPoint(10, 0));
fm.SetZoom(CSSToScreenScale(1.0));
apzc->SetFrameMetrics(fm);
apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25), CSSToScreenScale(4.0)));
// the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
MakeApzcZoomable();
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
@ -578,13 +641,7 @@ TEST_F(AsyncPanZoomControllerTester, Overzoom) {
EXPECT_LT(abs(fm.GetScrollOffset().y), 1e-5);
}
TEST_F(AsyncPanZoomControllerTester, SimpleTransform) {
TimeStamp testStartTime = TimeStamp::Now();
// RefCounted class can't live in the stack
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
apzc->SetFrameMetrics(TestFrameMetrics());
TEST_F(APZCBasicTester, SimpleTransform) {
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
@ -594,10 +651,7 @@ TEST_F(AsyncPanZoomControllerTester, SimpleTransform) {
}
TEST_F(AsyncPanZoomControllerTester, ComplexTransform) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
TEST_F(APZCBasicTester, ComplexTransform) {
// This test assumes there is a page that gets rendered to
// two layers. In CSS pixels, the first layer is 50x50 and
// the second layer is 25x50. The widget scale factor is 3.0
@ -613,9 +667,7 @@ TEST_F(AsyncPanZoomControllerTester, ComplexTransform) {
// CSS pixels). The displayport is 1 extra CSS pixel on all
// sides.
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
nsRefPtr<TestAsyncPanZoomController> childApzc = new TestAsyncPanZoomController(0, mcc);
nsRefPtr<TestAsyncPanZoomController> childApzc = new TestAsyncPanZoomController(0, mcc, tm);
const char* layerTreeSyntax = "c(c)";
// LayerID 0 1
@ -698,59 +750,49 @@ TEST_F(AsyncPanZoomControllerTester, ComplexTransform) {
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
}
static void
DoPanTest(bool aShouldTriggerScroll, uint32_t aBehavior)
{
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
class APZCPanningTester : public APZCBasicTester {
protected:
void DoPanTest(bool aShouldTriggerScroll, uint32_t aBehavior)
{
if (aShouldTriggerScroll) {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
} else {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
}
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc, tm);
int time = 0;
int touchStart = 50;
int touchEnd = 10;
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
if (aShouldTriggerScroll) {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
} else {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
}
// Pan down
ApzcPanAndCheckStatus(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
int time = 0;
int touchStart = 50;
int touchEnd = 10;
ScreenPoint pointOut;
ViewTransform viewTransformOut;
if (aShouldTriggerScroll) {
EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut);
EXPECT_NE(ViewTransform(), viewTransformOut);
} else {
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
}
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
// Pan back
ApzcPanAndCheckStatus(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
// Pan down
ApzcPanAndCheckStatus(apzc, tm, time, touchStart, touchEnd, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
if (aShouldTriggerScroll) {
EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut);
EXPECT_NE(ViewTransform(), viewTransformOut);
} else {
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
}
};
// Pan back
ApzcPanAndCheckStatus(apzc, tm, time, touchEnd, touchStart, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, Pan) {
TEST_F(APZCPanningTester, Pan) {
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::NONE);
}
@ -759,41 +801,30 @@ TEST_F(AsyncPanZoomControllerTester, Pan) {
// According to the pointer-events/touch-action spec AUTO and PAN_Y touch-action values allow vertical
// scrolling while NONE and PAN_X forbid it. The first parameter of DoPanTest method specifies this
// behavior.
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionAuto) {
TEST_F(APZCPanningTester, PanWithTouchActionAuto) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
}
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionNone) {
TEST_F(APZCPanningTester, PanWithTouchActionNone) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoPanTest(false, 0);
}
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionPanX) {
TEST_F(APZCPanningTester, PanWithTouchActionPanX) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoPanTest(false, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN);
}
TEST_F(AsyncPanZoomControllerTester, PanWithTouchActionPanY) {
TEST_F(APZCPanningTester, PanWithTouchActionPanY) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
}
TEST_F(AsyncPanZoomControllerTester, PanWithPreventDefault) {
TEST_F(APZCBasicTester, PanWithPreventDefault) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc, tm);
FrameMetrics frameMetrics(TestFrameMetrics());
frameMetrics.mMayHaveTouchListeners = true;
apzc->SetFrameMetrics(frameMetrics);
apzc->NotifyLayersUpdated(frameMetrics, true);
UseTouchListenerMetrics();
int time = 0;
int touchStart = 50;
@ -813,21 +844,9 @@ TEST_F(AsyncPanZoomControllerTester, PanWithPreventDefault) {
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, Fling) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
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);
TEST_F(APZCBasicTester, Fling) {
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
@ -845,86 +864,65 @@ TEST_F(AsyncPanZoomControllerTester, Fling) {
EXPECT_GT(pointOut.y, lastPoint.y);
lastPoint = pointOut;
}
apzc->Destroy();
}
// Start a fling, and then tap while the fling is ongoing. When
// aSlow is false, the tap will happen while the fling is at a
// high velocity, and we check that the tap doesn't trigger sending a tap
// to content. If aSlow is true, the tap will happen while the fling
// is at a slow velocity, and we check that the tap does trigger sending
// a tap to content. See bug 1022956.
void
DoFlingStopTest(bool aSlow) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
class APZCFlingStopTester : public APZCGestureDetectorTester {
protected:
// Start a fling, and then tap while the fling is ongoing. When
// aSlow is false, the tap will happen while the fling is at a
// high velocity, and we check that the tap doesn't trigger sending a tap
// to content. If aSlow is true, the tap will happen while the fling
// is at a slow velocity, and we check that the tap does trigger sending
// a tap to content. See bug 1022956.
void DoFlingStopTest(bool aSlow) {
int time = 0;
int touchStart = 50;
int touchEnd = 10;
nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
// Start the fling down.
ApzcPan(apzc, tm, time, touchStart, touchEnd);
// The touchstart from the pan will leave some cancelled tasks in the queue, clear them out
EXPECT_EQ(2, mcc->RunThroughDelayedTasks());
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
// If we want to tap while the fling is fast, let the fling advance for 10ms only. If we want
// the fling to slow down more, advance to 2000ms. These numbers may need adjusting if our
// friction and threshold values change, but they should be deterministic at least.
int timeDelta = aSlow ? 2000 : 10;
int tapCallsExpected = aSlow ? 1 : 0;
int delayedTasksExpected = aSlow ? 3 : 2;
int time = 0;
int touchStart = 50;
int touchEnd = 10;
// Advance the fling animation by timeDelta milliseconds.
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut);
// Start the fling down.
ApzcPan(apzc, tm, time, touchStart, touchEnd);
// The touchstart from the pan will leave some cancelled tasks in the queue, clear them out
EXPECT_EQ(2, mcc->RunThroughDelayedTasks());
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
// call out of it if and only if the fling is slow.
EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
ApzcTap(apzc, 10, 10, time, 0, nullptr);
EXPECT_EQ(delayedTasksExpected, mcc->RunThroughDelayedTasks());
// If we want to tap while the fling is fast, let the fling advance for 10ms only. If we want
// the fling to slow down more, advance to 2000ms. These numbers may need adjusting if our
// friction and threshold values change, but they should be deterministic at least.
int timeDelta = aSlow ? 2000 : 10;
int tapCallsExpected = aSlow ? 1 : 0;
int delayedTasksExpected = aSlow ? 3 : 2;
// Verify that we didn't advance any further after the fling was aborted, in either case.
ScreenPoint finalPointOut;
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut);
EXPECT_EQ(pointOut.x, finalPointOut.x);
EXPECT_EQ(pointOut.y, finalPointOut.y);
// Advance the fling animation by timeDelta milliseconds.
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut);
apzc->AssertStateIsReset();
}
};
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
// call out of it if and only if the fling is slow.
EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
ApzcTap(apzc, 10, 10, time, 0, nullptr);
EXPECT_EQ(delayedTasksExpected, mcc->RunThroughDelayedTasks());
// Verify that we didn't advance any further after the fling was aborted, in either case.
ScreenPoint finalPointOut;
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut);
EXPECT_EQ(pointOut.x, finalPointOut.x);
EXPECT_EQ(pointOut.y, finalPointOut.y);
apzc->AssertStateIsReset();
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, FlingStop) {
TEST_F(APZCFlingStopTester, FlingStop) {
DoFlingStopTest(false);
}
TEST_F(AsyncPanZoomControllerTester, FlingStopTap) {
TEST_F(APZCFlingStopTester, FlingStopTap) {
DoFlingStopTest(true);
}
TEST_F(AsyncPanZoomControllerTester, OverScrollPanning) {
TEST_F(APZCBasicTester, OverScrollPanning) {
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
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 behavior
int time = 0;
int touchStart = 500;
@ -960,22 +958,11 @@ TEST_F(AsyncPanZoomControllerTester, OverScrollPanning) {
EXPECT_FALSE(apzc->IsOverscrolled());
apzc->AssertStateIsReset();
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, OverScrollAbort) {
TEST_F(APZCBasicTester, OverScrollAbort) {
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
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 behavior
int time = 0;
int touchStart = 500;
@ -997,20 +984,11 @@ TEST_F(AsyncPanZoomControllerTester, OverScrollAbort) {
apzc->CancelAnimation();
EXPECT_FALSE(apzc->IsOverscrolled());
apzc->AssertStateIsReset();
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, OverScrollPanningAbort) {
TEST_F(APZCBasicTester, OverScrollPanningAbort) {
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, 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;
@ -1026,19 +1004,10 @@ TEST_F(AsyncPanZoomControllerTester, OverScrollPanningAbort) {
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();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
TEST_F(APZCGestureDetectorTester, ShortPress) {
MakeApzcUnzoomable();
int time = 0;
nsEventStatus status = ApzcTap(apzc, 10, 10, time, 100, mcc.get());
@ -1052,18 +1021,10 @@ TEST_F(AsyncPanZoomControllerTester, ShortPress) {
mcc->RunDelayedTask();
apzc->AssertStateIsReset();
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, MediumPress) {
nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
TEST_F(APZCGestureDetectorTester, MediumPress) {
MakeApzcUnzoomable();
int time = 0;
nsEventStatus status = ApzcTap(apzc, 10, 10, time, 400, mcc.get());
@ -1077,179 +1038,156 @@ TEST_F(AsyncPanZoomControllerTester, MediumPress) {
mcc->RunDelayedTask();
apzc->AssertStateIsReset();
apzc->Destroy();
}
void
DoLongPressTest(uint32_t aBehavior) {
nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
class APZCLongPressTester : public APZCGestureDetectorTester {
protected:
void DoLongPressTest(uint32_t aBehavior) {
MakeApzcUnzoomable();
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
int time = 0;
int time = 0;
nsEventStatus status = ApzcDown(apzc, 10, 10, time);
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
nsEventStatus status = ApzcDown(apzc, 10, 10, time);
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
// SetAllowedTouchBehavior() must be called after sending touch-start.
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
// SetAllowedTouchBehavior() must be called after sending touch-start.
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
MockFunction<void(std::string checkPointName)> check;
MockFunction<void(std::string checkPointName)> check;
{
InSequence s;
{
InSequence s;
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
EXPECT_CALL(check, Call("preHandleLongTapUp"));
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTapUp"));
}
EXPECT_CALL(check, Call("preHandleLongTapUp"));
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTapUp"));
mcc->CheckHasDelayedTask();
// Manually invoke the longpress while the touch is currently down.
check.Call("preHandleLongTap");
mcc->RunDelayedTask();
check.Call("postHandleLongTap");
// Destroy pending MAX_TAP timeout task
mcc->DestroyOldestTask();
// There should be a TimeoutContentResponse task in the queue still
// Clear the waiting-for-content timeout task, then send the signal that
// content has handled this long tap. This takes the place of the
// "contextmenu" event.
mcc->CheckHasDelayedTask();
mcc->ClearDelayedTask();
apzc->ContentReceivedTouch(true);
time += 1000;
status = ApzcUp(apzc, 10, 10, time);
EXPECT_EQ(nsEventStatus_eIgnore, status);
// To get a LongTapUp event, we must kick APZC to flush its event queue. This
// would normally happen if we had a (Tab|RenderFrame)(Parent|Child)
// mechanism.
check.Call("preHandleLongTapUp");
apzc->ContentReceivedTouch(false);
check.Call("postHandleLongTapUp");
apzc->AssertStateIsReset();
}
mcc->CheckHasDelayedTask();
void DoLongPressPreventDefaultTest(uint32_t aBehavior) {
MakeApzcUnzoomable();
// Manually invoke the longpress while the touch is currently down.
check.Call("preHandleLongTap");
mcc->RunDelayedTask();
check.Call("postHandleLongTap");
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
// Destroy pending MAX_TAP timeout task
mcc->DestroyOldestTask();
// There should be a TimeoutContentResponse task in the queue still
// Clear the waiting-for-content timeout task, then send the signal that
// content has handled this long tap. This takes the place of the
// "contextmenu" event.
mcc->CheckHasDelayedTask();
mcc->ClearDelayedTask();
apzc->ContentReceivedTouch(true);
int touchX = 10,
touchStartY = 10,
touchEndY = 50;
time += 1000;
int time = 0;
nsEventStatus status = ApzcDown(apzc, touchX, touchStartY, time);
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
status = ApzcUp(apzc, 10, 10, time);
EXPECT_EQ(nsEventStatus_eIgnore, status);
// SetAllowedTouchBehavior() must be called after sending touch-start.
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
// To get a LongTapUp event, we must kick APZC to flush its event queue. This
// would normally happen if we had a (Tab|RenderFrame)(Parent|Child)
// mechanism.
check.Call("preHandleLongTapUp");
apzc->ContentReceivedTouch(false);
check.Call("postHandleLongTapUp");
MockFunction<void(std::string checkPointName)> check;
apzc->AssertStateIsReset();
apzc->Destroy();
}
{
InSequence s;
void
DoLongPressPreventDefaultTest(uint32_t aBehavior) {
// We have to initialize both an integer time and TimeStamp time because
// TimeStamp doesn't have any ToXXX() functions for converting back to
// primitives.
TimeStamp testStartTime = TimeStamp::Now();
int time = 0;
AsyncPanZoomController::SetFrameTime(testStartTime);
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
}
nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
mcc->CheckHasDelayedTask();
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
// Manually invoke the longpress while the touch is currently down.
check.Call("preHandleLongTap");
mcc->RunDelayedTask();
check.Call("postHandleLongTap");
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
// Destroy pending MAX_TAP timeout task
mcc->DestroyOldestTask();
// Clear the waiting-for-content timeout task, then send the signal that
// content has handled this long tap. This takes the place of the
// "contextmenu" event.
mcc->ClearDelayedTask();
apzc->ContentReceivedTouch(true);
int touchX = 10,
touchStartY = 10,
touchEndY = 50;
time += 1000;
nsEventStatus status = ApzcDown(apzc, touchX, touchStartY, time);
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0);
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0));
status = apzc->ReceiveInputEvent(mti);
EXPECT_EQ(nsEventStatus_eIgnore, status);
// SetAllowedTouchBehavior() must be called after sending touch-start.
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
status = ApzcUp(apzc, touchX, touchEndY, time);
EXPECT_EQ(nsEventStatus_eIgnore, status);
MockFunction<void(std::string checkPointName)> check;
// Flush the event queue. Once the "contextmenu" event is handled, any touch
// events that come from the same series of start->n*move->end events should
// be discarded, even if only the "contextmenu" event is preventDefaulted.
apzc->ContentReceivedTouch(false);
{
InSequence s;
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
apzc->AssertStateIsReset();
}
};
mcc->CheckHasDelayedTask();
// Manually invoke the longpress while the touch is currently down.
check.Call("preHandleLongTap");
mcc->RunDelayedTask();
check.Call("postHandleLongTap");
// Destroy pending MAX_TAP timeout task
mcc->DestroyOldestTask();
// Clear the waiting-for-content timeout task, then send the signal that
// content has handled this long tap. This takes the place of the
// "contextmenu" event.
mcc->ClearDelayedTask();
apzc->ContentReceivedTouch(true);
time += 1000;
MultiTouchInput mti =
MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0);
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0));
status = apzc->ReceiveInputEvent(mti);
EXPECT_EQ(nsEventStatus_eIgnore, status);
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
status = ApzcUp(apzc, touchX, touchEndY, time);
EXPECT_EQ(nsEventStatus_eIgnore, status);
// Flush the event queue. Once the "contextmenu" event is handled, any touch
// events that come from the same series of start->n*move->end events should
// be discarded, even if only the "contextmenu" event is preventDefaulted.
apzc->ContentReceivedTouch(false);
ScreenPoint pointOut;
ViewTransform viewTransformOut;
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
EXPECT_EQ(ScreenPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
apzc->AssertStateIsReset();
apzc->Destroy();
}
TEST_F(AsyncPanZoomControllerTester, LongPress) {
TEST_F(APZCLongPressTester, LongPress) {
DoLongPressTest(mozilla::layers::AllowedTouchBehavior::NONE);
}
TEST_F(AsyncPanZoomControllerTester, LongPressWithTouchAction) {
TEST_F(APZCLongPressTester, LongPressWithTouchAction) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoLongPressTest(mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN
| mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
}
TEST_F(AsyncPanZoomControllerTester, LongPressPreventDefault) {
TEST_F(APZCLongPressTester, LongPressPreventDefault) {
DoLongPressPreventDefaultTest(mozilla::layers::AllowedTouchBehavior::NONE);
}
TEST_F(AsyncPanZoomControllerTester, LongPressPreventDefaultWithTouchAction) {
TEST_F(APZCLongPressTester, LongPressPreventDefaultWithTouchAction) {
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
DoLongPressPreventDefaultTest(mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN