- Revision
- 243309
- Author
- [email protected]
- Date
- 2019-03-21 11:58:09 -0700 (Thu, 21 Mar 2019)
Log Message
Absolute in stacking-context scroller jiggles when scrolled
https://bugs.webkit.org/show_bug.cgi?id=196010
Reviewed by Zalan Bujtas.
Source/WebCore:
Updating compositing layers after a scroll (in a compositing update on the main thread)
failed to traverse to an absolute layer inside a stacking-context overflow:scroll,
because the overflow's layer didn't have the "hasCompositingAncestor" bit set on it.
This happened because childState.subtreeIsCompositing wasn't being set when indirect
reasons trigger compositing. So clean up RenderLayerCompositor::computeCompositingRequirements()
to set childState.subtreeIsCompositing for "late" compositing decisions, and move the
"Subsequent layers in the parent stacking context also need to composite" chunk
down to after the last compositing decision has been made.
Test: compositing/overflow/absolute-in-overflow.html
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::scrollTo):
* page/scrolling/cocoa/ScrollingTreePositionedNode.mm:
(WebCore::ScrollingTreePositionedNode::applyLayerPositions):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
LayoutTests:
* compositing/overflow/absolute-in-overflow-expected.html: Added.
* compositing/overflow/absolute-in-overflow.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (243308 => 243309)
--- trunk/LayoutTests/ChangeLog 2019-03-21 18:57:09 UTC (rev 243308)
+++ trunk/LayoutTests/ChangeLog 2019-03-21 18:58:09 UTC (rev 243309)
@@ -1,3 +1,13 @@
+2019-03-21 Simon Fraser <[email protected]>
+
+ Absolute in stacking-context scroller jiggles when scrolled
+ https://bugs.webkit.org/show_bug.cgi?id=196010
+
+ Reviewed by Zalan Bujtas.
+
+ * compositing/overflow/absolute-in-overflow-expected.html: Added.
+ * compositing/overflow/absolute-in-overflow.html: Added.
+
2019-03-21 Zalan Bujtas <[email protected]>
[ContentChangeObserver] Start tracking implicit transitions at touchStart
Added: trunk/LayoutTests/compositing/overflow/absolute-in-overflow-expected.html (0 => 243309)
--- trunk/LayoutTests/compositing/overflow/absolute-in-overflow-expected.html (rev 0)
+++ trunk/LayoutTests/compositing/overflow/absolute-in-overflow-expected.html 2019-03-21 18:58:09 UTC (rev 243309)
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+ #scroller {
+ margin: 10px;
+ background-color: silver;
+ width: 400px;
+ height: 300px;
+ overflow: scroll;
+ opacity: 0.8;
+ }
+
+ .scrolling-content {
+ height: 1000px;
+ }
+
+ .absolute {
+ top: 20px;
+ left: 20px;
+ width: 200px;
+ height: 200px;
+ background-color: blue;
+ }
+
+ .changed {
+ position: absolute;
+ }
+ </style>
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ if (window.internals)
+ window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+ function doTest()
+ {
+ setTimeout(() => {
+ scroller.scrollTop = 200;
+ target.classList.add('changed');
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }, 0);
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div id="scroller">
+ <div class="scrolling-content">
+ <div id="target" class="absolute"></div>
+ </div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/compositing/overflow/absolute-in-overflow.html (0 => 243309)
--- trunk/LayoutTests/compositing/overflow/absolute-in-overflow.html (rev 0)
+++ trunk/LayoutTests/compositing/overflow/absolute-in-overflow.html 2019-03-21 18:58:09 UTC (rev 243309)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+ #scroller {
+ margin: 10px;
+ background-color: silver;
+ width: 400px;
+ height: 300px;
+ overflow: scroll;
+ opacity: 0.8;
+ }
+
+ .scrolling-content {
+ height: 1000px;
+ }
+
+ .absolute {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ width: 200px;
+ height: 200px;
+ background-color: blue;
+ }
+ </style>
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ if (window.internals)
+ window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+ function doTest()
+ {
+ setTimeout(() => {
+ scroller.scrollTop = 200;
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }, 0);
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div id="scroller">
+ <div class="scrolling-content">
+ <div class="absolute"></div>
+ </div>
+ </div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (243308 => 243309)
--- trunk/Source/WebCore/ChangeLog 2019-03-21 18:57:09 UTC (rev 243308)
+++ trunk/Source/WebCore/ChangeLog 2019-03-21 18:58:09 UTC (rev 243309)
@@ -1,3 +1,29 @@
+2019-03-21 Simon Fraser <[email protected]>
+
+ Absolute in stacking-context scroller jiggles when scrolled
+ https://bugs.webkit.org/show_bug.cgi?id=196010
+
+ Reviewed by Zalan Bujtas.
+
+ Updating compositing layers after a scroll (in a compositing update on the main thread)
+ failed to traverse to an absolute layer inside a stacking-context overflow:scroll,
+ because the overflow's layer didn't have the "hasCompositingAncestor" bit set on it.
+
+ This happened because childState.subtreeIsCompositing wasn't being set when indirect
+ reasons trigger compositing. So clean up RenderLayerCompositor::computeCompositingRequirements()
+ to set childState.subtreeIsCompositing for "late" compositing decisions, and move the
+ "Subsequent layers in the parent stacking context also need to composite" chunk
+ down to after the last compositing decision has been made.
+
+ Test: compositing/overflow/absolute-in-overflow.html
+
+ * page/scrolling/ScrollingTreeScrollingNode.cpp:
+ (WebCore::ScrollingTreeScrollingNode::scrollTo):
+ * page/scrolling/cocoa/ScrollingTreePositionedNode.mm:
+ (WebCore::ScrollingTreePositionedNode::applyLayerPositions):
+ * rendering/RenderLayerCompositor.cpp:
+ (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+
2019-03-21 Zalan Bujtas <[email protected]>
[ContentChangeObserver] Start tracking implicit transitions at touchStart
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (243308 => 243309)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2019-03-21 18:57:09 UTC (rev 243308)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2019-03-21 18:58:09 UTC (rev 243309)
@@ -161,6 +161,9 @@
return;
m_currentScrollPosition = adjustedScrollPosition(position, clamp);
+
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeScrollingNode " << scrollingNodeID() << " scrollTo " << position << " (delta from last committed position " << (m_lastCommittedScrollPosition - m_currentScrollPosition) << ")");
+
updateViewportForCurrentScrollPosition();
currentScrollPositionChanged();
}
Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm (243308 => 243309)
--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm 2019-03-21 18:57:09 UTC (rev 243308)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm 2019-03-21 18:58:09 UTC (rev 243309)
@@ -87,8 +87,6 @@
}
}
}
- LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: overflow delta " << scrollOffsetSinceLastCommit);
-
auto layerOffset = -scrollOffsetSinceLastCommit;
if (m_constraints.scrollPositioningBehavior() == ScrollPositioningBehavior::Stationary) {
// Stationary nodes move in the opposite direction.
@@ -96,6 +94,9 @@
}
FloatPoint layerPosition = m_constraints.layerPositionAtLastLayout() - layerOffset;
+
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: overflow delta " << scrollOffsetSinceLastCommit << " moving layer to " << layerPosition);
+
[m_layer _web_setLayerTopLeftPosition:layerPosition - m_constraints.alignmentOffset()];
// FIXME: Should our scroller deltas propagate to descendants?
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (243308 => 243309)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2019-03-21 18:57:09 UTC (rev 243308)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2019-03-21 18:58:09 UTC (rev 243309)
@@ -958,6 +958,7 @@
&& requiresCompositingForIndirectReason(layer.renderer(), compositingState.compositingAncestor, childState.subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) {
layer.setIndirectCompositingReason(indirectCompositingReason);
childState.compositingAncestor = &layer;
+ childState.subtreeIsCompositing = true;
overlapMap.pushCompositingContainer();
addToOverlapMapRecursive(overlapMap, layer);
willBeComposited = true;
@@ -968,10 +969,6 @@
layer.reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None);
}
- // Subsequent layers in the parent stacking context also need to composite.
- compositingState.subtreeIsCompositing |= childState.subtreeIsCompositing;
- compositingState.fullPaintOrderTraversalRequired |= childState.fullPaintOrderTraversalRequired;
-
// Set the flag to say that this layer has compositing children.
layer.setHasCompositingDescendant(childState.subtreeIsCompositing);
@@ -987,6 +984,7 @@
if (isCompositedClippingLayer) {
if (!willBeComposited) {
childState.compositingAncestor = &layer;
+ childState.subtreeIsCompositing = true;
overlapMap.pushCompositingContainer();
addToOverlapMapRecursive(overlapMap, layer);
willBeComposited = true;
@@ -994,8 +992,7 @@
}
#if ENABLE(CSS_COMPOSITING)
- if ((willBeComposited && layer.hasBlendMode())
- || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
+ if ((willBeComposited && layer.hasBlendMode()) || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
#endif
@@ -1013,7 +1010,11 @@
willBeComposited = false;
#endif
}
-
+
+ // Subsequent layers in the parent stacking context also need to composite.
+ compositingState.subtreeIsCompositing |= childState.subtreeIsCompositing;
+ compositingState.fullPaintOrderTraversalRequired |= childState.fullPaintOrderTraversalRequired;
+
ASSERT(willBeComposited == needsToBeComposited(layer, queryData));
// Create or destroy backing here. However, we can't update geometry because layers above us may become composited