Bug 1627362 - Properly support items stuck to both bottom and top. r=botond

The semantics of sticky items are somewhat different from the semantics of
fixed items. For fixed items, if an item is fixed to eTop or eBottom or
eTopBottom, it is *always* fixed to those sides. For sticky items, however,
the sides actively stuck to are dependent on the scroll position. So we need
a mechanism to dynamically figure out which sides are stuck, and use those
sides when computing the fixed margins to apply. This patch implements that
by modifying the IsStuckToRootContentAtBottom method into a
SidesStuckToRootContent method.

Differential Revision: https://phabricator.services.mozilla.com/D70910

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kartikaya Gupta 2020-04-15 21:05:12 +00:00
parent 952f78e233
commit bbdeafdcdb
2 changed files with 27 additions and 17 deletions

View File

@ -3529,33 +3529,35 @@ bool APZCTreeManager::IsFixedToRootContent(
return targetApzc && targetApzc->IsRootContent();
}
bool APZCTreeManager::IsStuckToRootContentAtBottom(
SideBits APZCTreeManager::SidesStuckToRootContent(
const HitTestingTreeNode* aNode) const {
MutexAutoLock lock(mMapLock);
return IsStuckToRootContentAtBottom(StickyPositionInfo(aNode), lock);
return SidesStuckToRootContent(StickyPositionInfo(aNode), lock);
}
bool APZCTreeManager::IsStuckToRootContentAtBottom(
SideBits APZCTreeManager::SidesStuckToRootContent(
const StickyPositionInfo& aStickyInfo,
const MutexAutoLock& aProofOfMapLock) const {
SideBits result = SideBits::eNone;
ScrollableLayerGuid::ViewID stickyTarget = aStickyInfo.mStickyPosTarget;
if (stickyTarget == ScrollableLayerGuid::NULL_SCROLL_ID) {
return false;
return result;
}
// We support the dynamic toolbar at top and bottom.
if ((aStickyInfo.mFixedPosSides & SideBits::eTopBottom) == SideBits::eNone) {
return false;
return result;
}
auto it = mApzcMap.find(
ScrollableLayerGuid(aStickyInfo.mLayersId, 0, stickyTarget));
if (it == mApzcMap.end()) {
return false;
return result;
}
RefPtr<AsyncPanZoomController> stickyTargetApzc = it->second.apzc;
if (!stickyTargetApzc || !stickyTargetApzc->IsRootContent()) {
return false;
return result;
}
ParentLayerPoint translation =
@ -3564,9 +3566,16 @@ bool APZCTreeManager::IsStuckToRootContentAtBottom(
AsyncPanZoomController::eForHitTesting,
AsyncTransformComponents{AsyncTransformComponent::eLayout})
.mTranslation;
return apz::IsStuckAtBottom(translation.y,
aStickyInfo.mStickyScrollRangeInner,
aStickyInfo.mStickyScrollRangeOuter);
if (apz::IsStuckAtTop(translation.y, aStickyInfo.mStickyScrollRangeInner,
aStickyInfo.mStickyScrollRangeOuter)) {
result |= SideBits::eTop;
}
if (apz::IsStuckAtBottom(translation.y, aStickyInfo.mStickyScrollRangeInner,
aStickyInfo.mStickyScrollRangeOuter)) {
result |= SideBits::eBottom;
}
return result;
}
LayerToParentLayerMatrix4x4 APZCTreeManager::ComputeTransformForNode(
@ -3648,14 +3657,15 @@ LayerToParentLayerMatrix4x4 APZCTreeManager::ComputeTransformForNode(
return aNode->GetTransform() *
CompleteAsyncTransform(
AsyncTransformComponentMatrix::Translation(translation));
} else if (IsStuckToRootContentAtBottom(aNode)) {
}
SideBits sides = SidesStuckToRootContent(aNode);
if (sides != SideBits::eNone) {
ParentLayerPoint translation;
{
MutexAutoLock mapLock(mMapLock);
translation = ViewAs<ParentLayerPixel>(
AsyncCompositionManager::ComputeFixedMarginsOffset(
GetCompositorFixedLayerMargins(mapLock),
aNode->GetFixedPosSides() & SideBits::eTopBottom,
GetCompositorFixedLayerMargins(mapLock), sides,
// For sticky layers, we don't need to factor
// mGeckoFixedLayerMargins because Gecko doesn't shift the
// position of sticky elements for dynamic toolbar movements.

View File

@ -680,13 +680,13 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
bool IsFixedToRootContent(const FixedPositionInfo& aFixedInfo,
const MutexAutoLock& aProofOfMapLock) const;
// Returns true that |aNode| is stuck to the root content at bottom.
// Returns the vertical sides of |aNode| that are stuck to the root content.
// The map lock is required within these functions; if the map lock is already
// being held by the caller, the second overload should be used. If the map
// lock is not being held at the call site, the first overload should be used.
bool IsStuckToRootContentAtBottom(const HitTestingTreeNode* aNode) const;
bool IsStuckToRootContentAtBottom(const StickyPositionInfo& aStickyInfo,
const MutexAutoLock& aProofOfMapLock) const;
SideBits SidesStuckToRootContent(const HitTestingTreeNode* aNode) const;
SideBits SidesStuckToRootContent(const StickyPositionInfo& aStickyInfo,
const MutexAutoLock& aProofOfMapLock) const;
/**
* Perform hit testing for a touch-start event.