Commit 34569e44 authored by Tien-Ren Chen's avatar Tien-Ren Chen Committed by Commit Bot

[Blink] Correct ignore root layer scrolling in PaintLayerClipper

The flag kIgnoreOverflowClipAndScroll can be passed to PaintLayerClipper
to compute clip rect in the space of the scrolled box of the root layer.
This is done by first computing clip rect in the space of the border box,
then apply an anti-scroll to the rect if the rect was affected by the
scroll.

Prior to this CL, the condition that determines whether the anti-scroll
is needed was incorrect. It used a function that determines whether two
layers can ever have relative movement upon scrolled, and is allowed to
return false positive. This CL instead traverses the layer tree to see
whether the root layer is a part of the containing block chain.

BUG=825543

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Ifec0bddb9511aa3b878cc0757bb8fb6f59cfb0ab
Reviewed-on: https://chromium-review.googlesource.com/987319Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Tien-Ren Chen <trchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547979}
parent e8e14cfc
...@@ -402,6 +402,27 @@ bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const { ...@@ -402,6 +402,27 @@ bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const {
return AncestorScrollingLayer() != other->AncestorScrollingLayer(); return AncestorScrollingLayer() != other->AncestorScrollingLayer();
} }
bool PaintLayer::IsAffectedByScrollOf(const PaintLayer* ancestor) const {
if (this == ancestor)
return false;
const PaintLayer* current_layer = this;
while (current_layer && current_layer != ancestor) {
bool ancestor_escaped = false;
const PaintLayer* container =
current_layer->ContainingLayer(ancestor, &ancestor_escaped);
if (ancestor_escaped)
return false;
// Workaround the bug that LayoutView is mistakenly considered
// a fixed-pos container.
if (current_layer->GetLayoutObject().IsFixedPositioned() &&
container->IsRootLayer())
return false;
current_layer = container;
}
return current_layer == ancestor;
}
void PaintLayer::UpdateLayerPositionsAfterOverflowScroll() { void PaintLayer::UpdateLayerPositionsAfterOverflowScroll() {
if (IsRootLayer()) { if (IsRootLayer()) {
// The root PaintLayer (i.e. the LayoutView) is special, in that scroll // The root PaintLayer (i.e. the LayoutView) is special, in that scroll
......
...@@ -667,6 +667,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient { ...@@ -667,6 +667,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
bool FixedToViewport() const; bool FixedToViewport() const;
bool ScrollsWithRespectTo(const PaintLayer*) const; bool ScrollsWithRespectTo(const PaintLayer*) const;
bool IsAffectedByScrollOf(const PaintLayer* ancestor) const;
void AddLayerHitTestRects(LayerHitTestRects&, TouchAction) const; void AddLayerHitTestRects(LayerHitTestRects&, TouchAction) const;
// Compute rects only for this layer // Compute rects only for this layer
......
...@@ -458,7 +458,7 @@ void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context, ...@@ -458,7 +458,7 @@ void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context,
FloatPoint(), &context.root_layer->GetLayoutObject())); FloatPoint(), &context.root_layer->GetLayoutObject()));
if (context.respect_overflow_clip == kIgnoreOverflowClipAndScroll && if (context.respect_overflow_clip == kIgnoreOverflowClipAndScroll &&
context.root_layer->ScrollsOverflow() && context.root_layer->ScrollsOverflow() &&
layer_.ScrollsWithRespectTo(context.root_layer)) { layer_.IsAffectedByScrollOf(context.root_layer)) {
offset.Move(LayoutSize( offset.Move(LayoutSize(
context.root_layer->GetScrollableArea()->GetScrollOffset())); context.root_layer->GetScrollableArea()->GetScrollOffset()));
} }
......
...@@ -890,6 +890,27 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) { ...@@ -890,6 +890,27 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) {
PaintLayer* target_layer = PaintLayer* target_layer =
ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
GetDocument().domWindow()->scrollTo(0, 50);
GetDocument()
.GetLayoutView()
->Layer()
->Clipper(PaintLayer::kDoNotUseGeometryMapper)
.ClearClipRectsIncludingDescendants();
{
ClipRect clip_rect;
target_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
.CalculateBackgroundClipRect(
ClipRectsContext(GetDocument().GetLayoutView()->Layer(),
kAbsoluteClipRectsIgnoringViewportClip,
kIgnorePlatformOverlayScrollbarSize,
kIgnoreOverflowClipAndScroll),
clip_rect);
EXPECT_EQ(LayoutRect(100, 250, 300, 400), clip_rect.Rect());
}
GetDocument().domWindow()->scrollTo(0, 100);
{ {
ClipRect clip_rect; ClipRect clip_rect;
target_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper) target_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
...@@ -899,10 +920,32 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) { ...@@ -899,10 +920,32 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) {
kIgnorePlatformOverlayScrollbarSize, kIgnorePlatformOverlayScrollbarSize,
kIgnoreOverflowClipAndScroll), kIgnoreOverflowClipAndScroll),
clip_rect); clip_rect);
EXPECT_EQ(LayoutRect(100, 200, 300, 400), clip_rect.Rect()); EXPECT_EQ(LayoutRect(100, 300, 300, 400), clip_rect.Rect());
} }
}
TEST_P(PaintLayerClipperTestParameterized,
FixedLayerClipRectInDocumentSpaceWithNestedScroller) {
SetBodyInnerHTML(R"HTML(
<div style="position:fixed; left:100px; top:200px; width:300px; height:400px; overflow:scroll;">
<div style="width:200px; height:300px; overflow:hidden;">
<div id="target" style="position:relative;"></div>
</div>
<div style="height:3000px;"></div>
</div>
<div style="height:3000px;"></div>
)HTML");
Element* target = GetDocument().getElementById("target");
PaintLayer* target_layer =
ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
GetDocument().domWindow()->scrollTo(0, 50); GetDocument().domWindow()->scrollTo(0, 50);
GetDocument()
.GetLayoutView()
->Layer()
->Clipper(PaintLayer::kDoNotUseGeometryMapper)
.ClearClipRectsIncludingDescendants();
{ {
ClipRect clip_rect; ClipRect clip_rect;
...@@ -913,7 +956,21 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) { ...@@ -913,7 +956,21 @@ TEST_P(PaintLayerClipperTestParameterized, FixedLayerClipRectInDocumentSpace) {
kIgnorePlatformOverlayScrollbarSize, kIgnorePlatformOverlayScrollbarSize,
kIgnoreOverflowClipAndScroll), kIgnoreOverflowClipAndScroll),
clip_rect); clip_rect);
EXPECT_EQ(LayoutRect(100, 250, 300, 400), clip_rect.Rect()); EXPECT_EQ(LayoutRect(100, 250, 200, 300), clip_rect.Rect());
}
GetDocument().domWindow()->scrollTo(0, 100);
{
ClipRect clip_rect;
target_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
.CalculateBackgroundClipRect(
ClipRectsContext(GetDocument().GetLayoutView()->Layer(),
kAbsoluteClipRectsIgnoringViewportClip,
kIgnorePlatformOverlayScrollbarSize,
kIgnoreOverflowClipAndScroll),
clip_rect);
EXPECT_EQ(LayoutRect(100, 300, 200, 300), clip_rect.Rect());
} }
} }
......
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