Bug 1270955 - When hit-testing on fixed-pos layers, find the root APZC for the scroll container rather than the layers id. r?botond
MozReview-Commit-ID: xuISpyT8KC
--- a/gfx/layers/LayerMetricsWrapper.h
+++ b/gfx/layers/LayerMetricsWrapper.h
@@ -429,16 +429,23 @@ public:
}
bool IsScrollbarContainer() const
{
MOZ_ASSERT(IsValid());
return mLayer->IsScrollbarContainer();
}
+ FrameMetrics::ViewID GetFixedPositionScrollContainerId() const
+ {
+ MOZ_ASSERT(IsValid());
+
+ return mLayer->GetFixedPositionScrollContainerId();
+ }
+
// Expose an opaque pointer to the layer. Mostly used for printf
// purposes. This is not intended to be a general-purpose accessor
// for the underlying layer.
const void* GetLayer() const
{
MOZ_ASSERT(IsValid());
return (void*)mLayer;
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -364,16 +364,17 @@ APZCTreeManager::PrepareNodeForLayer(con
GetEventRegions(aLayer),
aLayer.GetTransformTyped(),
aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(),
GetEventRegionsOverride(aParent, aLayer));
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
aLayer.GetScrollbarDirection(),
aLayer.GetScrollbarSize(),
aLayer.IsScrollbarContainer());
+ node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
return node;
}
AsyncPanZoomController* apzc = nullptr;
// If we get here, aLayer is a scrollable layer and somebody
// has registered a GeckoContentController for it, so we need to ensure
// it has an APZC instance to manage its scrolling.
@@ -544,16 +545,17 @@ APZCTreeManager::PrepareNodeForLayer(con
Some(clipRegion),
GetEventRegionsOverride(aParent, aLayer));
}
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
aLayer.GetScrollbarDirection(),
aLayer.GetScrollbarSize(),
aLayer.IsScrollbarContainer());
+ node->SetFixedPosData(aLayer.GetFixedPositionScrollContainerId());
return node;
}
HitTestingTreeNode*
APZCTreeManager::UpdateHitTestingTree(TreeBuildingState& aState,
const LayerMetricsWrapper& aLayer,
uint64_t aLayersId,
const gfx::Matrix4x4& aAncestorTransform,
@@ -1768,20 +1770,35 @@ APZCTreeManager::GetAPZCAtPoint(HitTesti
MOZ_ASSERT(resultNode);
if (aOutHitScrollbar) {
for (HitTestingTreeNode* n = resultNode; n; n = n->GetParent()) {
if (n->IsScrollbarNode()) {
*aOutHitScrollbar = true;
}
}
}
- AsyncPanZoomController* result = resultNode->GetNearestContainingApzcWithSameLayersId();
+
+ AsyncPanZoomController* result = nullptr;
+
+ FrameMetrics::ViewID fpTarget =
+ resultNode->GetNearestAncestorFixedPosTargetWithSameLayersId();
+ if (fpTarget != FrameMetrics::NULL_SCROLL_ID) {
+ ScrollableLayerGuid guid(resultNode->GetLayersId(), 0, fpTarget);
+ RefPtr<HitTestingTreeNode> hitNode = GetTargetNode(guid, &GuidComparatorIgnoringPresShell);
+ result = hitNode ? hitNode->GetApzc() : nullptr;
+ APZCTM_LOG("Found target %p using fixed-pos lookup on %" PRIu64 "\n", result, fpTarget);
+ }
+ if (!result) {
+ result = resultNode->GetNearestContainingApzcWithSameLayersId();
+ APZCTM_LOG("Found target %p using ancestor lookup\n", result);
+ }
if (!result) {
result = FindRootApzcForLayersId(resultNode->GetLayersId());
MOZ_ASSERT(result);
+ APZCTM_LOG("Found target %p using root lookup\n", result);
}
APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n",
result, resultNode, *aOutHitResult);
return result;
}
return nullptr;
}
--- a/gfx/layers/apz/src/HitTestingTreeNode.cpp
+++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp
@@ -24,16 +24,17 @@ HitTestingTreeNode::HitTestingTreeNode(A
uint64_t aLayersId)
: mApzc(aApzc)
, mIsPrimaryApzcHolder(aIsPrimaryHolder)
, mLayersId(aLayersId)
, mScrollViewId(FrameMetrics::NULL_SCROLL_ID)
, mScrollDir(Layer::NONE)
, mScrollSize(0)
, mIsScrollbarContainer(false)
+ , mFixedPosTarget(FrameMetrics::NULL_SCROLL_ID)
, mOverride(EventRegionsOverride::NoOverride)
{
if (mIsPrimaryApzcHolder) {
MOZ_ASSERT(mApzc);
}
MOZ_ASSERT(!mApzc || mApzc->GetLayersId() == mLayersId);
}
@@ -122,16 +123,35 @@ HitTestingTreeNode::GetScrollSize() cons
bool
HitTestingTreeNode::IsScrollbarNode() const
{
return mIsScrollbarContainer || (mScrollDir != Layer::NONE);
}
void
+HitTestingTreeNode::SetFixedPosData(FrameMetrics::ViewID aFixedPosTarget)
+{
+ mFixedPosTarget = aFixedPosTarget;
+}
+
+FrameMetrics::ViewID
+HitTestingTreeNode::GetNearestAncestorFixedPosTargetWithSameLayersId() const
+{
+ for (const HitTestingTreeNode* n = this;
+ n && n->mLayersId == mLayersId;
+ n = n->GetParent()) {
+ if (n->mFixedPosTarget != FrameMetrics::NULL_SCROLL_ID) {
+ return n->mFixedPosTarget;
+ }
+ }
+ return FrameMetrics::NULL_SCROLL_ID;
+}
+
+void
HitTestingTreeNode::SetPrevSibling(HitTestingTreeNode* aSibling)
{
mPrevSibling = aSibling;
if (aSibling) {
aSibling->mParent = mParent;
if (aSibling->GetApzc()) {
AsyncPanZoomController* parent = mParent ? mParent->GetNearestContainingApzc() : nullptr;
@@ -288,21 +308,22 @@ HitTestingTreeNode::GetEventRegionsOverr
}
void
HitTestingTreeNode::Dump(const char* aPrefix) const
{
if (mPrevSibling) {
mPrevSibling->Dump(aPrefix);
}
- printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) %s%sr=(%s) t=(%s) c=(%s)\n",
+ printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) %s%s%sr=(%s) t=(%s) c=(%s)\n",
aPrefix, this, mApzc.get(),
mApzc ? Stringify(mApzc->GetGuid()).c_str() : nsPrintfCString("l=%" PRIu64, mLayersId).get(),
(mOverride & EventRegionsOverride::ForceDispatchToContent) ? "fdtc " : "",
(mOverride & EventRegionsOverride::ForceEmptyHitRegion) ? "fehr " : "",
+ (mFixedPosTarget != FrameMetrics::NULL_SCROLL_ID) ? nsPrintfCString("fixed=%" PRIu64 " ", mFixedPosTarget).get() : "",
Stringify(mEventRegions).c_str(), Stringify(mTransform).c_str(),
mClipRegion ? Stringify(mClipRegion.ref()).c_str() : "none");
if (mLastChild) {
mLastChild->Dump(nsPrintfCString("%s ", aPrefix).get());
}
}
void
--- a/gfx/layers/apz/src/HitTestingTreeNode.h
+++ b/gfx/layers/apz/src/HitTestingTreeNode.h
@@ -95,16 +95,21 @@ public:
void SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
Layer::ScrollDirection aDir,
int32_t aScrollSize,
bool aIsScrollContainer);
bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
int32_t GetScrollSize() const;
bool IsScrollbarNode() const;
+ /* Fixed pos info */
+
+ void SetFixedPosData(FrameMetrics::ViewID aFixedPosTarget);
+ FrameMetrics::ViewID GetNearestAncestorFixedPosTargetWithSameLayersId() const;
+
/* Convert aPoint into the LayerPixel space for the layer corresponding to
* this node. */
Maybe<LayerPoint> Untransform(const ParentLayerPoint& aPoint) const;
/* Assuming aPoint is inside the clip region for this node, check which of the
* event region spaces it falls inside. */
HitTestResult HitTest(const ParentLayerPoint& aPoint) const;
/* Returns the mOverride flag. */
EventRegionsOverride GetEventRegionsOverride() const;
@@ -124,16 +129,18 @@ private:
uint64_t mLayersId;
FrameMetrics::ViewID mScrollViewId;
Layer::ScrollDirection mScrollDir;
int32_t mScrollSize;
bool mIsScrollbarContainer;
+ FrameMetrics::ViewID mFixedPosTarget;
+
/* Let {L,M} be the {layer, scrollable metrics} pair that this node
* corresponds to in the layer tree. mEventRegions contains the event regions
* from L, in the case where event-regions are enabled. If event-regions are
* disabled, it will contain the visible region of L, which we use as an
* approximation to the hit region for the purposes of obscuring other layers.
* This value is in L's LayerPixels.
*/
EventRegions mEventRegions;