Bug 1119497 - Don't continue searching if we hit a layer that has no containing APZC. r=botond
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1368,17 +1368,17 @@ APZCTreeManager::GetAPZCAtPoint(HitTesti
result = GetAPZCAtPoint(node->GetLastChild(), childPoint, aOutHitResult);
if (*aOutHitResult == OverscrolledApzc) {
// We matched an overscrolled APZC, abort.
return nullptr;
}
}
// If we didn't match anything in the subtree, check |node|.
- if (!result) {
+ if (*aOutHitResult == NoApzcHit) {
APZCTM_LOG("Testing ParentLayer point %s (Layer %s) against node %p\n",
Stringify(aHitTestPoint).c_str(),
hitTestPointForChildLayers ? Stringify(hitTestPointForChildLayers.ref()).c_str() : "nil",
node);
HitTestResult hitResult = node->HitTest(aHitTestPoint);
if (hitResult != HitTestResult::NoApzcHit) {
result = node->GetNearestContainingApzc();
APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n",
@@ -1387,24 +1387,24 @@ APZCTreeManager::GetAPZCAtPoint(HitTesti
// If event regions are disabled, *aOutHitResult will be ApzcHitRegion
*aOutHitResult = hitResult;
}
}
// If we are overscrolled, and the point matches us or one of our children,
// the result is inside an overscrolled APZC, inform our caller of this
// (callers typically ignore events targeted at overscrolled APZCs).
- if (result && apzc && apzc->IsOverscrolled()) {
+ if (*aOutHitResult != NoApzcHit && apzc && apzc->IsOverscrolled()) {
APZCTM_LOG("Result is inside overscrolled APZC %p\n", apzc);
*aOutHitResult = OverscrolledApzc;
return nullptr;
}
- if (result) {
- if (!gfxPrefs::LayoutEventRegionsEnabled()) {
+ if (*aOutHitResult != NoApzcHit) {
+ if (result && !gfxPrefs::LayoutEventRegionsEnabled()) {
// When event-regions are disabled, we treat scrollinfo layers as
// regular scrollable layers. Unfortunately, their "hit region" (which
// we create from the composition bounds) is their full area, and they
// sit on top of their non-scrollinfo siblings. This means they will get
// a HitTestingTreeNode with a hit region that will aggressively match
// any input events that might be directed to sub-APZCs of their non-
// scrollinfo siblings. Therefore, we need to keep looping through to
// see if there are any other non-scrollinfo siblings that have children
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -2546,16 +2546,35 @@ protected:
layers[1]->SetEventRegions(regions);
regions.mHitRegion = nsIntRegion(nsIntRect(0, 100, 200, 100));
layers[2]->SetEventRegions(regions);
registration = MakeUnique<ScopedLayerTreeRegistration>(0, root, mcc);
manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
rootApzc = ApzcOf(root);
}
+
+ void CreateBug1119497LayerTree() {
+ const char* layerTreeSyntax = "c(tt)";
+ // LayerID 0 12
+ // 0 is the root and doesn't have an APZC
+ // 1 is behind 2 and does have an APZC
+ // 2 entirely covers 1 and should take all the input events
+ nsIntRegion layerVisibleRegions[] = {
+ nsIntRegion(nsIntRect(0, 0, 100, 100)),
+ nsIntRegion(nsIntRect(0, 0, 100, 100)),
+ nsIntRegion(nsIntRect(0, 0, 100, 100)),
+ };
+ root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers);
+
+ SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1);
+
+ registration = MakeUnique<ScopedLayerTreeRegistration>(0, root, mcc);
+ manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
+ }
};
TEST_F(APZEventRegionsTester, HitRegionImmediateResponse) {
SCOPED_GFX_PREF(LayoutEventRegionsEnabled, bool, true);
CreateEventRegionsLayerTree1();
TestAsyncPanZoomController* root = ApzcOf(layers[0]);
@@ -2638,16 +2657,29 @@ TEST_F(APZEventRegionsTester, Obscuratio
ApzcPanNoFling(parent, time, 75, 25);
HitTestResult result;
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(ScreenPoint(50, 75), &result);
EXPECT_EQ(child, hit.get());
EXPECT_EQ(HitTestResult::ApzcHitRegion, result);
}
+TEST_F(APZEventRegionsTester, Bug1119497) {
+ SCOPED_GFX_PREF(LayoutEventRegionsEnabled, bool, true);
+
+ CreateBug1119497LayerTree();
+
+ HitTestResult result;
+ nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(ScreenPoint(50, 50), &result);
+ // We should hit layers[2], so |result| will be ApzcHitRegion but there's no
+ // actual APZC in that parent chain, so |hit| should be nullptr.
+ EXPECT_EQ(nullptr, hit.get());
+ EXPECT_EQ(HitTestResult::ApzcHitRegion, result);
+}
+
class TaskRunMetrics {
public:
TaskRunMetrics()
: mRunCount(0)
, mCancelCount(0)
{}
void IncrementRunCount() {