Skip to content

Commit

Permalink
[scroll-anchoring] findAnchorElementRecursive should descend into sub…
Browse files Browse the repository at this point in the history
…scrollers if its not maintaining a scroll anchor

https://bugs.webkit.org/show_bug.cgi?id=262557
rdar://116411088

Reviewed by Simon Fraser.

We should only disallow descending into subscrollers if the subscroller is currently
maintaining a scroll anchor.

* LayoutTests/imported/w3c/web-platform-tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box-expected.txt:
* Source/WebCore/page/scrolling/ScrollAnchoringController.cpp:
(WebCore::elementForScrollableArea):
(WebCore::ScrollAnchoringController::invalidateAnchorElement):
(WebCore::canDescendIntoElement):
(WebCore::ScrollAnchoringController::examineCandidate):
* Source/WebCore/rendering/RenderObject.cpp:
(WebCore::RenderObject::findScrollAnchoringControllerForRenderer):

Canonical link: https://commits.webkit.org/272277@main
  • Loading branch information
nmoucht committed Dec 19, 2023
1 parent 57fdd17 commit 07319b8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

FAIL Position changes in document scroller. assert_equals: expected 225 but got 200
FAIL Position changes in scrollable <div>. assert_equals: expected 225 but got 200
PASS Position changes in document scroller.
PASS Position changes in scrollable <div>.

45 changes: 34 additions & 11 deletions Source/WebCore/page/scrolling/ScrollAnchoringController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,29 @@ static bool elementIsScrollableArea(const Element& element, const ScrollableArea
return element.renderBox() && element.renderBox()->layer() && element.renderBox()->layer()->scrollableArea() == &scrollableArea;
}

static Element* elementForScrollableArea(ScrollableArea& scrollableArea)
{
if (is<RenderLayerScrollableArea>(scrollableArea))
return downcast<RenderLayerScrollableArea>(scrollableArea).layer().renderer().element();
if (auto* document = downcast<LocalFrameView>(downcast<ScrollView>(scrollableArea)).frame().document())
return document->documentElement();
return nullptr;
}

void ScrollAnchoringController::invalidateAnchorElement()
{
if (m_midUpdatingScrollPositionForAnchorElement)
return;
LOG_WITH_STREAM(ScrollAnchoring, stream << "ScrollAnchoringController::invalidateAnchorElement() invalidating anchor for frame: " << frameView() << " for scroller: " << m_owningScrollableArea);

if (!m_anchorElement) {
if (auto* element = elementForScrollableArea(m_owningScrollableArea)) {
if (auto* renderer = element->renderer()) {
auto* scrollAnchoringControllerForScrollableArea = RenderObject::findScrollAnchoringControllerForRenderer(*renderer);
if (scrollAnchoringControllerForScrollableArea && scrollAnchoringControllerForScrollableArea->isInScrollAnchoringAncestorChain(*renderer))
scrollAnchoringControllerForScrollableArea->invalidateAnchorElement();
}
}
}
m_anchorElement = nullptr;
m_lastOffsetForAnchorElement = { };
m_isQueuedForScrollPositionUpdate = false;
Expand All @@ -80,15 +97,6 @@ static IntRect boundingRectForScrollableArea(ScrollableArea& scrollableArea)
return IntRect(downcast<LocalFrameView>(downcast<ScrollView>(scrollableArea)).layoutViewportRect());
}

static Element* elementForScrollableArea(ScrollableArea& scrollableArea)
{
if (is<RenderLayerScrollableArea>(scrollableArea))
return downcast<RenderLayerScrollableArea>(scrollableArea).layer().renderer().element();
if (auto* document = downcast<LocalFrameView>(downcast<ScrollView>(scrollableArea)).frame().document())
return document->documentElement();
return nullptr;
}

FloatPoint ScrollAnchoringController::computeOffsetFromOwningScroller(RenderObject& candidate)
{
// TODO: investigate this for zoom/rtl
Expand Down Expand Up @@ -171,6 +179,21 @@ static bool absolutePositionedElementOutsideScroller(RenderElement& renderer, Sc
return false;
}

static bool canDescendIntoElement(Element& element)
{
if (auto renderer = element.renderer()) {
if (renderer->hasLayer()) {
if (auto layer = downcast<RenderLayerModelObject>(*renderer).layer()) {
if (auto scrollableArea = layer->scrollableArea()) {
if (auto* scrollAnchoringController = scrollableArea->scrollAnchoringController())
return !scrollAnchoringController->anchorElement();
}
}
}
}
return false;
}

CandidateExaminationResult ScrollAnchoringController::examineAnchorCandidate(Element& element)
{
if (elementForScrollableArea(m_owningScrollableArea) && elementForScrollableArea(m_owningScrollableArea)->identifier() == element.identifier())
Expand Down Expand Up @@ -209,7 +232,7 @@ CandidateExaminationResult ScrollAnchoringController::examineAnchorCandidate(Ele
if (auto* renderBox = dynamicDowncast<RenderBox>(renderer))
isScrollingNode = renderBox->hasPotentiallyScrollableOverflow();
if (intersects)
return isScrollingNode ? CandidateExaminationResult::Select : CandidateExaminationResult::Descend;
return !isScrollingNode || canDescendIntoElement(element) ? CandidateExaminationResult::Descend : CandidateExaminationResult::Select;
if (isScrollingNode)
return CandidateExaminationResult::Exclude;
}
Expand Down
7 changes: 5 additions & 2 deletions Source/WebCore/rendering/RenderObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,8 +2371,11 @@ Vector<FloatRect> RenderObject::clientBorderAndTextRects(const SimpleRange& rang
ScrollAnchoringController* RenderObject::findScrollAnchoringControllerForRenderer(const RenderObject& renderer)
{
if (renderer.hasLayer()) {
if (auto* scrollableArea = downcast<RenderLayerModelObject>(renderer).layer()->scrollableArea())
return scrollableArea->scrollAnchoringController();
if (auto* scrollableArea = downcast<RenderLayerModelObject>(renderer).layer()->scrollableArea()) {
auto controller = scrollableArea->scrollAnchoringController();
if (controller && controller->anchorElement())
return controller;
}
}
for (auto* enclosingLayer = renderer.enclosingLayer(); enclosingLayer; enclosingLayer = enclosingLayer->parent()) {
if (RenderLayerScrollableArea* scrollableArea = enclosingLayer->scrollableArea()) {
Expand Down

0 comments on commit 07319b8

Please sign in to comment.