Bug 1257288 - Have APZ hit testing respect scroll clips. r=kats draft
authorBotond Ballo <botond@mozilla.com>
Wed, 20 Apr 2016 18:38:25 -0400
changeset 354445 f435fa574a52bdf90690c1ede739f248d2f0d99f
parent 354444 8b5a5fca7f26c78b53280647a88de285a2208fd8
child 354485 40b9413982c6b6f2c9068df8d55256c898136540
child 355442 1a3779ab7154282388c2e57251886863e818b168
push id16081
push userbballo@mozilla.com
push dateWed, 20 Apr 2016 22:37:55 +0000
reviewerskats
bugs1257288
milestone48.0a1
Bug 1257288 - Have APZ hit testing respect scroll clips. r=kats MozReview-Commit-ID: AZU5TEMvySG
gfx/layers/LayerMetricsWrapper.h
gfx/layers/apz/test/gtest/TestHitTesting.cpp
--- a/gfx/layers/LayerMetricsWrapper.h
+++ b/gfx/layers/LayerMetricsWrapper.h
@@ -361,27 +361,32 @@ public:
     if (AtBottomLayer()) {
       return mLayer->GetVisibleRegion();
     }
     LayerIntRegion region = mLayer->GetVisibleRegion();
     region.Transform(mLayer->GetTransform());
     return region;
   }
 
-  const Maybe<ParentLayerIntRect>& GetClipRect() const
+  Maybe<ParentLayerIntRect> GetClipRect() const
   {
     MOZ_ASSERT(IsValid());
 
-    static const Maybe<ParentLayerIntRect> sNoClipRect = Nothing();
+    Maybe<ParentLayerIntRect> result;
 
+    // The layer can have a clip rect, which is considered to apply
+    // only to the bottommost LayerMetrics.
     if (AtBottomLayer()) {
-      return mLayer->GetClipRect();
+      result = mLayer->GetClipRect();
     }
 
-    return sNoClipRect;
+    // The scroll metadata can have a clip rect as well.
+    result = IntersectMaybeRects(result, Metadata().GetClipRect());
+
+    return result;
   }
 
   float GetPresShellResolution() const
   {
     MOZ_ASSERT(IsValid());
 
     if (AtTopLayer() && mLayer->AsContainerLayer()) {
       return mLayer->AsContainerLayer()->GetPresShellResolution();
--- a/gfx/layers/apz/test/gtest/TestHitTesting.cpp
+++ b/gfx/layers/apz/test/gtest/TestHitTesting.cpp
@@ -530,8 +530,49 @@ TEST_F(APZHitTestingTester, Bug1148350) 
   layers[0]->SetBaseTransform(Matrix4x4::Translation(0, 50, 0));
   manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
 
   TouchUp(manager, ScreenIntPoint(100, 100), mcc->Time());
   mcc->RunThroughDelayedTasks();
   check.Call("Tapped with interleaved transform");
 }
 
+TEST_F(APZHitTestingTester, HitTestingRespectsScrollClip_Bug1257288) {
+  // Create the layer tree.
+  const char* layerTreeSyntax = "c(tt)";
+  // LayerID                     0 12
+  nsIntRegion layerVisibleRegion[] = {
+    nsIntRegion(IntRect(0,0,200,200)),
+    nsIntRegion(IntRect(0,0,200,200)),
+    nsIntRegion(IntRect(0,0,200,100))
+  };
+  root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers);
+
+  // Add root scroll metadata to the first painted layer.
+  SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID, CSSRect(0,0,200,200));
+
+  // Add root and subframe scroll metadata to the second painted layer.
+  // Give the subframe metadata a scroll clip corresponding to the subframe's
+  // composition bounds.
+  // Importantly, give the layer a layer clip which leaks outside of the
+  // subframe's composition bounds.
+  ScrollMetadata rootMetadata = BuildScrollMetadata(
+      FrameMetrics::START_SCROLL_ID, CSSRect(0,0,200,200),
+      ParentLayerRect(0,0,200,200));
+  ScrollMetadata subframeMetadata = BuildScrollMetadata(
+      FrameMetrics::START_SCROLL_ID + 1, CSSRect(0,0,200,200),
+      ParentLayerRect(0,0,200,100));
+  subframeMetadata.SetClipRect(Some(ParentLayerIntRect(0,0,200,100)));
+  layers[2]->SetScrollMetadata({subframeMetadata, rootMetadata});
+  layers[2]->SetClipRect(Some(ParentLayerIntRect(0,0,200,200)));
+  SetEventRegionsBasedOnBottommostMetrics(layers[2]);
+
+  // Build the hit testing tree.
+  ScopedLayerTreeRegistration registration(manager, 0, root, mcc);
+  manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
+
+  // Pan on a region that's inside layers[2]'s layer clip, but outside
+  // its subframe metadata's scroll clip.
+  Pan(manager, mcc, 120, 110);
+
+  // Test that the subframe hasn't scrolled.
+  EXPECT_EQ(CSSPoint(0,0), ApzcOf(layers[2], 0)->GetFrameMetrics().GetScrollOffset());
+}
\ No newline at end of file