Skip to content

Commit

Permalink
[scroll-anchoring] Implement scroll anchoring for subscrollers
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=261775
rdar://115746157

Reviewed by Simon Fraser.

Implement scroll anchoring for subscrollers.

* Source/WebCore/dom/Document.cpp:
(WebCore::Document::runScrollSteps):
* Source/WebCore/page/LocalFrameView.cpp:
(WebCore::LocalFrameView::LocalFrameView):
(WebCore::LocalFrameView::scrollPositionChanged):
(WebCore::LocalFrameView::updateScrollAnchoringElementsForScrollableAreas):
(WebCore::LocalFrameView::invalidateScrollAnchoringElement): Deleted.
(WebCore::LocalFrameView::updateScrollAnchoringElement): Deleted.
(WebCore::LocalFrameView::updateScrollPositionForScrollAnchoringController): Deleted.
* Source/WebCore/page/LocalFrameView.h:
* Source/WebCore/page/scrolling/ScrollAnchoringController.cpp:
(WebCore::ScrollAnchoringController::ScrollAnchoringController):
(WebCore::ScrollAnchoringController::invalidateAnchorElement):
(WebCore::ScrollAnchoringController::updateAnchorElement):
(WebCore::ScrollAnchoringController::adjustScrollPositionForAnchoring):
* Source/WebCore/page/scrolling/ScrollAnchoringController.h:
* Source/WebCore/platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::setScrollAnchoringController):
(WebCore::ScrollableArea::scrollAnchoringController):
(WebCore::ScrollableArea::scrollPositionChanged):
(WebCore::ScrollableArea::updateScrollAnchoringElement):
(WebCore::ScrollableArea::updateScrollPositionForScrollAnchoringController):
(WebCore::ScrollableArea::invalidateScrollAnchoringElement):
* Source/WebCore/platform/ScrollableArea.h:
(WebCore::ScrollableArea::updateScrollAnchoringElement): Deleted.
(WebCore::ScrollableArea::updateScrollPositionForScrollAnchoringController): Deleted.
* Source/WebCore/rendering/RenderLayerScrollableArea.cpp:
(WebCore::RenderLayerScrollableArea::RenderLayerScrollableArea):

Canonical link: https://commits.webkit.org/268848@main
  • Loading branch information
nmoucht committed Oct 4, 2023
1 parent d3044ed commit a886605
Show file tree
Hide file tree
Showing 29 changed files with 181 additions and 90 deletions.
2 changes: 2 additions & 0 deletions LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -5432,6 +5432,8 @@ security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.h
userscripts/user-script-plugin-document.html [ Skip ]

webkit.org/b/242983 imported/w3c/web-platform-tests/css/css-scroll-anchoring/fullscreen-crash.html [ Skip ]
webkit.org/b/261849 imported/w3c/web-platform-tests/css/css-scroll-anchoring/heuristic-with-offset-update-from-scroll-event-listener.html [ Skip ]
webkit.org/b/261849 imported/w3c/web-platform-tests/css/css-scroll-anchoring/zero-scroll-offset.html [ Skip ]

# These tests are image failures
imported/w3c/web-platform-tests/css/css-scroll-anchoring/vertical-rl-viewport-size-change-000.html [ Skip ]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<script src="../resources/accessibility-helper.js"></script>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<script src="../resources/accessibility-helper.js"></script>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true ] -->
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<style>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Mixing user and programmatic scroll of iframe</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Mixing user and programmatic scroll of iframe</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Mixing user and programmatic scroll of iframe</title>
Expand Down
2 changes: 1 addition & 1 deletion LayoutTests/fast/scrolling/ios/scroll-iframe-001.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Scrolling of iframe</title>
Expand Down
2 changes: 1 addition & 1 deletion LayoutTests/fast/scrolling/ios/scroll-iframe-002.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Scrolling of iframe</title>
Expand Down
2 changes: 1 addition & 1 deletion LayoutTests/fast/scrolling/ios/scroll-iframe-003.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html><!-- webkit-test-runner [ CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<title>Scrolling of iframe</title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true ] -->
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<style>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

FAIL Ancestor changes in document scroller. assert_equals: expected 150 but got 220
FAIL Ancestor changes in scrollable <div>. assert_equals: expected 200 but got 150
FAIL Ancestor changes in scrollable <div>. assert_equals: expected 150 but got 220

Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

FAIL Anchor node recomputed after an explicit scroll occurs. assert_equals: expected 600 but got 500
FAIL Anchor node recomputed after an explicit scroll occurs. assert_equals: expected 200 but got 100

Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

PASS Positioned ancestors with dynamic changes to offsets trigger scroll suppressions.
FAIL Positioned ancestors with dynamic changes to offsets trigger scroll suppressions. assert_equals: expected 200 but got 310

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
content

FAIL An element in a fragmented div should be able to be selected as an anchor node. assert_equals: expected 20 but got 10
PASS An element in a fragmented div should be able to be selected as an anchor node.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
content

FAIL Dynamically styling 'overflow-anchor: none' on the anchor node should prevent scroll anchoring assert_equals: expected 150 but got 100
FAIL Dynamically styling 'overflow-anchor: none' on the anchor node should prevent scroll anchoring assert_equals: expected 150 but got 200

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
content

FAIL Dynamically styling 'overflow-anchor: none' on the scroller element should prevent scroll anchoring assert_equals: expected 150 but got 100
FAIL Dynamically styling 'overflow-anchor: none' on the scroller element should prevent scroll anchoring assert_equals: expected 150 but got 200

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

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

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

FAIL Position changes in document scroller. assert_equals: expected 200 but got 175
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

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true ] -->
<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true CSSScrollAnchoringEnabled=false ] -->
<html>
<head>
<style>
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4661,7 +4661,7 @@ void Document::runScrollSteps()
if (scrollAnimationsInProgress)
page()->scheduleRenderingUpdate({ RenderingUpdateStep::Scroll });

frameView->updateScrollAnchoringElement();
frameView->updateScrollAnchoringElementsForScrollableAreas();
frameView->updateScrollAnchoringPositionForScrollableAreas();
}

Expand Down
54 changes: 31 additions & 23 deletions Source/WebCore/page/LocalFrameView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ LocalFrameView::LocalFrameView(LocalFrame& frame)
ScrollableArea::setVerticalScrollElasticity(verticalElasticity);
ScrollableArea::setHorizontalScrollElasticity(horizontalElasticity);
#endif
if (frame.document() && frame.document()->settings().cssScrollAnchoringEnabled())
if (m_frame->settings().cssScrollAnchoringEnabled())
m_scrollAnchoringController = WTF::makeUnique<ScrollAnchoringController>(*this);
}

Expand Down Expand Up @@ -2859,7 +2859,9 @@ void LocalFrameView::scrollOffsetChangedViaPlatformWidgetImpl(const ScrollOffset
updateCompositingLayersAfterScrolling();
repaintSlowRepaintObjects();
scrollPositionChanged(scrollPositionFromOffset(oldOffset), scrollPositionFromOffset(newOffset));

invalidateScrollAnchoringElement();
updateScrollAnchoringElement();

if (auto* renderView = this->renderView()) {
if (renderView->usesCompositing())
renderView->compositor().didChangeVisibleRect();
Expand Down Expand Up @@ -2895,9 +2897,6 @@ void LocalFrameView::scrollPositionChanged(const ScrollPosition& oldPosition, co
if (auto* layer = renderView->layer())
m_frame->editor().renderLayerDidScroll(*layer);
}

invalidateScrollAnchoringElement();
updateScrollAnchoringElement();
}

void LocalFrameView::applyRecursivelyWithVisibleRect(const Function<void(LocalFrameView& frameView, const IntRect& visibleRect)>& apply)
Expand Down Expand Up @@ -3867,24 +3866,6 @@ void LocalFrameView::performPostLayoutTasks()
m_frame->document()->scheduleDeferredAXObjectCacheUpdate();
}

void LocalFrameView::invalidateScrollAnchoringElement()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->invalidateAnchorElement();
}

void LocalFrameView::updateScrollAnchoringElement()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->updateAnchorElement();
}

void LocalFrameView::updateScrollPositionForScrollAnchoringController()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->adjustScrollPositionForAnchoring();
}

void LocalFrameView::dequeueScrollableAreaForScrollAnchoringUpdate(ScrollableArea& scrollableArea)
{
m_scrollableAreasWithScrollAnchoringControllersNeedingUpdate.remove(scrollableArea);
Expand All @@ -3895,6 +3876,15 @@ void LocalFrameView::queueScrollableAreaForScrollAnchoringUpdate(ScrollableArea&
m_scrollableAreasWithScrollAnchoringControllersNeedingUpdate.add(scrollableArea);
}

void LocalFrameView::updateScrollAnchoringElementsForScrollableAreas()
{
updateScrollAnchoringElement();
if (!m_scrollableAreas)
return;
for (auto& scrollableArea : *m_scrollableAreas)
scrollableArea.updateScrollAnchoringElement();
}

void LocalFrameView::updateScrollAnchoringPositionForScrollableAreas()
{
auto scrollableAreasNeedingUpdate = std::exchange(m_scrollableAreasWithScrollAnchoringControllersNeedingUpdate, { });
Expand Down Expand Up @@ -6452,6 +6442,24 @@ void LocalFrameView::writeRenderTreeAsText(TextStream& ts, OptionSet<RenderAsTex
externalRepresentationForLocalFrame(ts, frame(), behavior);
}

void LocalFrameView::updateScrollAnchoringElement()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->updateAnchorElement();
}

void LocalFrameView::updateScrollPositionForScrollAnchoringController()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->adjustScrollPositionForAnchoring();
}

void LocalFrameView::invalidateScrollAnchoringElement()
{
if (m_scrollAnchoringController)
m_scrollAnchoringController->invalidateAnchorElement();
}

} // namespace WebCore

#undef PAGE_ID
Expand Down
12 changes: 7 additions & 5 deletions Source/WebCore/page/LocalFrameView.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,14 +736,15 @@ class LocalFrameView final : public FrameView {
ScrollbarGutter scrollbarGutterStyle() const final;
ScrollbarWidth scrollbarWidthStyle() const final;

void updateScrollAnchoringElement() final;
void updateScrollPositionForScrollAnchoringController() final;
void invalidateScrollAnchoringElement();

void dequeueScrollableAreaForScrollAnchoringUpdate(ScrollableArea&);
void queueScrollableAreaForScrollAnchoringUpdate(ScrollableArea&);
void updateScrollAnchoringElementsForScrollableAreas();
void updateScrollAnchoringPositionForScrollableAreas();

void updateScrollAnchoringElement() final;
void updateScrollPositionForScrollAnchoringController() final;
void invalidateScrollAnchoringElement() final;

private:
explicit LocalFrameView(LocalFrame&);

Expand Down Expand Up @@ -1026,9 +1027,10 @@ class LocalFrameView final : public FrameView {
ViewportRendererType m_viewportRendererType { ViewportRendererType::None };
ScrollPinningBehavior m_scrollPinningBehavior { ScrollPinningBehavior::DoNotPin };
SelectionRevealMode m_selectionRevealModeForFocusedElement { SelectionRevealMode::DoNotReveal };
std::unique_ptr<ScrollAnchoringController> m_scrollAnchoringController;
ScrollableAreaSet m_scrollableAreasWithScrollAnchoringControllersNeedingUpdate;

std::unique_ptr<ScrollAnchoringController> m_scrollAnchoringController;

bool m_shouldUpdateWhileOffscreen { true };
bool m_overflowStatusDirty { true };
bool m_horizontalOverflow { false };
Expand Down
Loading

0 comments on commit a886605

Please sign in to comment.