Diff
Modified: trunk/LayoutTests/ChangeLog (246196 => 246197)
--- trunk/LayoutTests/ChangeLog 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/LayoutTests/ChangeLog 2019-06-07 14:17:49 UTC (rev 246197)
@@ -1,3 +1,18 @@
+2019-06-07 Antti Koivisto <an...@apple.com>
+
+ position:fixed inside overflow positioning nodes is jumpy
+ https://bugs.webkit.org/show_bug.cgi?id=198647
+ <rdar://problem/51514437>
+
+ Reviewed by Frédéric Wang.
+
+ * scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1-expected.html: Added.
+ * scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1.html: Added.
+ * scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2-expected.html: Added.
+ * scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2.html: Added.
+ * scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary-expected.html: Added.
+ * scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary.html: Added.
+
2019-06-07 Enrique Ocaña González <eoca...@igalia.com>
[MSE][GStreamer] Avoid QUOTA_EXCEEDED_ERR when seeking to a buffered range just before the buffered one
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1-expected.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1-expected.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1-expected.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,59 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ position: relative;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ margin: 40px;
+ border: 2px solid red;
+ height: 5000px;
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ await UIHelper.ensurePresentationUpdate();
+ document.querySelector('.scroller').scrollTo(0, 200);
+ await UIHelper.ensurePresentationUpdate();
+
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,57 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ position: relative;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ margin: 40px;
+ border: 2px solid red;
+ height: 5000px;
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ const scrollUpdatesDisabled = true;
+ await UIHelper.immediateScrollElementAtContentPointToOffset(50, 50, 0, 200, scrollUpdatesDisabled);
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2-expected.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2-expected.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2-expected.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,60 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ position: relative;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ margin: 40px;
+ border: 2px solid red;
+ height: 5000px;
+ will-change: transform;
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ await UIHelper.ensurePresentationUpdate();
+ document.querySelector('.scroller').scrollTo(0, 200);
+ await UIHelper.ensurePresentationUpdate();
+
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,58 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ position: relative;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ margin: 40px;
+ border: 2px solid red;
+ height: 5000px;
+ will-change: transform;
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ const scrollUpdatesDisabled = true;
+ await UIHelper.immediateScrollElementAtContentPointToOffset(50, 50, 0, 200, scrollUpdatesDisabled);
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary-expected.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary-expected.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary-expected.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,69 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ will-change: transform;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ top: 0px;
+ margin: 40px;
+ border: 2px solid red;
+ width: 200px;
+ height: 5000px;
+ position: absolute;
+ will-change: transform;
+ }
+ .spacer {
+ height: 1000px;
+ border: 2px solid blue;
+
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ await UIHelper.ensurePresentationUpdate();
+ document.querySelector('.scroller').scrollTo(0, 200);
+ await UIHelper.ensurePresentationUpdate();
+
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ <div class="spacer"></div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary.html (0 => 246197)
--- trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary.html (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary.html 2019-06-07 14:17:49 UTC (rev 246197)
@@ -0,0 +1,67 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true internal:AsyncOverflowScrollingEnabled=true internal:AsyncFrameScrollingEnabled=true ] -->
+<html>
+<head>
+ <meta name="viewport" content="initial-scale=1.0">
+ <style>
+ .scroller {
+ margin: 10px;
+ height: 300px;
+ width: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ will-change: transform;
+ }
+
+ .fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+
+ .container {
+ top: 0px;
+ margin: 40px;
+ border: 2px solid red;
+ width: 200px;
+ height: 5000px;
+ position: absolute;
+ will-change: transform;
+ }
+ .spacer {
+ height: 1000px;
+ border: 2px solid blue;
+
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+
+ async function doTest()
+ {
+ if (!window.testRunner)
+ return;
+
+ if (!testRunner.runUIScript)
+ return;
+
+ const scrollUpdatesDisabled = true;
+ await UIHelper.immediateScrollElementAtContentPointToOffset(50, 50, 0, 200, scrollUpdatesDisabled);
+ testRunner.notifyDone();
+ }
+
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+ <div class="scroller">
+ <div class="container">
+ <div class="fixed"></div>
+ </div>
+ <div class="spacer"></div>
+ </div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (246196 => 246197)
--- trunk/Source/WebCore/ChangeLog 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/ChangeLog 2019-06-07 14:17:49 UTC (rev 246197)
@@ -1,3 +1,32 @@
+2019-06-07 Antti Koivisto <an...@apple.com>
+
+ position:fixed inside overflow positioning nodes is jumpy
+ https://bugs.webkit.org/show_bug.cgi?id=198647
+ <rdar://problem/51514437>
+
+ Reviewed by Frédéric Wang.
+
+ Tests: scrollingcoordinator/ios/fixed-overflow-no-stacking-context-1.html
+ scrollingcoordinator/ios/fixed-overflow-no-stacking-context-2.html
+ scrollingcoordinator/ios/fixed-overflow-stacking-context-stationary.html
+
+ * page/scrolling/ScrollingTreeScrollingNode.h:
+ * page/scrolling/cocoa/ScrollingTreeFixedNode.mm:
+ (WebCore::ScrollingTreeFixedNode::applyLayerPositions):
+
+ Take deltas from positioning nodes into account.
+
+ * page/scrolling/cocoa/ScrollingTreePositionedNode.h:
+ * page/scrolling/cocoa/ScrollingTreePositionedNode.mm:
+ (WebCore::ScrollingTreePositionedNode::scrollDeltaSinceLastCommit const):
+
+ Rename since 'scrollOffset' has other meaning.
+
+ (WebCore::ScrollingTreePositionedNode::applyLayerPositions):
+ (WebCore::ScrollingTreePositionedNode::scrollOffsetSinceLastCommit const): Deleted.
+ * page/scrolling/cocoa/ScrollingTreeStickyNode.mm:
+ (WebCore::ScrollingTreeStickyNode::applyLayerPositions):
+
2019-06-07 Enrique Ocaña González <eoca...@igalia.com>
[MSE][GStreamer] Avoid QUOTA_EXCEEDED_ERR when seeking to a buffered range just before the buffered one
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (246196 => 246197)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2019-06-07 14:17:49 UTC (rev 246197)
@@ -55,6 +55,7 @@
FloatPoint currentScrollPosition() const { return m_currentScrollPosition; }
FloatPoint lastCommittedScrollPosition() const { return m_lastCommittedScrollPosition; }
+ FloatSize scrollDeltaSinceLastCommit() const { return m_currentScrollPosition - m_lastCommittedScrollPosition; }
// These are imperative; they adjust the scrolling layers.
void scrollTo(const FloatPoint&, ScrollType = ScrollType::User, ScrollPositionClamp = ScrollPositionClamp::ToContentEdges);
Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeFixedNode.mm (246196 => 246197)
--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeFixedNode.mm 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeFixedNode.mm 2019-06-07 14:17:49 UTC (rev 246197)
@@ -33,6 +33,7 @@
#import "ScrollingTree.h"
#import "ScrollingTreeFrameScrollingNode.h"
#import "ScrollingTreeOverflowScrollingNode.h"
+#import "ScrollingTreePositionedNode.h"
#import "WebCoreCALayerExtras.h"
#import <wtf/text/TextStream.h>
@@ -69,21 +70,24 @@
{
auto computeLayerPosition = [&] {
FloatSize overflowScrollDelta;
- // FIXME: This code is wrong in complex cases where the fixed element is inside a positioned node as
- // the scroll container order does not match the scrolling tree ancestor order.
- for (auto* node = parent(); node; node = node->parent()) {
- if (is<ScrollingTreeFrameScrollingNode>(*node)) {
+ for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+ if (is<ScrollingTreePositionedNode>(*ancestor)) {
+ auto& positioningAncestor = downcast<ScrollingTreePositionedNode>(*ancestor);
+ if (positioningAncestor.layer() != m_layer)
+ overflowScrollDelta -= positioningAncestor.scrollDeltaSinceLastCommit();
+ }
+
+ if (is<ScrollingTreeFrameScrollingNode>(*ancestor)) {
// Fixed nodes are positioned relative to the containing frame scrolling node.
// We bail out after finding one.
- auto layoutViewport = downcast<ScrollingTreeFrameScrollingNode>(*node).layoutViewport();
+ auto layoutViewport = downcast<ScrollingTreeFrameScrollingNode>(*ancestor).layoutViewport();
return m_constraints.layerPositionForViewportRect(layoutViewport) - overflowScrollDelta;
}
- if (is<ScrollingTreeOverflowScrollingNode>(*node)) {
+ if (is<ScrollingTreeOverflowScrollingNode>(*ancestor)) {
// To keep the layer still during async scrolling we adjust by how much the position has changed since layout.
- auto& overflowNode = downcast<ScrollingTreeOverflowScrollingNode>(*node);
- auto localDelta = overflowNode.lastCommittedScrollPosition() - overflowNode.currentScrollPosition();
- overflowScrollDelta += localDelta;
+ auto& overflowNode = downcast<ScrollingTreeOverflowScrollingNode>(*ancestor);
+ overflowScrollDelta -= overflowNode.scrollDeltaSinceLastCommit();
}
}
ASSERT_NOT_REACHED();
Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h (246196 => 246197)
--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h 2019-06-07 14:17:49 UTC (rev 246197)
@@ -46,7 +46,7 @@
ScrollPositioningBehavior scrollPositioningBehavior() const { return m_constraints.scrollPositioningBehavior(); }
const Vector<ScrollingNodeID>& relatedOverflowScrollingNodes() const { return m_relatedOverflowScrollingNodes; }
- FloatSize scrollOffsetSinceLastCommit() const;
+ FloatSize scrollDeltaSinceLastCommit() const;
private:
ScrollingTreePositionedNode(ScrollingTree&, ScrollingNodeID);
Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm (246196 => 246197)
--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm 2019-06-07 14:17:49 UTC (rev 246197)
@@ -76,31 +76,31 @@
scrollingTree().positionedNodesWithRelatedOverflow().add(scrollingNodeID());
}
-FloatSize ScrollingTreePositionedNode::scrollOffsetSinceLastCommit() const
+FloatSize ScrollingTreePositionedNode::scrollDeltaSinceLastCommit() const
{
- FloatSize offset;
+ FloatSize delta;
for (auto nodeID : m_relatedOverflowScrollingNodes) {
if (auto* node = scrollingTree().nodeForID(nodeID)) {
if (is<ScrollingTreeOverflowScrollingNode>(node)) {
auto& overflowNode = downcast<ScrollingTreeOverflowScrollingNode>(*node);
- offset += overflowNode.currentScrollPosition() - overflowNode.lastCommittedScrollPosition();
+ delta += overflowNode.scrollDeltaSinceLastCommit();
}
}
}
if (m_constraints.scrollPositioningBehavior() == ScrollPositioningBehavior::Stationary) {
// Stationary nodes move in the opposite direction.
- return -offset;
+ return -delta;
}
- return offset;
+ return delta;
}
void ScrollingTreePositionedNode::applyLayerPositions()
{
- auto offset = scrollOffsetSinceLastCommit();
- auto layerPosition = m_constraints.layerPositionAtLastLayout() - offset;
+ auto delta = scrollDeltaSinceLastCommit();
+ auto layerPosition = m_constraints.layerPositionAtLastLayout() - delta;
- LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: overflow delta " << offset << " moving layer to " << layerPosition);
+ LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: overflow delta " << delta << " moving layer to " << layerPosition);
[m_layer _web_setLayerTopLeftPosition:layerPosition - m_constraints.alignmentOffset()];
}
Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeStickyNode.mm (246196 => 246197)
--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeStickyNode.mm 2019-06-07 14:12:05 UTC (rev 246196)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreeStickyNode.mm 2019-06-07 14:17:49 UTC (rev 246197)
@@ -97,7 +97,7 @@
if (positioningAncestor.layer() == m_layer) {
// We'll also do the adjustment the positioning node would do.
- position -= positioningAncestor.scrollOffsetSinceLastCommit();
+ position -= positioningAncestor.scrollDeltaSinceLastCommit();
}
return position;