Commit 379712bf authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

Store block-start offset in scroll anchor.

Storing a purely physical offset was problematic when in vertical-rl
writing-mode, if the viewport size changes.

We were storing the X coordinate relative to the left edge of the
visible contents inside the scrollport. However, in vertical-rl
writing-mode the block-start is at the right side of the scrollport.

If the viewport width changed, the distance from the left edge to the
anchored element would also change, even though the scroll offset
remained exactly the same, and we'd mess up the scroll offset.

Bug: 1124195
Change-Id: Id91a25012da2d0cbd803e543b6cb02ba66eb20e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2390380Reviewed-by: default avatarStefan Zager <szager@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804469}
parent db9f2acd
...@@ -123,7 +123,10 @@ static LayoutRect RelativeBounds(const LayoutObject* layout_object, ...@@ -123,7 +123,10 @@ static LayoutRect RelativeBounds(const LayoutObject* layout_object,
static LayoutPoint ComputeRelativeOffset(const LayoutObject* layout_object, static LayoutPoint ComputeRelativeOffset(const LayoutObject* layout_object,
const ScrollableArea* scroller, const ScrollableArea* scroller,
Corner corner) { Corner corner) {
return CornerPointOfRect(RelativeBounds(layout_object, scroller), corner); LayoutPoint offset =
CornerPointOfRect(RelativeBounds(layout_object, scroller), corner);
const LayoutBox* scroller_box = ScrollerLayoutBox(scroller);
return scroller_box->FlipForWritingMode(PhysicalOffset(offset));
} }
static bool CandidateMayMoveWithScroller(const LayoutObject* candidate, static bool CandidateMayMoveWithScroller(const LayoutObject* candidate,
...@@ -504,10 +507,16 @@ IntSize ScrollAnchor::ComputeAdjustment() const { ...@@ -504,10 +507,16 @@ IntSize ScrollAnchor::ComputeAdjustment() const {
RoundedIntSize(saved_relative_offset_); RoundedIntSize(saved_relative_offset_);
// Only adjust on the block layout axis. // Only adjust on the block layout axis.
if (ScrollerLayoutBox(scroller_)->IsHorizontalWritingMode()) const LayoutBox* scroller_box = ScrollerLayoutBox(scroller_);
if (scroller_box->IsHorizontalWritingMode()) {
delta.SetWidth(0); delta.SetWidth(0);
else } else {
// If block direction is flipped, delta is a logical value, so flip it to
// make it physical.
if (scroller_box->HasFlippedBlocksWritingMode())
delta.SetWidth(-delta.Width());
delta.SetHeight(0); delta.SetHeight(0);
}
return delta; return delta;
} }
......
...@@ -157,8 +157,10 @@ class CORE_EXPORT ScrollAnchor final { ...@@ -157,8 +157,10 @@ class CORE_EXPORT ScrollAnchor final {
// Which corner of m_anchorObject's bounding box to anchor to. // Which corner of m_anchorObject's bounding box to anchor to.
Corner corner_; Corner corner_;
// Location of m_layoutObject relative to scroller at time of // Location of anchor_object_ relative to scroller block-start at the time of
// notifyBeforeLayout(). // NotifyBeforeLayout(). Note that the block-offset is a logical coordinate,
// which makes a difference if we're in a block-flipped writing-mode
// (vertical-rl).
LayoutPoint saved_relative_offset_; LayoutPoint saved_relative_offset_;
// Previously calculated css selector that uniquely locates the current // Previously calculated css selector that uniquely locates the current
......
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<style>
html {
writing-mode: vertical-rl;
overflow: hidden;
background: red;
}
body {
margin: 0;
}
</style>
<div style="display:flex; flex-direction:column-reverse;">
<div style="block-size:1000px;"></div>
<div style="block-size:100px; background:green;"></div>
<div style="block-size:100px;"></div>
</div>
<script>
window.scrollTo(-100, 0);
</script>
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<style>
html {
writing-mode: vertical-rl;
overflow: hidden;
background: red;
}
body {
margin: 0;
}
</style>
<div style="block-size:100px;"></div>
<div style="block-size:100px; background:green;"></div>
<div style="block-size:1000px;"></div>
<script>
window.scrollTo(-100, 0);
</script>
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1124195">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<style>
#iframe {
display: block;
border: none;
width: 300px;
height: 100px;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<iframe id="iframe" src="support/scrolling-vertical-rl.html"></iframe>
<script>
onload = function() {
document.body.offsetTop;
iframe.style.width = "100px";
}
</script>
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/">
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1124195">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<style>
#iframe {
display: block;
border: none;
width: 300px;
height: 100px;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<iframe id="iframe" src="support/flexbox-scrolling-vertical-rl.html"></iframe>
<script>
onload = function() {
document.body.offsetTop;
iframe.style.width = "100px";
}
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment