Bug 898443 - Completely extract the transformation calculation from GetTargetAPZC. r=BenWa

This commit is contained in:
Kartikaya Gupta 2013-08-21 12:03:03 -04:00
parent cadc35ef37
commit 0cfcca1de1
3 changed files with 122 additions and 126 deletions

View File

@ -217,21 +217,18 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
case MULTITOUCH_INPUT: {
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint),
transformToApzc, transformToScreen);
} else {
if (mApzcForInputBlock) {
APZC_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
// If we have an mApzcForInputBlock and it's the end of the touch sequence
// then null it out so we don't keep a dangling reference and leak things.
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL ||
(multiTouchInput.mType == MultiTouchInput::MULTITOUCH_END && multiTouchInput.mTouches.Length() == 1)) {
mApzcForInputBlock = nullptr;
}
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint));
} else if (mApzcForInputBlock) {
APZC_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
// If we have an mApzcForInputBlock and it's the end of the touch sequence
// then null it out so we don't keep a dangling reference and leak things.
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL ||
(multiTouchInput.mType == MultiTouchInput::MULTITOUCH_END && multiTouchInput.mTouches.Length() == 1)) {
mApzcForInputBlock = nullptr;
}
}
if (mApzcForInputBlock) {
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
MultiTouchInput inputForApzc(multiTouchInput);
for (int i = inputForApzc.mTouches.Length() - 1; i >= 0; i--) {
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
@ -241,8 +238,9 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
break;
} case PINCHGESTURE_INPUT: {
const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint, transformToApzc, transformToScreen);
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint);
if (apzc) {
GetInputTransforms(apzc, transformToApzc, transformToScreen);
PinchGestureInput inputForApzc(pinchInput);
ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc);
apzc->ReceiveInputEvent(inputForApzc);
@ -250,8 +248,9 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
break;
} case TAPGESTURE_INPUT: {
const TapGestureInput& tapInput = aEvent.AsTapGestureInput();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint), transformToApzc, transformToScreen);
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint));
if (apzc) {
GetInputTransforms(apzc, transformToApzc, transformToScreen);
TapGestureInput inputForApzc(tapInput);
ApplyTransform(&(inputForApzc.mPoint), transformToApzc);
apzc->ReceiveInputEvent(inputForApzc);
@ -278,21 +277,18 @@ APZCTreeManager::ReceiveInputEvent(const nsInputEvent& aEvent,
}
if (touchEvent.message == NS_TOUCH_START) {
nsIntPoint point = touchEvent.touches[0]->mRefPoint;
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(point.x, point.y),
transformToApzc, transformToScreen);
} else {
if (mApzcForInputBlock) {
APZC_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
// If we have an mApzcForInputBlock and it's the end of the touch sequence
// then null it out so we don't keep a dangling reference and leak things.
if (touchEvent.message == NS_TOUCH_CANCEL ||
(touchEvent.message == NS_TOUCH_END && touchEvent.touches.Length() == 1)) {
mApzcForInputBlock = nullptr;
}
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(point.x, point.y));
} else if (mApzcForInputBlock) {
APZC_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
// If we have an mApzcForInputBlock and it's the end of the touch sequence
// then null it out so we don't keep a dangling reference and leak things.
if (touchEvent.message == NS_TOUCH_CANCEL ||
(touchEvent.message == NS_TOUCH_END && touchEvent.touches.Length() == 1)) {
mApzcForInputBlock = nullptr;
}
}
if (mApzcForInputBlock) {
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
MultiTouchInput inputForApzc(touchEvent);
for (int i = inputForApzc.mTouches.Length() - 1; i >= 0; i--) {
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
@ -309,10 +305,9 @@ APZCTreeManager::ReceiveInputEvent(const nsInputEvent& aEvent,
break;
} case NS_MOUSE_EVENT: {
const nsMouseEvent& mouseEvent = static_cast<const nsMouseEvent&>(aEvent);
nsRefPtr<AsyncPanZoomController> apzc =
GetTargetAPZC(ScreenPoint(mouseEvent.refPoint.x, mouseEvent.refPoint.y),
transformToApzc, transformToScreen);
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(mouseEvent.refPoint.x, mouseEvent.refPoint.y));
if (apzc) {
GetInputTransforms(apzc, transformToApzc, transformToScreen);
MultiTouchInput inputForApzc(mouseEvent);
ApplyTransform(&(inputForApzc.mTouches[0].mScreenPoint), transformToApzc);
@ -440,11 +435,78 @@ APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
return target.forget();
}
/* This function returns the AsyncPanZoomController instance that hit testing determines
is under the given ScreenPoint.
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint)
{
MonitorAutoLock lock(mTreeLock);
nsRefPtr<AsyncPanZoomController> target;
// The root may have siblings, so check those too
gfxPoint point(aPoint.x, aPoint.y);
for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
target = GetAPZCAtPoint(apzc, point);
if (target) {
break;
}
}
return target.forget();
}
In addition, the aTransformToApzcOut and aTransformToScreenOut out-parameters are filled
with some useful transformations that input events may need applied. This is best
AsyncPanZoomController*
APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid) {
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = FindTargetAPZC(child, aGuid);
if (match) {
return match;
}
}
if (aApzc->Matches(aGuid)) {
return aApzc;
}
return nullptr;
}
AsyncPanZoomController*
APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& aHitTestPoint)
{
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment on GetInputTransforms. This function will recurse with aApzc at L and P, and the
// comments explain what values are stored in the variables at these two levels. All the comments
// use standard matrix notation where the leftmost matrix in a multiplication is applied first.
// ancestorUntransform is OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L,
// and RC.Inverse() * QC.Inverse() at recursion level for P.
gfx3DMatrix ancestorUntransform = aApzc->GetAncestorTransform().Inverse();
// asyncUntransform is LA.Inverse() at recursion level for L,
// and PA.Inverse() at recursion level for P.
gfx3DMatrix asyncUntransform = gfx3DMatrix(aApzc->GetCurrentAsyncTransform()).Inverse();
// untransformSinceLastApzc is OC.Inverse() * NC.Inverse() * MC.Inverse() * LA.Inverse() * LC.Inverse() at L,
// and RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() at P.
gfx3DMatrix untransformSinceLastApzc = ancestorUntransform * asyncUntransform * aApzc->GetCSSTransform().Inverse();
// untransformed is the user input in L's layer space at L,
// and in P's layer space at P.
gfxPoint untransformed = untransformSinceLastApzc.ProjectPoint(aHitTestPoint);
APZC_LOG("Untransformed %f %f to %f %f for APZC %p\n", aHitTestPoint.x, aHitTestPoint.y, untransformed.x, untransformed.y, aApzc);
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = GetAPZCAtPoint(child, untransformed);
if (match) {
return match;
}
}
if (aApzc->VisibleRegionContains(LayerPoint(untransformed.x, untransformed.y))) {
APZC_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n", untransformed.x, untransformed.y, aApzc);
return aApzc;
}
return nullptr;
}
/* This function sets the aTransformToApzcOut and aTransformToScreenOut out-parameters
to some useful transformations that input events may need applied. This is best
illustrated with an example. Consider a chain of layers, L, M, N, O, P, Q, R. Layer L
is the layer that corresponds to the returned APZC instance, and layer R is the root
of the layer tree. Layer M is the parent of L, N is the parent of M, and so on.
@ -503,89 +565,13 @@ APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
layer L would store LC and (MC * NC * OC), and the layer P would store PC and (QC * RC).
The APZCs also obviously have LA and PA, so all of the above transformation combinations
required can be generated.
Note that this function may return null, in which case the matrix out-parameters are
left unmodified.
*/
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
gfx3DMatrix& aTransformToApzcOut,
gfx3DMatrix& aTransformToScreenOut)
{
MonitorAutoLock lock(mTreeLock);
nsRefPtr<AsyncPanZoomController> target;
// The root may have siblings, so check those too
gfxPoint point(aPoint.x, aPoint.y);
for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
target = GetAPZCAtPoint(apzc, point);
if (target) {
GetInputTransforms(target, aTransformToApzcOut, aTransformToScreenOut);
break;
}
}
return target.forget();
}
AsyncPanZoomController*
APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid) {
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = FindTargetAPZC(child, aGuid);
if (match) {
return match;
}
}
if (aApzc->Matches(aGuid)) {
return aApzc;
}
return nullptr;
}
AsyncPanZoomController*
APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& aHitTestPoint)
{
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment on GetTargetAPZC. This function will recurse with aApzc at L and P, and the
// comments explain what values are stored in the variables at these two levels. All the comments
// use standard matrix notation where the leftmost matrix in a multiplication is applied first.
// ancestorUntransform is OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L,
// and RC.Inverse() * QC.Inverse() at recursion level for P.
gfx3DMatrix ancestorUntransform = aApzc->GetAncestorTransform().Inverse();
// asyncUntransform is LA.Inverse() at recursion level for L,
// and PA.Inverse() at recursion level for P.
gfx3DMatrix asyncUntransform = gfx3DMatrix(aApzc->GetCurrentAsyncTransform()).Inverse();
// untransformSinceLastApzc is OC.Inverse() * NC.Inverse() * MC.Inverse() * LA.Inverse() * LC.Inverse() at L,
// and RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() at P.
gfx3DMatrix untransformSinceLastApzc = ancestorUntransform * asyncUntransform * aApzc->GetCSSTransform().Inverse();
// untransformed is the user input in L's layer space at L,
// and in P's layer space at P.
gfxPoint untransformed = untransformSinceLastApzc.ProjectPoint(aHitTestPoint);
APZC_LOG("Untransformed %f %f to %f %f for APZC %p\n", aHitTestPoint.x, aHitTestPoint.y, untransformed.x, untransformed.y, aApzc);
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
AsyncPanZoomController* match = GetAPZCAtPoint(child, untransformed);
if (match) {
return match;
}
}
if (aApzc->VisibleRegionContains(LayerPoint(untransformed.x, untransformed.y))) {
APZC_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n", untransformed.x, untransformed.y, aApzc);
return aApzc;
}
return nullptr;
}
void
APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
gfx3DMatrix& aTransformToScreenOut)
{
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment on GetTargetAPZC. This function is called with aApzc at L, and the loop
// explained in the comment above. This function is called with aApzc at L, and the loop
// below performs one iteration, where parent is at P. The comments explain what values are stored
// in the variables at these two levels. All the comments use standard matrix notation where the
// leftmost matrix in a multiplication is applied first.

View File

@ -250,14 +250,13 @@ public:
used by other production code.
*/
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint, gfx3DMatrix& aTransformToApzcOut,
gfx3DMatrix& aTransformToScreenOut);
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint);
void GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
gfx3DMatrix& aTransformToScreenOut);
private:
/* Helpers */
AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid);
AsyncPanZoomController* GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& aHitTestPoint);
void GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
gfx3DMatrix& aTransformToScreenOut);
/**
* Recursive helper function to build the APZC tree. The tree of APZC instances has

View File

@ -381,6 +381,17 @@ NudgeToIntegers(const gfxPoint& aPoint)
return gfxPoint(x, y);
}
static already_AddRefed<AsyncPanZoomController>
GetTargetAPZC(APZCTreeManager* manager, const ScreenPoint& aPoint,
gfx3DMatrix& aTransformToApzcOut, gfx3DMatrix& aTransformToScreenOut)
{
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(aPoint);
if (hit) {
manager->GetInputTransforms(hit.get(), aTransformToApzcOut, aTransformToScreenOut);
}
return hit.forget();
}
TEST(APZCTreeManager, GetAPZCAtPoint) {
nsTArray<nsRefPtr<Layer> > layers;
nsRefPtr<LayerManager> lm;
@ -396,7 +407,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
gfx3DMatrix transformToScreen;
// No APZC attached so hit testing will return no APZC at (20,20)
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(ScreenPoint(20, 20), transformToApzc, transformToScreen);
nsRefPtr<AsyncPanZoomController> hit = GetTargetAPZC(manager, ScreenPoint(20, 20), transformToApzc, transformToScreen);
AsyncPanZoomController* nullAPZC = nullptr;
EXPECT_EQ(nullAPZC, hit.get());
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
@ -405,7 +416,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
// Now we have a root APZC that will match the page
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc);
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
hit = manager->GetTargetAPZC(ScreenPoint(15, 15), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerIntPoint(15, 15)
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
@ -415,36 +426,36 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc);
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController());
hit = manager->GetTargetAPZC(ScreenPoint(15, 15), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerIntPoint(15, 15)
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
EXPECT_EQ(gfxPoint(15, 15), transformToScreen.Transform(gfxPoint(15, 15)));
// Now test hit testing when we have two scrollable layers
hit = manager->GetTargetAPZC(ScreenPoint(15, 15), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1, mcc);
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
hit = manager->GetTargetAPZC(ScreenPoint(15, 15), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerIntPoint(15, 15)
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
EXPECT_EQ(gfxPoint(15, 15), transformToScreen.Transform(gfxPoint(15, 15)));
// Hit test ouside the reach of layer[3,4] but inside root
hit = manager->GetTargetAPZC(ScreenPoint(90, 90), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(90, 90), transformToApzc, transformToScreen);
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerIntPoint(90, 90)
EXPECT_EQ(gfxPoint(90, 90), transformToApzc.Transform(gfxPoint(90, 90)));
EXPECT_EQ(gfxPoint(90, 90), transformToScreen.Transform(gfxPoint(90, 90)));
// Hit test ouside the reach of any layer
hit = manager->GetTargetAPZC(ScreenPoint(1000, 10), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(1000, 10), transformToApzc, transformToScreen);
EXPECT_EQ(nullAPZC, hit.get());
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
hit = manager->GetTargetAPZC(ScreenPoint(-1000, 10), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(-1000, 10), transformToApzc, transformToScreen);
EXPECT_EQ(nullAPZC, hit.get());
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
@ -454,14 +465,14 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
transform.ScalePost(0.1, 0.1, 1);
root->SetBaseTransform(transform);
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
hit = manager->GetTargetAPZC(ScreenPoint(50, 50), transformToApzc, transformToScreen); // This point is now outside the root layer
hit = GetTargetAPZC(manager, ScreenPoint(50, 50), transformToApzc, transformToScreen); // This point is now outside the root layer
EXPECT_EQ(nullAPZC, hit.get());
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
// This hit test will hit both layers[3] and layers[4]; layers[4] is later in the tree so
// it is a better match
hit = manager->GetTargetAPZC(ScreenPoint(2, 2), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(2, 2), transformToApzc, transformToScreen);
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerPoint(20, 20)
EXPECT_EQ(gfxPoint(20, 20), NudgeToIntegers(transformToApzc.Transform(gfxPoint(2, 2))));
@ -472,7 +483,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
// layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2)
// Does not contain (2, 2)
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
hit = manager->GetTargetAPZC(ScreenPoint(2, 2), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(2, 2), transformToApzc, transformToScreen);
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerPoint(20, 20)
EXPECT_EQ(gfxPoint(20, 20), NudgeToIntegers(transformToApzc.Transform(gfxPoint(2, 2))));
@ -495,7 +506,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
// layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers
hit = manager->GetTargetAPZC(ScreenPoint(1, 45), transformToApzc, transformToScreen);
hit = GetTargetAPZC(manager, ScreenPoint(1, 45), transformToApzc, transformToScreen);
EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
// expect hit point at LayerPoint(20, 440), which is CSSPoint(20, 29)
EXPECT_EQ(gfxPoint(20, 440), NudgeToIntegers(transformToApzc.Transform(gfxPoint(1, 45))));