diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 4e977ee46087..c239913c0980 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -390,17 +390,13 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, // or not, depending on whether it went through the newApzc branch above. MOZ_ASSERT(node->IsPrimaryHolder() && node->Apzc()->Matches(guid)); - nsIntRegion unobscured; if (!gfxPrefs::LayoutEventRegionsEnabled()) { - unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); + nsIntRegion unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); + node->SetHitTestData(EventRegions(), Matrix4x4(), unobscured); + APZCTM_LOG("Setting region %s as visible region for APZC %p (node %p)\n", + Stringify(unobscured).c_str(), apzc, node.get()); } - // This initializes, among other things, the APZC's hit-region. - // If event-regions are disabled, this will initialize it to the empty - // region, but UpdatePanZoomControllerTree will add the hit-region from - // the event regions later. - apzc->SetLayerHitTestData(EventRegions(unobscured), aAncestorTransform); - APZCTM_LOG("Setting region %s as visible region for APZC %p\n", - Stringify(unobscured).c_str(), apzc); + apzc->SetAncestorTransform(aAncestorTransform); PrintAPZCInfo(aLayer, apzc); @@ -442,18 +438,6 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, // We already built an APZC earlier in this tree walk, but we have another layer // now that will also be using that APZC. The hit-test region on the APZC needs // to be updated to deal with the new layer's hit region. - // FIXME: Combining this hit test region to the existing hit test region has a bit - // of a problem, because it assumes the z-index of this new region is the same as - // the z-index of the old region (from the previous layer with the same scrollid) - // when in fact that may not be the case. - // Consider the case where we have three layers: A, B, and C. A is at the top in - // z-order and C is at the bottom. A and C share a scrollid and scroll together; but - // B has a different scrollid and scrolls independently. Depending on how B moves - // and the async transform on it, a larger/smaller area of C may be unobscured. - // However, when we combine the hit regions of A and C here we are ignoring the - // async transform and so we basically assume the same amount of C is always visible - // on top of B. Fixing this doesn't appear to be very easy so I'm leaving it for - // now in the hopes that we won't run into this problem a lot. // TODO(optimization): we could recycle one of the non-primary-holder nodes // from mNodesToDestroy instead of creating a new one since those are going @@ -469,8 +453,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, if (!gfxPrefs::LayoutEventRegionsEnabled()) { nsIntRegion unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); - apzc->AddHitTestRegions(EventRegions(unobscured)); - APZCTM_LOG("Adding region %s to visible region of APZC %p\n", Stringify(unobscured).c_str(), apzc); + node->SetHitTestData(EventRegions(), Matrix4x4(), unobscured); + APZCTM_LOG("Adding region %s to visible region of APZC %p (via node %p)\n", + Stringify(unobscured).c_str(), apzc, node.get()); } } @@ -513,11 +498,13 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId); - nsIntRegion obscured; + nsIntRegion obscuredByUncles; if (aLayersId == childLayersId) { - // If the child layer is in the same process, transform - // aObscured from aLayer's ParentLayerPixels to aLayer's LayerPixels, - // which are the children layers' ParentLayerPixels. + // If the child layer is in the same process, keep a copy of |aObscured|. + // This value is in ParentLayerPixels and represents the area that is + // obscured by |aLayer|'s younger uncles (i.e. any next-siblings of any + // ancestor of |aLayer|) in the same process. We will need this value later. + // If we cross a process boundary, we assume that we can start with // an empty obscured region because nothing in the parent process will // obscure the child process. This may be false. However, not doing this @@ -526,8 +513,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, // all child processes, even though visually they do not. We'd probably // have to check for mask layers and so on in order to properly handle // that case. - obscured = aObscured; - obscured.Transform(To3DMatrix(transform).Inverse()); + obscuredByUncles = aObscured; } // If there's no APZC at this level, any APZCs for our child layers will @@ -553,6 +539,9 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, aState.mEventRegions.AppendElement(EventRegions()); } + // Convert the obscured region into this layer's LayerPixels. + nsIntRegion obscured = obscuredByUncles; + obscured.Transform(To3DMatrix(transform).Inverse()); for (LayerMetricsWrapper child = aLayer.GetLastChild(); child; child = child.GetPrevSibling()) { gfx::TreeAutoIndent indent(mApzcTreeLog); next = UpdatePanZoomControllerTree(aState, child, childLayersId, @@ -585,39 +574,42 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, // way we do hit-testing (where the deepest matching APZC is used) it should // still be ok if we did propagate those regions upwards and included them // in all the ancestor APZCs. - // - // Also at this point in the code the |obscured| region includes the hit - // regions of children of |aLayer| as well as the hit regions of |aLayer|'s - // younger uncles (i.e. the next-sibling chains of |aLayer|'s ancestors). - // When we compute the unobscured regions below, we subtract off the - // |obscured| region, but it would also be ok to do this before the above - // loop. At that point |obscured| would only have the uncles' hit regions - // and not the children. The reason this is ok is again because of the way - // we do hit-testing (where the deepest APZC is used) it doesn't matter if - // we count the children as obscuring the parent or not. - - EventRegions unobscured; - unobscured.Sub(aLayer.GetEventRegions(), obscured); - APZCTM_LOG("Picking up unobscured hit region %s from layer %p\n", Stringify(unobscured).c_str(), aLayer.GetLayer()); // Take the hit region of the |aLayer|'s subtree (which has already been // transformed into the coordinate space of |aLayer|) and... EventRegions subtreeEventRegions = aState.mEventRegions.LastElement(); aState.mEventRegions.RemoveElementAt(aState.mEventRegions.Length() - 1); - // ... combine it with the hit region for this layer, and then ... - subtreeEventRegions.OrWith(unobscured); - // ... transform it up to the parent layer's coordinate space. - subtreeEventRegions.Transform(To3DMatrix(aLayer.GetTransform())); - if (aLayer.GetClipRect()) { - subtreeEventRegions.AndWith(*aLayer.GetClipRect()); - } - - APZCTM_LOG("After processing layer %p the subtree hit region is %s\n", aLayer.GetLayer(), Stringify(subtreeEventRegions).c_str()); + // ... combine it with the event region for this layer. + subtreeEventRegions.OrWith(aLayer.GetEventRegions()); // If we have an APZC at this level, intersect the subtree hit region with // the touch-sensitive region and add it to the APZ's hit test regions. - if (apzc) { - APZCTM_LOG("Adding region %s to visible region of APZC %p\n", Stringify(subtreeEventRegions).c_str(), apzc); + if (node) { + // At this point in the code we have two different "obscured" regions. + // There is |obscuredByUncles| which represents the hit regions of + // |aLayer|'s younger uncles (i.e. the next-sibling chains of |aLayer|'s + // ancestors). This obscured region does not move when aLayer is scrolled, + // and so is in the same ParentLayerPixel coordinate space as |aLayer|'s + // clip rect. + // We also have |obscured| which includes the hit regions of |aLayer|'s + // descendants. However we don't want to use this because those + // descendants (and their hit regions) move as |aLayer| scrolls. + // From |aLayer|'s point of view |obscured| is in a nonsensical coordinate + // space because it combines the uncle-obscured region and child-obscured + // regions. + // We combine the |obscuredByUncles| region with the clip rect of |aLayer| + // below, to "apply" the obscuration by the uncles. + nsIntRegion clipRegion; + if (aLayer.GetClipRect()) { + clipRegion = nsIntRegion(*aLayer.GetClipRect()); + } else { + // if there is no clip on this layer (which should only happen for the + // root scrollable layer in a process) fall back to using the comp + // bounds which should be equivalent. + clipRegion = nsIntRegion(ParentLayerIntRect::ToUntyped(RoundedToInt(aLayer.Metrics().mCompositionBounds))); + } + clipRegion.SubOut(obscuredByUncles); + const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); MOZ_ASSERT(state); MOZ_ASSERT(state->mController.get()); @@ -632,16 +624,24 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, LayoutDeviceToParentLayerScale parentCumulativeResolution = aLayer.Metrics().GetCumulativeResolution() / ParentLayerToLayerScale(aLayer.Metrics().mPresShellResolution); - subtreeEventRegions.AndWith(ParentLayerIntRect::ToUntyped( + clipRegion.AndWith(ParentLayerIntRect::ToUntyped( RoundedIn(touchSensitiveRegion * aLayer.Metrics().GetDevPixelsPerCSSPixel() * parentCumulativeResolution))); } - apzc->AddHitTestRegions(subtreeEventRegions); + + node->SetHitTestData(subtreeEventRegions, aLayer.GetTransform(), clipRegion); + APZCTM_LOG("After processing layer %p the event regions for %p is %s\n", + aLayer.GetLayer(), node, Stringify(subtreeEventRegions).c_str()); } else { // If we don't have an APZC at this level, carry the subtree hit region // up to the parent. MOZ_ASSERT(aState.mEventRegions.Length() > 0); + // transform it up to the parent layer's coordinate space. + subtreeEventRegions.Transform(To3DMatrix(aLayer.GetTransform())); + if (aLayer.GetClipRect()) { + subtreeEventRegions.AndWith(*aLayer.GetClipRect()); + } aState.mEventRegions.LastElement().OrWith(subtreeEventRegions); } } @@ -1333,13 +1333,19 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHit HitTestResult hitResult = NoApzcHit; for (HitTestingTreeNode* node = mRootNode; node; node = node->GetPrevSibling()) { target = GetAPZCAtPoint(node, aPoint.ToUnknownPoint(), &hitResult); - if (target == node->Apzc() && node->GetPrevSibling() && target == node->GetPrevSibling()->Apzc()) { - // We might be able to do better if we keep looping, so let's do that. - // This happens because the hit-test data stored in "target" actually - // includes the areas of all the nodes that have "target" as their APZC. - // One of these nodes (that we haven't yet encountered) may have a child - // that is on top of this area, so we need to check for that. A future - // patch will deal with this more correctly. + if (!gfxPrefs::LayoutEventRegionsEnabled() && target == node->Apzc() + && node->GetPrevSibling() && target == node->GetPrevSibling()->Apzc()) { + // 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. This means that we need to keep looping through + // to see if there are any other non-scrollinfo siblings that have + // children that match this event. If so, they should take priority. + // Once we turn on event-regions and ignore scrollinfo layers, this + // will become unnecessary. continue; } // If we hit an overscrolled APZC, 'target' will be nullptr but it's still @@ -1485,7 +1491,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, // since the composition bounds (used to initialize the visible rect against // which we hit test are in those coordinates). Point4D hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint); - APZCTM_LOG("Untransformed %f %f to transient coordinates %f %f for hit-testing APZC %p\n", + APZCTM_LOG("Untransformed %f %f to parentlayer coordinates %f %f for hit-testing APZC %p\n", aHitTestPoint.x, aHitTestPoint.y, hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, apzc); @@ -1505,13 +1511,19 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, if (hitTestPointForChildLayers.HasPositiveWCoord()) { for (HitTestingTreeNode* child = aNode->GetLastChild(); child; child = child->GetPrevSibling()) { AsyncPanZoomController* match = GetAPZCAtPoint(child, hitTestPointForChildLayers.As2DPoint(), aOutHitResult); - if (match == child->Apzc() && child->GetPrevSibling() && match == child->GetPrevSibling()->Apzc()) { - // We might be able to do better if we keep looping, so let's do that. - // This happens because the hit-test data stored in "target" actually - // includes the areas of all the nodes that have "target" as their APZC. - // One of these nodes (that we haven't yet encountered) may have a child - // that is on top of this area, so we need to check for that. A future - // patch will deal with this more correctly. + if (!gfxPrefs::LayoutEventRegionsEnabled() && match == aNode->Apzc() + && aNode->GetPrevSibling() && match == aNode->GetPrevSibling()->Apzc()) { + // 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. This means that we need to keep looping through + // to see if there are any other non-scrollinfo siblings that have + // children that match this event. If so, they should take priority. + // Once we turn on event-regions and ignore scrollinfo layers, this + // will become unnecessary. continue; } if (*aOutHitResult == OverscrolledApzc) { @@ -1526,12 +1538,14 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, } if (!result && hitTestPointForThisLayer.HasPositiveWCoord()) { ParentLayerPoint point = ParentLayerPoint::FromUnknownPoint(hitTestPointForThisLayer.As2DPoint()); - if (apzc->HitRegionContains(point)) { - APZCTM_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n", - hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, apzc); + HitTestResult hitResult = aNode->HitTest(point); + if (hitResult != HitTestResult::NoApzcHit) { + APZCTM_LOG("Successfully matched untransformed point %s to visible region for APZC %p via node %p\n", + Stringify(hitTestPointForThisLayer.As2DPoint()).c_str(), apzc, aNode); result = apzc; + MOZ_ASSERT(hitResult == ApzcHitRegion || hitResult == ApzcContentRegion); // If event regions are disabled, *aOutHitResult will be ApzcHitRegion - *aOutHitResult = (apzc->DispatchToContentRegionContains(point) ? ApzcContentRegion : ApzcHitRegion); + *aOutHitResult = hitResult; } } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index df4f3a5803f4..b344233f8a49 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -970,39 +970,19 @@ private: * hit-testing to see which APZC instance should handle touch events. */ public: - void SetLayerHitTestData(const EventRegions& aRegions, const Matrix4x4& aTransformToLayer) { - mEventRegions = aRegions; + void SetAncestorTransform(const Matrix4x4& aTransformToLayer) { mAncestorTransform = aTransformToLayer; } - void AddHitTestRegions(const EventRegions& aRegions) { - mEventRegions.OrWith(aRegions); - } - Matrix4x4 GetAncestorTransform() const { return mAncestorTransform; } - bool HitRegionContains(const ParentLayerPoint& aPoint) const { - ParentLayerIntPoint point = RoundedToInt(aPoint); - return mEventRegions.mHitRegion.Contains(point.x, point.y); - } - - bool DispatchToContentRegionContains(const ParentLayerPoint& aPoint) const { - ParentLayerIntPoint point = RoundedToInt(aPoint); - return mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y); - } - bool IsOverscrolled() const { return mX.IsOverscrolled() || mY.IsOverscrolled(); } private: - /* This is the union of the hit regions of the layers that this APZC - * corresponds to, in the local screen pixels of those layers. (This is the - * same coordinate system in which this APZC receives events in - * ReceiveInputEvent()). */ - EventRegions mEventRegions; /* This is the cumulative CSS transform for all the layers from (and including) * the parent APZC down to (but excluding) this one. */ Matrix4x4 mAncestorTransform; diff --git a/gfx/layers/apz/src/HitTestingTreeNode.cpp b/gfx/layers/apz/src/HitTestingTreeNode.cpp index e51af795ecec..75f30717e20c 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.cpp +++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp @@ -6,9 +6,12 @@ #include "HitTestingTreeNode.h" -#include "AsyncPanZoomController.h" -#include "LayersLogging.h" -#include "nsPrintfCString.h" +#include "AsyncPanZoomController.h" // for AsyncPanZoomController +#include "LayersLogging.h" // for Stringify +#include "mozilla/gfx/Point.h" // for Point4D +#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4() +#include "nsPrintfCString.h" // for nsPrintfCString +#include "UnitTransforms.h" // for ViewAs namespace mozilla { namespace layers { @@ -115,14 +118,63 @@ HitTestingTreeNode::IsPrimaryHolder() const return mIsPrimaryApzcHolder; } +void +HitTestingTreeNode::SetHitTestData(const EventRegions& aRegions, + const gfx::Matrix4x4& aTransform, + const nsIntRegion& aClipRegion) +{ + mEventRegions = aRegions; + mTransform = aTransform; + mClipRegion = aClipRegion; +} + +HitTestResult +HitTestingTreeNode::HitTest(const ParentLayerPoint& aPoint) const +{ + // When event regions are disabled, we are actually storing the + // touch-sensitive section of the composition bounds in the clip rect, and we + // don't need to use mTransform or mEventRegions. + if (!gfxPrefs::LayoutEventRegionsEnabled()) { + MOZ_ASSERT(mEventRegions == EventRegions()); + MOZ_ASSERT(mTransform == gfx::Matrix4x4()); + return mClipRegion.Contains(aPoint.x, aPoint.y) + ? HitTestResult::ApzcHitRegion + : HitTestResult::NoApzcHit; + } + + // test against clip rect in ParentLayer coordinate space + if (!mClipRegion.Contains(aPoint.x, aPoint.y)) { + return HitTestResult::NoApzcHit; + } + + // convert into Layer coordinate space + gfx::Matrix4x4 localTransform = mTransform * gfx::Matrix4x4(mApzc->GetCurrentAsyncTransform()); + gfx::Point4D pointInLayerPixels = localTransform.Inverse().ProjectPoint(aPoint.ToUnknownPoint()); + if (!pointInLayerPixels.HasPositiveWCoord()) { + return HitTestResult::NoApzcHit; + } + LayerIntPoint point = RoundedToInt(ViewAs(pointInLayerPixels.As2DPoint())); + + // test against event regions in Layer coordinate space + if (!mEventRegions.mHitRegion.Contains(point.x, point.y)) { + return HitTestResult::NoApzcHit; + } + if (mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y)) { + return HitTestResult::ApzcContentRegion; + } + return HitTestResult::ApzcHitRegion; +} + void HitTestingTreeNode::Dump(const char* aPrefix) const { if (mPrevSibling) { mPrevSibling->Dump(aPrefix); } - printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) guid (%s)\n", - aPrefix, this, mApzc.get(), Stringify(mApzc->GetGuid()).c_str()); + printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) r=(%s) t=(%s) c=(%s)\n", + aPrefix, this, mApzc.get(), Stringify(mApzc->GetGuid()).c_str(), + Stringify(mEventRegions).c_str(), Stringify(mTransform).c_str(), + Stringify(mClipRegion).c_str()); if (mLastChild) { mLastChild->Dump(nsPrintfCString("%s ", aPrefix).get()); } diff --git a/gfx/layers/apz/src/HitTestingTreeNode.h b/gfx/layers/apz/src/HitTestingTreeNode.h index 6f1a8fc28365..fb6233e7adf3 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.h +++ b/gfx/layers/apz/src/HitTestingTreeNode.h @@ -7,8 +7,11 @@ #ifndef mozilla_layers_HitTestingTreeNode_h #define mozilla_layers_HitTestingTreeNode_h -#include "FrameMetrics.h" -#include "nsRefPtr.h" +#include "APZUtils.h" // for HitTestResult +#include "FrameMetrics.h" // for ScrollableLayerGuid +#include "mozilla/gfx/Matrix.h" // for Matrix4x4 +#include "mozilla/layers/LayersTypes.h" // for EventRegions +#include "nsRefPtr.h" // for nsRefPtr namespace mozilla { namespace layers { @@ -67,6 +70,12 @@ public: AsyncPanZoomController* Apzc() const; bool IsPrimaryHolder() const; + /* Hit test related methods */ + void SetHitTestData(const EventRegions& aRegions, + const gfx::Matrix4x4& aTransform, + const nsIntRegion& aClipRegion); + HitTestResult HitTest(const ParentLayerPoint& aPoint) const; + /* Debug helpers */ void Dump(const char* aPrefix = "") const; @@ -77,6 +86,32 @@ private: nsRefPtr mApzc; bool mIsPrimaryApzcHolder; + + /* Let {L,M} be the {layer, scrollable metrics} pair that this node + * corresponds to in the layer tree. Then, mEventRegions contains the union + * of the event regions of all layers in L's subtree, excluding those layers + * which are contained in a descendant HitTestingTreeNode's mEventRegions. + * This value is stored in L's LayerPixel space. + * For example, if this HitTestingTreeNode maps to a ContainerLayer with + * scrollable metrics and which has two PaintedLayer children, the event + * regions stored here will be the union of the three event regions in the + * ContainerLayer's layer pixel space. This means the event regions from the + * PaintedLayer children will have been transformed and clipped according to + * the individual properties on those layers but the ContainerLayer's event + * regions will be used "raw". */ + EventRegions mEventRegions; + + /* This is the transform that the layer subtree corresponding to this node is + * subject to. In the terms of the comment on mEventRegions, it is the + * transform from the ContainerLayer. This does NOT include any async + * transforms. */ + gfx::Matrix4x4 mTransform; + + /* This is the clip rect that the layer subtree corresponding to this node + * is subject to. In the terms of the comment on mEventRegions, it is the clip + * rect of the ContainerLayer, and is in the ContainerLayer's ParentLayerPixel + * space. */ + nsIntRegion mClipRegion; }; } diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 3b0a42373275..fbbc2663f053 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -1688,6 +1688,7 @@ protected: metrics.SetScrollableRect(aScrollableRect); metrics.SetScrollOffset(CSSPoint(0, 0)); aLayer->SetFrameMetrics(metrics); + aLayer->SetClipRect(&layerBound); if (!aScrollableRect.IsEqualEdges(CSSRect(-1, -1, -1, -1))) { // The purpose of this is to roughly mimic what layout would do in the // case of a scrollable frame with the event regions and clip. This lets @@ -1696,7 +1697,6 @@ protected: nsIntRect scrollRect = LayerIntRect::ToUntyped(RoundedToInt(aScrollableRect * metrics.LayersPixelsPerCSSPixel())); er.mHitRegion = nsIntRegion(nsIntRect(layerBound.TopLeft(), scrollRect.Size())); aLayer->SetEventRegions(er); - aLayer->SetClipRect(&layerBound); } } @@ -2444,7 +2444,12 @@ protected: void CreateEventRegionsLayerTree1() { const char* layerTreeSyntax = "c(tt)"; - root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); + nsIntRegion layerVisibleRegions[] = { + nsIntRegion(nsIntRect(0, 0, 200, 200)), // root + nsIntRegion(nsIntRect(0, 0, 100, 200)), // left half + nsIntRegion(nsIntRect(0, 100, 200, 100)), // bottom half + }; + root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 2); @@ -2472,7 +2477,11 @@ protected: void CreateEventRegionsLayerTree2() { const char* layerTreeSyntax = "c(t)"; - root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); + nsIntRegion layerVisibleRegions[] = { + nsIntRegion(nsIntRect(0, 0, 100, 500)), + nsIntRegion(nsIntRect(0, 150, 100, 100)), + }; + root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); // Set up the event regions so that the child thebes layer is positioned far