Fixed elements no longer stay fixed with elastic overscroll
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jan 2020 21:51:37 +0000 (21:51 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jan 2020 21:51:37 +0000 (21:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=206227
rdar://problem/58707084

Reviewed by Antti Koivisto.
Source/WebCore:

Intended behavior on iOS and macOS is for position:fixed and sticky elements to maintain
their position relative to the view bounds when rubber-banding ("overscrolling"). This broke
some time back. This change restores the correct behavior with the call to layoutViewportRespectingRubberBanding()
in ScrollingTreeFixedNode::applyLayerPositions() and ScrollingTreeStickyNode::computeLayerPosition().
layoutViewportRespectingRubberBanding() computes a layout viewport without clamping.

The rest of the changes are to support testing. internals.unconstrainedScrollTo()
didn't work for main frame scrolling because of scroll position clamping in various places,
so propagate ScrollClamping in more places (and replace the redundant ScrollPositionClamp with ScrollClamping).

"requested scroll position" updates now carry along both clamping and "is programmatic" data, wrapped in a struct
which is passed around the scrolling tree. This allows us to not clamp the scroll position (for testing) in more places.

Internals::unconstrainedScrollTo() needs one weird hack to trigger a layout (and thus a scrolling tree commit),
because the layout is normally triggered by a layout viewport change, but when rubber-banding we clamp the layoutViewport
used for layout, so those layouts are never triggered.

Tests: tiled-drawing/scrolling/fixed/fixed-during-rubberband.html
       tiled-drawing/scrolling/sticky/sticky-during-rubberband.html

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Element.cpp:
(WebCore::Element::scrollTo):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::scrollTo const):
* page/FrameView.cpp:
(WebCore::FrameView::setScrollPosition):
(WebCore::FrameView::requestScrollPositionUpdate):
* page/FrameView.h:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
* page/scrolling/AsyncScrollingCoordinator.h:
* page/scrolling/ScrollingCoordinator.cpp:
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::requestScrollPositionUpdate):
* page/scrolling/ScrollingStateScrollingNode.cpp:
(WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
(WebCore::ScrollingStateScrollingNode::setRequestedScrollData):
(WebCore::ScrollingStateScrollingNode::dumpProperties const):
(WebCore::ScrollingStateScrollingNode::setRequestedScrollPosition): Deleted.
* page/scrolling/ScrollingStateScrollingNode.h:
(WebCore::RequestedScrollData::operator== const):
(WebCore::ScrollingStateScrollingNode::requestedScrollData const):
(WebCore::ScrollingStateScrollingNode::requestedScrollPosition const): Deleted.
(WebCore::ScrollingStateScrollingNode::requestedScrollPositionRepresentsProgrammaticScroll const): Deleted.
* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::scrollingTreeNodeRequestsScroll):
* page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
(WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition const):
(WebCore::ScrollingTreeFrameScrollingNode::layoutViewportRespectingRubberBanding const):
* page/scrolling/ScrollingTreeFrameScrollingNode.h:
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::commitStateAfterChildren):
(WebCore::ScrollingTreeScrollingNode::adjustedScrollPosition const):
(WebCore::ScrollingTreeScrollingNode::scrollBy):
(WebCore::ScrollingTreeScrollingNode::scrollTo):
(WebCore::ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling):
* page/scrolling/ScrollingTreeScrollingNode.h:
* page/scrolling/cocoa/ScrollingTreeFixedNode.mm:
(WebCore::ScrollingTreeFixedNode::applyLayerPositions):
* page/scrolling/cocoa/ScrollingTreeStickyNode.mm:
(WebCore::ScrollingTreeStickyNode::computeLayerPosition const):
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::commitStateAfterChildren):
(WebCore::ScrollingTreeFrameScrollingNodeMac::adjustedScrollPosition const):
* page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
* page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
(WebCore::ScrollingTreeOverflowScrollingNodeMac::commitStateAfterChildren):
(WebCore::ScrollingTreeOverflowScrollingNodeMac::adjustedScrollPosition const):
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
(WebCore::ScrollingTreeScrollingNodeDelegateMac::immediateScrollByWithoutContentEdgeConstraints):
* platform/ScrollTypes.cpp: Added.
(WebCore::operator<<):
* platform/ScrollTypes.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::setContentsScrollPosition):
(WebCore::ScrollView::setScrollPosition):
* platform/ScrollView.h:
* platform/ScrollableArea.cpp:
(WebCore::ScrollableArea::setScrollOffsetFromAnimation):
* platform/ScrollableArea.h:
(WebCore::ScrollableArea::requestScrollPositionUpdate):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollToOffset):
* testing/Internals.cpp:
(WebCore::Internals::unconstrainedScrollTo):

Source/WebKit:

Intended behavior on iOS and macOS is for position:fixed and sticky elements to maintain
their position relative to the view bounds when rubber-banding ("overscrolling"). This broke
some time back. This change restores the correct behavior with the call to layoutViewportRespectingRubberBanding()
in ScrollingTreeFixedNode::applyLayerPositions() and ScrollingTreeStickyNode::computeLayerPosition().
layoutViewportRespectingRubberBanding() computes a layout viewport without clamping.

The rest of the changes are to support testing. internals.unconstrainedScrollTo()
didn't work for main frame scrolling because of scroll position clamping in various places,
so propagate ScrollClamping in more places (and replace the redundant ScrollPositionClamp with ScrollClamping).

"requested scroll position" updates now carry along both clamping and "is programmatic" data, wrapped in a struct
which is passed around the scrolling tree. This allows us to not clamp the scroll position (for testing) in more places.

* Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp:
(ArgumentCoder<ScrollingStateScrollingNode>::encode):
(ArgumentCoder<ScrollingStateScrollingNode>::decode):
(ArgumentCoder<RequestedScrollData>::encode):
(ArgumentCoder<RequestedScrollData>::decode):
(WebKit::dump):
* UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp:
(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll):
* UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
* UIProcess/RemoteLayerTree/RemoteScrollingTree.cpp:
(WebKit::RemoteScrollingTree::scrollingTreeNodeRequestsScroll):
* UIProcess/RemoteLayerTree/RemoteScrollingTree.h:
* UIProcess/RemoteLayerTree/ios/ScrollingTreeFrameScrollingNodeRemoteIOS.mm:
(WebKit::ScrollingTreeFrameScrollingNodeRemoteIOS::commitStateAfterChildren):
* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren):

LayoutTests:

* tiled-drawing/scrolling/fixed/fixed-during-rubberband-expected.html: Added.
* tiled-drawing/scrolling/fixed/fixed-during-rubberband.html: Added.
* tiled-drawing/scrolling/sticky/sticky-during-rubberband-expected.html: Added.
* tiled-drawing/scrolling/sticky/sticky-during-rubberband.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@255037 268f45cc-cd09-0410-ab3c-d52691b4dbfc

50 files changed:
LayoutTests/ChangeLog
LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband-expected.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband-expected.html [new file with mode: 0644]
LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Element.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
Source/WebCore/page/scrolling/ScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h
Source/WebCore/page/scrolling/ScrollingTree.h
Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.h
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
Source/WebCore/page/scrolling/cocoa/ScrollingTreeFixedNode.mm
Source/WebCore/page/scrolling/cocoa/ScrollingTreeStickyNode.mm
Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h
Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm
Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h
Source/WebCore/page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm
Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm
Source/WebCore/page/scrolling/nicosia/ScrollingTreeFrameScrollingNodeNicosia.cpp
Source/WebCore/page/scrolling/nicosia/ScrollingTreeFrameScrollingNodeNicosia.h
Source/WebCore/page/scrolling/nicosia/ScrollingTreeOverflowScrollingNodeNicosia.cpp
Source/WebCore/page/scrolling/nicosia/ScrollingTreeOverflowScrollingNodeNicosia.h
Source/WebCore/platform/ScrollTypes.cpp [new file with mode: 0644]
Source/WebCore/platform/ScrollTypes.h
Source/WebCore/platform/ScrollView.cpp
Source/WebCore/platform/ScrollView.h
Source/WebCore/platform/ScrollableArea.cpp
Source/WebCore/platform/ScrollableArea.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/testing/Internals.cpp
Source/WebKit/ChangeLog
Source/WebKit/Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp
Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp
Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.cpp
Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.h
Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeFrameScrollingNodeRemoteIOS.mm
Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm

index 083b223..485a139 100644 (file)
 
         * http/wpt/webauthn/public-key-credential-create-failure-local.https.html:
 
+2020-01-22  Simon Fraser  <simon.fraser@apple.com>
+
+        Fixed elements no longer stay fixed with elastic overscroll
+        https://bugs.webkit.org/show_bug.cgi?id=206227
+        rdar://problem/58707084
+
+        Reviewed by Antti Koivisto.
+
+        * tiled-drawing/scrolling/fixed/fixed-during-rubberband-expected.html: Added.
+        * tiled-drawing/scrolling/fixed/fixed-during-rubberband.html: Added.
+        * tiled-drawing/scrolling/sticky/sticky-during-rubberband-expected.html: Added.
+        * tiled-drawing/scrolling/sticky/sticky-during-rubberband.html: Added.
+
 2020-01-21  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r254807 and r254849.
         https://bugs.webkit.org/show_bug.cgi?id=206559
 
-        Broke page up/page down on macOW (Requested by smfr on
+        Broke page up/page down on macOS (Requested by smfr on
         #webkit).
 
         Reverted changesets:
diff --git a/LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband-expected.html b/LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband-expected.html
new file mode 100644 (file)
index 0000000..7ae5ab6
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            margin: 0;
+        }
+        .fixed {
+            position: absolute;
+            top: 100px;
+            height: 200px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script>
+        window.addEventListener('load', () => {
+            internals.unconstrainedScrollTo(document.scrollingElement, 0, -100);
+        }, false);
+    </script>
+</head>
+<body>
+
+<div class="fixed"></div>
+
+</body>
+</html>
diff --git a/LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband.html b/LayoutTests/tiled-drawing/scrolling/fixed/fixed-during-rubberband.html
new file mode 100644 (file)
index 0000000..23ddf43
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            margin: 0;
+        }
+        .fixed {
+            position: fixed;
+            top: 200px;
+            height: 200px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script>
+        window.addEventListener('load', () => {
+            internals.unconstrainedScrollTo(document.scrollingElement, 0, -100);
+        }, false);
+    </script>
+</head>
+<body>
+
+<div class="fixed"></div>
+
+</body>
+</html>
diff --git a/LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband-expected.html b/LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband-expected.html
new file mode 100644 (file)
index 0000000..286d31c
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            margin: 0;
+        }
+        
+        .sticky-container {
+            border: 1px solid black;
+            height: 400px;
+            width: 80%;
+            margin-top: -10px;
+        }
+
+        .sticky {
+            position: relative;
+            top: 0px;
+            height: 200px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script>
+        window.addEventListener('load', () => {
+            internals.unconstrainedScrollTo(document.scrollingElement, 0, -10);
+        }, false);
+    </script>
+</head>
+<body>
+
+<div class="sticky-container">
+    <div class="sticky"></div>    
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband.html b/LayoutTests/tiled-drawing/scrolling/sticky/sticky-during-rubberband.html
new file mode 100644 (file)
index 0000000..457e9fe
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            margin: 0;
+        }
+        
+        .sticky-container {
+            border: 1px solid black;
+            height: 400px;
+            width: 80%;
+            margin-top: -10px;
+        }
+
+        .sticky {
+            position: sticky;
+            top: 0px;
+            height: 200px;
+            width: 100%;
+            background-color: green;
+        }
+    </style>
+    <script>
+        window.addEventListener('load', () => {
+            internals.unconstrainedScrollTo(document.scrollingElement, 0, -10);
+        }, false);
+    </script>
+</head>
+<body>
+
+<div class="sticky-container">
+    <div class="sticky"></div>    
+</div>
+
+</body>
+</html>
index 62b2904..bf2bc56 100644 (file)
         * svg/graphics/SVGImage.cpp:
         (WebCore::SVGImage::nativeImageForCurrentFrame):
 
+2020-01-22  Simon Fraser  <simon.fraser@apple.com>
+
+        Fixed elements no longer stay fixed with elastic overscroll
+        https://bugs.webkit.org/show_bug.cgi?id=206227
+        rdar://problem/58707084
+
+        Reviewed by Antti Koivisto.
+        
+        Intended behavior on iOS and macOS is for position:fixed and sticky elements to maintain
+        their position relative to the view bounds when rubber-banding ("overscrolling"). This broke
+        some time back. This change restores the correct behavior with the call to layoutViewportRespectingRubberBanding()
+        in ScrollingTreeFixedNode::applyLayerPositions() and ScrollingTreeStickyNode::computeLayerPosition().
+        layoutViewportRespectingRubberBanding() computes a layout viewport without clamping.
+
+        The rest of the changes are to support testing. internals.unconstrainedScrollTo()
+        didn't work for main frame scrolling because of scroll position clamping in various places,
+        so propagate ScrollClamping in more places (and replace the redundant ScrollPositionClamp with ScrollClamping).
+
+        "requested scroll position" updates now carry along both clamping and "is programmatic" data, wrapped in a struct
+        which is passed around the scrolling tree. This allows us to not clamp the scroll position (for testing) in more places.
+        
+        Internals::unconstrainedScrollTo() needs one weird hack to trigger a layout (and thus a scrolling tree commit),
+        because the layout is normally triggered by a layout viewport change, but when rubber-banding we clamp the layoutViewport
+        used for layout, so those layouts are never triggered.
+
+        Tests: tiled-drawing/scrolling/fixed/fixed-during-rubberband.html
+               tiled-drawing/scrolling/sticky/sticky-during-rubberband.html
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Element.cpp:
+        (WebCore::Element::scrollTo):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::scrollTo const):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::setScrollPosition):
+        (WebCore::FrameView::requestScrollPositionUpdate):
+        * page/FrameView.h:
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
+        * page/scrolling/AsyncScrollingCoordinator.h:
+        * page/scrolling/ScrollingCoordinator.cpp:
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::requestScrollPositionUpdate):
+        * page/scrolling/ScrollingStateScrollingNode.cpp:
+        (WebCore::ScrollingStateScrollingNode::ScrollingStateScrollingNode):
+        (WebCore::ScrollingStateScrollingNode::setRequestedScrollData):
+        (WebCore::ScrollingStateScrollingNode::dumpProperties const):
+        (WebCore::ScrollingStateScrollingNode::setRequestedScrollPosition): Deleted.
+        * page/scrolling/ScrollingStateScrollingNode.h:
+        (WebCore::RequestedScrollData::operator== const):
+        (WebCore::ScrollingStateScrollingNode::requestedScrollData const):
+        (WebCore::ScrollingStateScrollingNode::requestedScrollPosition const): Deleted.
+        (WebCore::ScrollingStateScrollingNode::requestedScrollPositionRepresentsProgrammaticScroll const): Deleted.
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::scrollingTreeNodeRequestsScroll):
+        * page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
+        (WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition const):
+        (WebCore::ScrollingTreeFrameScrollingNode::layoutViewportRespectingRubberBanding const):
+        * page/scrolling/ScrollingTreeFrameScrollingNode.h:
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::commitStateAfterChildren):
+        (WebCore::ScrollingTreeScrollingNode::adjustedScrollPosition const):
+        (WebCore::ScrollingTreeScrollingNode::scrollBy):
+        (WebCore::ScrollingTreeScrollingNode::scrollTo):
+        (WebCore::ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        * page/scrolling/cocoa/ScrollingTreeFixedNode.mm:
+        (WebCore::ScrollingTreeFixedNode::applyLayerPositions):
+        * page/scrolling/cocoa/ScrollingTreeStickyNode.mm:
+        (WebCore::ScrollingTreeStickyNode::computeLayerPosition const):
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::commitStateAfterChildren):
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::adjustedScrollPosition const):
+        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.h:
+        * page/scrolling/mac/ScrollingTreeOverflowScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeOverflowScrollingNodeMac::commitStateAfterChildren):
+        (WebCore::ScrollingTreeOverflowScrollingNodeMac::adjustedScrollPosition const):
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::immediateScrollByWithoutContentEdgeConstraints):
+        * platform/ScrollTypes.cpp: Added.
+        (WebCore::operator<<):
+        * platform/ScrollTypes.h:
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::setContentsScrollPosition):
+        (WebCore::ScrollView::setScrollPosition):
+        * platform/ScrollView.h:
+        * platform/ScrollableArea.cpp:
+        (WebCore::ScrollableArea::setScrollOffsetFromAnimation):
+        * platform/ScrollableArea.h:
+        (WebCore::ScrollableArea::requestScrollPositionUpdate):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::scrollToOffset):
+        * testing/Internals.cpp:
+        (WebCore::Internals::unconstrainedScrollTo):
+
 2020-01-21  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r254807 and r254849.
         https://bugs.webkit.org/show_bug.cgi?id=206559
 
-        Broke page up/page down on macOW (Requested by smfr on
+        Broke page up/page down on macOS (Requested by smfr on
         #webkit).
 
         Reverted changesets:
index f675801..efb3aee 100644 (file)
@@ -1763,6 +1763,7 @@ platform/RemoteCommandListener.cpp
 platform/RuntimeApplicationChecks.cpp
 platform/SSLKeyGenerator.cpp
 platform/ScrollAnimator.cpp
+platform/ScrollTypes.cpp
 platform/ScrollView.cpp
 platform/ScrollableArea.cpp
 platform/Scrollbar.cpp
index 1f3d7ea..672f1cf 100644 (file)
                0F4966A71DB40C4300A274BB /* JSDOMPointInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMPointInit.h; sourceTree = "<group>"; };
                0F4966A81DB40C4300A274BB /* JSDOMPointReadOnly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMPointReadOnly.cpp; sourceTree = "<group>"; };
                0F4966A91DB40C4300A274BB /* JSDOMPointReadOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMPointReadOnly.h; sourceTree = "<group>"; };
+               0F4CDEAA23D91A8A00251B02 /* ScrollTypes.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollTypes.cpp; sourceTree = "<group>"; };
                0F53FB81213B1BB800C40D34 /* CSSFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFilter.cpp; sourceTree = "<group>"; };
                0F53FB83213B1BB800C40D34 /* CSSFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFilter.h; sourceTree = "<group>"; };
                0F53FB89213B768400C40D34 /* RenderLayerFilters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderLayerFilters.h; sourceTree = "<group>"; };
                                BC8B854A0E7C7F5600AB6984 /* ScrollbarTheme.h */,
                                BC1402880E83680800319717 /* ScrollbarThemeComposite.cpp */,
                                BC1402890E83680800319717 /* ScrollbarThemeComposite.h */,
+                               0F4CDEAA23D91A8A00251B02 /* ScrollTypes.cpp */,
                                93C09C850B0657AA005ABD4D /* ScrollTypes.h */,
                                BC2441C30E8B65D00055320F /* ScrollView.cpp */,
                                BC6D6E2509AF943500F59759 /* ScrollView.h */,
index ff98eee..f69c597 100644 (file)
@@ -942,7 +942,7 @@ void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping)
         if (!window)
             return;
 
-        window->scrollTo(options);
+        window->scrollTo(options, clamping);
         return;
     }
 
index 2fc19df..463895b 100644 (file)
@@ -1698,7 +1698,7 @@ void DOMWindow::scrollTo(double x, double y, ScrollClamping clamping) const
     scrollTo({ x, y }, clamping);
 }
 
-void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping) const
+void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping clamping) const
 {
     if (!isCurrentlyDisplayedInFrame())
         return;
@@ -1717,7 +1717,7 @@ void DOMWindow::scrollTo(const ScrollToOptions& options, ScrollClamping) const
     document()->updateLayoutIgnorePendingStylesheets();
 
     IntPoint layoutPos(view->mapFromCSSToLayoutUnits(scrollToOptions.left.value()), view->mapFromCSSToLayoutUnits(scrollToOptions.top.value()));
-    view->setContentsScrollPosition(layoutPos);
+    view->setContentsScrollPosition(layoutPos, clamping);
 }
 
 bool DOMWindow::allowedToChangeWindowGeometry() const
index 225a5da..5705a60 100644 (file)
@@ -2279,7 +2279,7 @@ void FrameView::scrollElementToRect(const Element& element, const IntRect& rect)
     setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
 }
 
-void FrameView::setScrollPosition(const ScrollPosition& scrollPosition)
+void FrameView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping)
 {
     LOG_WITH_STREAM(Scrolling, stream << "FrameView::setScrollPosition " << scrollPosition << " , clearing anchor");
 
@@ -2292,7 +2292,7 @@ void FrameView::setScrollPosition(const ScrollPosition& scrollPosition)
     Page* page = frame().page();
     if (page && page->isMonitoringWheelEvents())
         scrollAnimator().setWheelEventTestMonitor(page->wheelEventTestMonitor());
-    ScrollView::setScrollPosition(scrollPosition);
+    ScrollView::setScrollPosition(scrollPosition, clamping);
 
     setCurrentScrollType(oldScrollType);
 }
@@ -2616,7 +2616,7 @@ bool FrameView::isRubberBandInProgress() const
     return false;
 }
 
-bool FrameView::requestScrollPositionUpdate(const ScrollPosition& position)
+bool FrameView::requestScrollPositionUpdate(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping)
 {
     LOG_WITH_STREAM(Scrolling, stream << "FrameView::requestScrollPositionUpdate " << position);
 
@@ -2628,7 +2628,7 @@ bool FrameView::requestScrollPositionUpdate(const ScrollPosition& position)
 #if ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
     if (Page* page = frame().page()) {
         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-            return scrollingCoordinator->requestScrollPositionUpdate(*this, position);
+            return scrollingCoordinator->requestScrollPositionUpdate(*this, position, scrollType, clamping);
     }
 #else
     UNUSED_PARAM(position);
index f34940d..4fcb311 100644 (file)
@@ -117,7 +117,7 @@ public:
     void setNeedsCompositingConfigurationUpdate();
     void setNeedsCompositingGeometryUpdate();
 
-    void setViewportConstrainedObjectsNeedLayout();
+    WEBCORE_EXPORT void setViewportConstrainedObjectsNeedLayout();
 
     WEBCORE_EXPORT bool renderedCharactersExceed(unsigned threshold);
 
@@ -223,13 +223,13 @@ public:
 #if USE(COORDINATED_GRAPHICS)
     WEBCORE_EXPORT void setFixedVisibleContentRect(const IntRect&) final;
 #endif
-    WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&) final;
+    WEBCORE_EXPORT void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped) final;
     void restoreScrollbar();
     void scheduleScrollToFocusedElement(SelectionRevealMode);
     void scrollToFocusedElementImmediatelyIfNeeded();
     void updateLayerPositionsAfterScrolling() final;
     void updateCompositingLayersAfterScrolling() final;
-    bool requestScrollPositionUpdate(const ScrollPosition&) final;
+    bool requestScrollPositionUpdate(const ScrollPosition&, ScrollType = ScrollType::User, ScrollClamping = ScrollClamping::Clamped) final;
     bool isRubberBandInProgress() const final;
     WEBCORE_EXPORT ScrollPosition minimumScrollPosition() const final;
     WEBCORE_EXPORT ScrollPosition maximumScrollPosition() const final;
index 429eee9..7aa75bd 100644 (file)
@@ -230,7 +230,7 @@ void AsyncScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView
     node->setHorizontalScrollbarLayer(frameView.layerForHorizontalScrollbar());
 }
 
-bool AsyncScrollingCoordinator::requestScrollPositionUpdate(ScrollableArea& scrollableArea, const IntPoint& scrollPosition)
+bool AsyncScrollingCoordinator::requestScrollPositionUpdate(ScrollableArea& scrollableArea, const IntPoint& scrollPosition, ScrollType scrollType, ScrollClamping clamping)
 {
     ASSERT(isMainThread());
     ASSERT(m_page);
@@ -251,6 +251,8 @@ bool AsyncScrollingCoordinator::requestScrollPositionUpdate(ScrollableArea& scro
     if (inProgrammaticScroll || inBackForwardCache)
         updateScrollPositionAfterAsyncScroll(scrollingNodeID, scrollPosition, { }, ScrollType::Programmatic, ScrollingLayerPositionAction::Set);
 
+    ASSERT(inProgrammaticScroll == (scrollType == ScrollType::Programmatic));
+
     // If this frame view's document is being put into the back/forward cache, we don't want to update our
     // main frame scroll position. Just let the FrameView think that we did.
     if (inBackForwardCache)
@@ -260,7 +262,7 @@ bool AsyncScrollingCoordinator::requestScrollPositionUpdate(ScrollableArea& scro
     if (!stateNode)
         return false;
 
-    stateNode->setRequestedScrollPosition(scrollPosition, inProgrammaticScroll);
+    stateNode->setRequestedScrollData({ scrollPosition, scrollType, clamping });
     return true;
 }
 
index 9be69aa..a68442c 100644 (file)
@@ -98,7 +98,7 @@ private:
     WEBCORE_EXPORT void frameViewVisualViewportChanged(FrameView&) override;
     WEBCORE_EXPORT void frameViewEventTrackingRegionsChanged(FrameView&) override;
 
-    WEBCORE_EXPORT bool requestScrollPositionUpdate(ScrollableArea&, const IntPoint&) override;
+    WEBCORE_EXPORT bool requestScrollPositionUpdate(ScrollableArea&, const IntPoint&, ScrollType, ScrollClamping) override;
 
     WEBCORE_EXPORT void applyScrollingTreeLayerPositions() override;
 
index 85cfc5e..a70b8e6 100644 (file)
@@ -498,13 +498,4 @@ TextStream& operator<<(TextStream& ts, ViewportRectStability stability)
     return ts;
 }
 
-TextStream& operator<<(TextStream& ts, ScrollType scrollType)
-{
-    switch (scrollType) {
-    case ScrollType::User: ts << "user"; break;
-    case ScrollType::Programmatic: ts << "programmatic"; break;
-    }
-    return ts;
-}
-
 } // namespace WebCore
index 095a929..aee2f96 100644 (file)
@@ -121,7 +121,7 @@ public:
 
     // These virtual functions are currently unique to the threaded scrolling architecture. 
     virtual void commitTreeStateIfNeeded() { }
-    virtual bool requestScrollPositionUpdate(ScrollableArea&, const IntPoint&) { return false; }
+    virtual bool requestScrollPositionUpdate(ScrollableArea&, const IntPoint&, ScrollType = ScrollType::Programmatic, ScrollClamping = ScrollClamping::Clamped) { return false; }
     virtual ScrollingEventResult handleWheelEvent(FrameView&, const PlatformWheelEvent&) { return ScrollingEventResult::DidNotHandleEvent; }
 
     // Create an unparented node.
@@ -221,7 +221,6 @@ WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollableAreaParam
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollingNodeType);
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollingLayerPositionAction);
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ViewportRectStability);
-WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollType);
 
 } // namespace WebCore
 
index 717bfc2..92fbebc 100644 (file)
@@ -45,7 +45,6 @@ ScrollingStateScrollingNode::ScrollingStateScrollingNode(const ScrollingStateScr
     , m_reachableContentsSize(stateNode.reachableContentsSize())
     , m_parentRelativeScrollableRect(stateNode.parentRelativeScrollableRect())
     , m_scrollPosition(stateNode.scrollPosition())
-    , m_requestedScrollPosition(stateNode.requestedScrollPosition())
     , m_scrollOrigin(stateNode.scrollOrigin())
 #if ENABLE(CSS_SCROLL_SNAP)
     , m_snapOffsetsInfo(stateNode.m_snapOffsetsInfo)
@@ -55,7 +54,7 @@ ScrollingStateScrollingNode::ScrollingStateScrollingNode(const ScrollingStateScr
     , m_horizontalScrollerImp(stateNode.horizontalScrollerImp())
 #endif
     , m_scrollableAreaParameters(stateNode.scrollableAreaParameters())
-    , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
+    , m_requestedScrollData(stateNode.requestedScrollData())
     , m_isMonitoringWheelEvents(stateNode.isMonitoringWheelEvents())
 {
     if (hasChangedProperty(ScrollContainerLayer))
@@ -219,10 +218,12 @@ void ScrollingStateScrollingNode::setScrollableAreaParameters(const ScrollableAr
     setPropertyChanged(ScrollableAreaParams);
 }
 
-void ScrollingStateScrollingNode::setRequestedScrollPosition(const FloatPoint& requestedScrollPosition, bool representsProgrammaticScroll)
+void ScrollingStateScrollingNode::setRequestedScrollData(const RequestedScrollData& scrollData)
 {
-    m_requestedScrollPosition = requestedScrollPosition;
-    m_requestedScrollPositionRepresentsProgrammaticScroll = representsProgrammaticScroll;
+    if (scrollData == m_requestedScrollData)
+        return;
+
+    m_requestedScrollData = scrollData;
     setPropertyChanged(RequestedScrollPosition);
 }
 
@@ -305,14 +306,17 @@ void ScrollingStateScrollingNode::dumpProperties(TextStream& ts, ScrollingStateT
     if (m_reachableContentsSize != m_totalContentsSize)
         ts.dumpProperty("reachable contents size", m_reachableContentsSize);
 
-    if (m_requestedScrollPosition != IntPoint()) {
+    if (!m_requestedScrollData.scrollPosition.isZero()) {
         TextStream::GroupScope scope(ts);
         ts << "requested scroll position "
-            << TextStream::FormatNumberRespectingIntegers(m_requestedScrollPosition.x()) << " "
-            << TextStream::FormatNumberRespectingIntegers(m_requestedScrollPosition.y());
+            << TextStream::FormatNumberRespectingIntegers(m_requestedScrollData.scrollPosition.x()) << " "
+            << TextStream::FormatNumberRespectingIntegers(m_requestedScrollData.scrollPosition.y());
     }
-    if (m_requestedScrollPositionRepresentsProgrammaticScroll)
-        ts.dumpProperty("requested scroll position represents programmatic scroll", m_requestedScrollPositionRepresentsProgrammaticScroll);
+    if (m_requestedScrollData.scrollType == ScrollType::Programmatic)
+        ts.dumpProperty("requested scroll position represents programmatic scroll", true);
+
+    if (m_requestedScrollData.clamping == ScrollClamping::Unclamped)
+        ts.dumpProperty("requested scroll position clamping", m_requestedScrollData.clamping);
 
     if (!m_parentRelativeScrollableRect.isEmpty())
         ts.dumpProperty("parent relative scrollable rect", m_parentRelativeScrollableRect);
index 4967a6c..eb56fe5 100644 (file)
@@ -38,6 +38,19 @@ OBJC_CLASS NSScrollerImp;
 
 namespace WebCore {
 
+struct RequestedScrollData {
+    FloatPoint scrollPosition;
+    ScrollType scrollType { ScrollType::User };
+    ScrollClamping clamping { ScrollClamping::Clamped };
+    
+    bool operator==(const RequestedScrollData& other) const
+    {
+        return scrollPosition == other.scrollPosition
+            && scrollType == other.scrollType
+            && clamping == other.clamping;
+    }
+};
+
 class ScrollingStateScrollingNode : public ScrollingStateNode {
 public:
     virtual ~ScrollingStateScrollingNode();
@@ -109,9 +122,8 @@ public:
     const ScrollableAreaParameters& scrollableAreaParameters() const { return m_scrollableAreaParameters; }
     WEBCORE_EXPORT void setScrollableAreaParameters(const ScrollableAreaParameters& params);
 
-    const FloatPoint& requestedScrollPosition() const { return m_requestedScrollPosition; }
-    bool requestedScrollPositionRepresentsProgrammaticScroll() const { return m_requestedScrollPositionRepresentsProgrammaticScroll; }
-    WEBCORE_EXPORT void setRequestedScrollPosition(const FloatPoint&, bool representsProgrammaticScroll);
+    const RequestedScrollData& requestedScrollData() const { return m_requestedScrollData; }
+    WEBCORE_EXPORT void setRequestedScrollData(const RequestedScrollData&);
 
     bool isMonitoringWheelEvents() const { return m_isMonitoringWheelEvents; }
     WEBCORE_EXPORT void setIsMonitoringWheelEvents(bool);
@@ -149,7 +161,6 @@ private:
     FloatSize m_reachableContentsSize;
     LayoutRect m_parentRelativeScrollableRect;
     FloatPoint m_scrollPosition;
-    FloatPoint m_requestedScrollPosition;
     IntPoint m_scrollOrigin;
 
 #if ENABLE(CSS_SCROLL_SNAP)
@@ -169,8 +180,8 @@ private:
 #endif
 
     ScrollableAreaParameters m_scrollableAreaParameters;
+    RequestedScrollData m_requestedScrollData;
 
-    bool m_requestedScrollPositionRepresentsProgrammaticScroll { false };
     bool m_isMonitoringWheelEvents { false };
 };
 
index 151ac29..8a59ccd 100644 (file)
@@ -83,7 +83,7 @@ public:
     virtual void scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync) = 0;
 
     // Called for requested scroll position updates.
-    virtual void scrollingTreeNodeRequestsScroll(ScrollingNodeID, const FloatPoint& /*scrollPosition*/, bool /*representsProgrammaticScroll*/) { }
+    virtual void scrollingTreeNodeRequestsScroll(ScrollingNodeID, const FloatPoint& /*scrollPosition*/, ScrollType, ScrollClamping) { }
 
     // Delegated scrolling/zooming has caused the viewport to change, so update viewport-constrained layers
     WEBCORE_EXPORT void mainFrameViewportChangedViaDelegatedScrolling(const FloatPoint& scrollPosition, const WebCore::FloatRect& layoutViewport, double scale);
index dbd24d6..255f54c 100644 (file)
@@ -95,7 +95,7 @@ bool ScrollingTreeFrameScrollingNode::scrollPositionAndLayoutViewportMatch(const
     return position == currentScrollPosition() && (!overrideLayoutViewport || overrideLayoutViewport.value() == m_layoutViewport);
 }
 
-FloatRect ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale) const
+FloatRect ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale, ScrollBehaviorForFixedElements fixedBehavior) const
 {
     FloatSize visualViewportSize = m_overrideVisualViewportSize.valueOr(scrollableAreaSize());
     FloatRect visibleContentRect(visibleContentOrigin, visualViewportSize);
@@ -107,7 +107,7 @@ FloatRect ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition(const
     LOG_WITH_STREAM(Scrolling, stream << "  visualViewport: " << visualViewport);
     LOG_WITH_STREAM(Scrolling, stream << "  scroll positions: min: " << minLayoutViewportOrigin() << " max: "<< maxLayoutViewportOrigin());
 
-    LayoutPoint newLocation = FrameView::computeLayoutViewportOrigin(LayoutRect(visualViewport), LayoutPoint(minLayoutViewportOrigin()), LayoutPoint(maxLayoutViewportOrigin()), layoutViewport, StickToDocumentBounds);
+    LayoutPoint newLocation = FrameView::computeLayoutViewportOrigin(LayoutRect(visualViewport), LayoutPoint(minLayoutViewportOrigin()), LayoutPoint(maxLayoutViewportOrigin()), layoutViewport, fixedBehavior);
 
     if (layoutViewport.location() != newLocation) {
         layoutViewport.setLocation(newLocation);
@@ -125,6 +125,11 @@ void ScrollingTreeFrameScrollingNode::updateViewportForCurrentScrollPosition(Opt
         setLayoutViewport(layoutViewportForScrollPosition(currentScrollPosition(), frameScaleFactor()));
 }
 
+FloatRect ScrollingTreeFrameScrollingNode::layoutViewportRespectingRubberBanding() const
+{
+    return layoutViewportForScrollPosition(currentScrollPosition(), frameScaleFactor(), StickToViewportBounds);
+}
+
 FloatSize ScrollingTreeFrameScrollingNode::viewToContentsOffset(const FloatPoint& scrollPosition) const
 {
     return toFloatSize(scrollPosition) - FloatSize(0, headerHeight() + topContentInset());
index 3c639c0..d7b54c4 100644 (file)
@@ -47,11 +47,12 @@ public:
     bool visualViewportIsSmallerThanLayoutViewport() const { return m_visualViewportIsSmallerThanLayoutViewport; }
 
     FloatSize viewToContentsOffset(const FloatPoint& scrollPosition) const;
-    FloatRect layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale) const;
 
     FloatRect layoutViewport() const { return m_layoutViewport; };
     void setLayoutViewport(const FloatRect& r) { m_layoutViewport = r; };
 
+    FloatRect layoutViewportRespectingRubberBanding() const;
+
     float frameScaleFactor() const { return m_frameScaleFactor; }
 
 protected:
@@ -72,6 +73,7 @@ private:
 
     void updateViewportForCurrentScrollPosition(Optional<FloatRect>) override;
     bool scrollPositionAndLayoutViewportMatch(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport) override;
+    FloatRect layoutViewportForScrollPosition(const FloatPoint&, float scale, ScrollBehaviorForFixedElements = StickToDocumentBounds) const;
 
     void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const override;
 
index 73dca28..1f079c8 100644 (file)
@@ -107,8 +107,10 @@ void ScrollingTreeScrollingNode::commitStateBeforeChildren(const ScrollingStateN
 void ScrollingTreeScrollingNode::commitStateAfterChildren(const ScrollingStateNode& stateNode)
 {
     const ScrollingStateScrollingNode& scrollingStateNode = downcast<ScrollingStateScrollingNode>(stateNode);
-    if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition))
-        scrollingTree().scrollingTreeNodeRequestsScroll(scrollingNodeID(), scrollingStateNode.requestedScrollPosition(), scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll());
+    if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
+        const auto& requestedScrollData = scrollingStateNode.requestedScrollData();
+        scrollingTree().scrollingTreeNodeRequestsScroll(scrollingNodeID(), requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
+    }
 
     m_isFirstCommit = false;
 }
@@ -144,20 +146,20 @@ bool ScrollingTreeScrollingNode::scrollLimitReached(const PlatformWheelEvent& wh
     return newScrollPosition == oldScrollPosition;
 }
 
-FloatPoint ScrollingTreeScrollingNode::adjustedScrollPosition(const FloatPoint& scrollPosition, ScrollPositionClamp clamp) const
+FloatPoint ScrollingTreeScrollingNode::adjustedScrollPosition(const FloatPoint& scrollPosition, ScrollClamping clamping) const
 {
-    if (clamp == ScrollPositionClamp::ToContentEdges)
+    if (clamping == ScrollClamping::Clamped)
         return clampScrollPosition(scrollPosition);
 
     return scrollPosition;
 }
 
-void ScrollingTreeScrollingNode::scrollBy(const FloatSize& delta, ScrollPositionClamp clamp)
+void ScrollingTreeScrollingNode::scrollBy(const FloatSize& delta, ScrollClamping clamp)
 {
     scrollTo(currentScrollPosition() + delta, ScrollType::User, clamp);
 }
 
-void ScrollingTreeScrollingNode::scrollTo(const FloatPoint& position, ScrollType scrollType, ScrollPositionClamp clamp)
+void ScrollingTreeScrollingNode::scrollTo(const FloatPoint& position, ScrollType scrollType, ScrollClamping clamp)
 {
     if (position == m_currentScrollPosition)
         return;
@@ -200,7 +202,7 @@ void ScrollingTreeScrollingNode::wasScrolledByDelegatedScrolling(const FloatPoin
     if (!scrollPositionChanged && scrollingLayerPositionAction != ScrollingLayerPositionAction::Set)
         return;
 
-    m_currentScrollPosition = adjustedScrollPosition(position, ScrollPositionClamp::None);
+    m_currentScrollPosition = adjustedScrollPosition(position, ScrollClamping::Unclamped);
     updateViewportForCurrentScrollPosition(overrideLayoutViewport);
 
     repositionRelatedLayers();
index 4cbf4d1..d25ac18 100644 (file)
@@ -60,8 +60,8 @@ public:
     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);
-    void scrollBy(const FloatSize&, ScrollPositionClamp = ScrollPositionClamp::ToContentEdges);
+    void scrollTo(const FloatPoint&, ScrollType = ScrollType::User, ScrollClamping = ScrollClamping::Clamped);
+    void scrollBy(const FloatSize&, ScrollClamping = ScrollClamping::Clamped);
 
     void wasScrolledByDelegatedScrolling(const FloatPoint& position, Optional<FloatRect> overrideLayoutViewport = { }, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync);
     
@@ -99,7 +99,7 @@ protected:
 
     FloatPoint clampScrollPosition(const FloatPoint&) const;
     
-    virtual FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollPositionClamp = ScrollPositionClamp::ToContentEdges) const;
+    virtual FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping = ScrollClamping::Clamped) const;
 
     virtual void currentScrollPositionChanged();
     virtual void updateViewportForCurrentScrollPosition(Optional<FloatRect> = { }) { }
index e0e70e8..8cbf044 100644 (file)
@@ -77,7 +77,7 @@ void ScrollingTreeFixedNode::applyLayerPositions()
             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>(*ancestor).layoutViewport();
+                auto layoutViewport = downcast<ScrollingTreeFrameScrollingNode>(*ancestor).layoutViewportRespectingRubberBanding();
                 return m_constraints.layerPositionForViewportRect(layoutViewport) - overflowScrollDelta;
             }
 
index 3ff5d0d..7999eb1 100644 (file)
@@ -73,7 +73,7 @@ FloatPoint ScrollingTreeStickyNode::computeLayerPosition() const
         FloatRect constrainingRect;
         if (is<ScrollingTreeFrameScrollingNode>(scrollingNode)) {
             auto& frameScrollingNode = downcast<ScrollingTreeFrameScrollingNode>(scrollingNode);
-            constrainingRect = frameScrollingNode.layoutViewport();
+            constrainingRect = frameScrollingNode.layoutViewportRespectingRubberBanding();
         } else {
             auto& overflowScrollingNode = downcast<ScrollingTreeOverflowScrollingNode>(scrollingNode);
             constrainingRect = FloatRect(overflowScrollingNode.currentScrollPosition(), m_constraints.constrainingRectAtLastLayout().size());
index 8fa5de3..0bd04fc 100644 (file)
@@ -61,7 +61,7 @@ protected:
     unsigned exposedUnfilledArea() const;
 
 private:
-    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollPositionClamp) const override;
+    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const override;
 
     void currentScrollPositionChanged() override;
     void repositionScrollingLayers() override;
index 0533e32..abaaa77 100644 (file)
@@ -137,8 +137,8 @@ void ScrollingTreeFrameScrollingNodeMac::commitStateAfterChildren(const Scrollin
 
     // Update the scroll position after child nodes have been updated, because they need to have updated their constraints before any scrolling happens.
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollTo(scrollingStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = scrollingStateNode.requestedScrollData();
+        scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 
     if (isRootNode()
@@ -169,7 +169,7 @@ ScrollingEventResult ScrollingTreeFrameScrollingNodeMac::handleWheelEvent(const
     return ScrollingEventResult::DidHandleEvent;
 }
 
-FloatPoint ScrollingTreeFrameScrollingNodeMac::adjustedScrollPosition(const FloatPoint& position, ScrollPositionClamp clamp) const
+FloatPoint ScrollingTreeFrameScrollingNodeMac::adjustedScrollPosition(const FloatPoint& position, ScrollClamping clamp) const
 {
     FloatPoint scrollPosition(roundf(position.x()), roundf(position.y()));
     return ScrollingTreeFrameScrollingNode::adjustedScrollPosition(scrollPosition, clamp);
index bd1e732..f3df3fb 100644 (file)
@@ -45,7 +45,7 @@ protected:
     void commitStateBeforeChildren(const ScrollingStateNode&) override;
     void commitStateAfterChildren(const ScrollingStateNode&) override;
     
-    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollPositionClamp) const override;
+    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const override;
 
     void repositionScrollingLayers() override;
     void repositionRelatedLayers() override;
index 77d9510..44bdebb 100644 (file)
@@ -62,8 +62,8 @@ void ScrollingTreeOverflowScrollingNodeMac::commitStateAfterChildren(const Scrol
     const auto& overflowStateNode = downcast<ScrollingStateOverflowScrollingNode>(stateNode);
 
     if (overflowStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = overflowStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollTo(overflowStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = overflowStateNode.requestedScrollData();
+        scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 }
 
@@ -83,7 +83,7 @@ ScrollingEventResult ScrollingTreeOverflowScrollingNodeMac::handleWheelEvent(con
     return ScrollingEventResult::DidHandleEvent;
 }
 
-FloatPoint ScrollingTreeOverflowScrollingNodeMac::adjustedScrollPosition(const FloatPoint& position, ScrollPositionClamp clamp) const
+FloatPoint ScrollingTreeOverflowScrollingNodeMac::adjustedScrollPosition(const FloatPoint& position, ScrollClamping clamp) const
 {
     FloatPoint scrollPosition(roundf(position.x()), roundf(position.y()));
     return ScrollingTreeOverflowScrollingNode::adjustedScrollPosition(scrollPosition, clamp);
index f7ac792..8d48e6d 100644 (file)
@@ -235,7 +235,7 @@ void ScrollingTreeScrollingNodeDelegateMac::immediateScrollBy(const FloatSize& d
 
 void ScrollingTreeScrollingNodeDelegateMac::immediateScrollByWithoutContentEdgeConstraints(const FloatSize& offset)
 {
-    scrollingNode().scrollBy(offset, ScrollPositionClamp::None);
+    scrollingNode().scrollBy(offset, ScrollClamping::Unclamped);
 }
 
 void ScrollingTreeScrollingNodeDelegateMac::stopSnapRubberbandTimer()
index deba5c8..5fe4ea5 100644 (file)
@@ -91,8 +91,8 @@ void ScrollingTreeFrameScrollingNodeNicosia::commitStateAfterChildren(const Scro
 
     // Update the scroll position after child nodes have been updated, because they need to have updated their constraints before any scrolling happens.
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollTo(scrollingStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = scrollingStateNode.requestedScrollData();
+        scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 }
 
@@ -116,10 +116,10 @@ ScrollingEventResult ScrollingTreeFrameScrollingNodeNicosia::handleWheelEvent(co
     return ScrollingEventResult::DidHandleEvent;
 }
 
-FloatPoint ScrollingTreeFrameScrollingNodeNicosia::adjustedScrollPosition(const FloatPoint& position, ScrollPositionClamp clamp) const
+FloatPoint ScrollingTreeFrameScrollingNodeNicosia::adjustedScrollPosition(const FloatPoint& position, ScrollClamping clamping) const
 {
     FloatPoint scrollPosition(roundf(position.x()), roundf(position.y()));
-    return ScrollingTreeFrameScrollingNode::adjustedScrollPosition(scrollPosition, clamp);
+    return ScrollingTreeFrameScrollingNode::adjustedScrollPosition(scrollPosition, clamping);
 }
 
 void ScrollingTreeFrameScrollingNodeNicosia::currentScrollPositionChanged()
index 1b993f6..171687d 100644 (file)
@@ -53,7 +53,7 @@ private:
 
     ScrollingEventResult handleWheelEvent(const PlatformWheelEvent&) override;
 
-    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollPositionClamp) const override;
+    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const override;
 
     void currentScrollPositionChanged() override;
 
index d1f1161..0b7de94 100644 (file)
@@ -55,15 +55,15 @@ void ScrollingTreeOverflowScrollingNodeNicosia::commitStateAfterChildren(const S
 
     const auto& overflowStateNode = downcast<ScrollingStateOverflowScrollingNode>(stateNode);
     if (overflowStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = overflowStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollTo(overflowStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = overflowStateNode.requestedScrollData();
+        scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 }
 
-FloatPoint ScrollingTreeOverflowScrollingNodeNicosia::adjustedScrollPosition(const FloatPoint& position, ScrollPositionClamp clamp) const
+FloatPoint ScrollingTreeOverflowScrollingNodeNicosia::adjustedScrollPosition(const FloatPoint& position, ScrollClamping clamping) const
 {
     FloatPoint scrollPosition(roundf(position.x()), roundf(position.y()));
-    return ScrollingTreeOverflowScrollingNode::adjustedScrollPosition(scrollPosition, clamp);
+    return ScrollingTreeOverflowScrollingNode::adjustedScrollPosition(scrollPosition, clamping);
 }
 
 void ScrollingTreeOverflowScrollingNodeNicosia::repositionScrollingLayers()
index 203db59..a1f9c81 100644 (file)
@@ -44,7 +44,7 @@ private:
 
     void commitStateAfterChildren(const ScrollingStateNode&) override;
 
-    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollPositionClamp) const override;
+    FloatPoint adjustedScrollPosition(const FloatPoint&, ScrollClamping) const override;
 
     void repositionScrollingLayers() override;
 
diff --git a/Source/WebCore/platform/ScrollTypes.cpp b/Source/WebCore/platform/ScrollTypes.cpp
new file mode 100644 (file)
index 0000000..a09de3f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2006 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+
+#include "config.h"
+#include "ScrollTypes.h"
+
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+TextStream& operator<<(TextStream& ts, ScrollType scrollType)
+{
+    switch (scrollType) {
+    case ScrollType::User: ts << "user"; break;
+    case ScrollType::Programmatic: ts << "programmatic"; break;
+    }
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, ScrollClamping clamping)
+{
+    switch (clamping) {
+    case ScrollClamping::Unclamped: ts << "unclamped"; break;
+    case ScrollClamping::Clamped: ts << "clamped"; break;
+    }
+    return ts;
+}
+
+} // namespace WebCore
index 8911491..7dff30a 100644 (file)
 #include <cstdint>
 #include <wtf/Assertions.h>
 
+namespace WTF {
+class TextStream;
+}
+
 namespace WebCore {
 
 enum class ScrollType : uint8_t {
@@ -49,11 +53,6 @@ enum ScrollLogicalDirection : uint8_t {
     ScrollInlineDirectionForward
 };
 
-enum class ScrollPositionClamp : uint8_t {
-    None,
-    ToContentEdges,
-};
-
 inline ScrollDirection logicalToPhysical(ScrollLogicalDirection direction, bool isVertical, bool isFlipped)
 {
     switch (direction) {
@@ -229,4 +228,7 @@ using ScrollbarControlState = unsigned;
 using ScrollbarControlPartMask = unsigned;
 using ScrollingNodeID = uint64_t;
 
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollType);
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollClamping);
+
 } // namespace WebCore
index 4f2137d..ca3bdd0 100644 (file)
@@ -211,13 +211,13 @@ IntPoint ScrollView::contentsScrollPosition() const
     return scrollPosition();
 }
 
-void ScrollView::setContentsScrollPosition(const IntPoint& position)
+void ScrollView::setContentsScrollPosition(const IntPoint& position, ScrollClamping clamping)
 {
 #if PLATFORM(IOS_FAMILY)
     if (platformWidget())
         setActualScrollPosition(position);
 #endif
-    setScrollPosition(position);
+    setScrollPosition(position, clamping);
 }
 
 FloatRect ScrollView::exposedContentRect() const
@@ -518,7 +518,7 @@ void ScrollView::completeUpdatesAfterScrollTo(const IntSize& scrollDelta)
     updateCompositingLayersAfterScrolling();
 }
 
-void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition)
+void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition, ScrollClamping clamping)
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollView::setScrollPosition " << scrollPosition);
 
@@ -530,12 +530,12 @@ void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition)
         return;
     }
 
-    ScrollPosition newScrollPosition = !delegatesScrolling() ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
+    ScrollPosition newScrollPosition = (!delegatesScrolling() && clamping == ScrollClamping::Clamped) ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
 
     if ((!delegatesScrolling() || currentScrollType() == ScrollType::User) && newScrollPosition == this->scrollPosition())
         return;
 
-    if (requestScrollPositionUpdate(newScrollPosition))
+    if (requestScrollPositionUpdate(newScrollPosition, currentScrollType(), clamping))
         return;
 
     updateScrollbars(newScrollPosition);
index c4aa592..ea80214 100644 (file)
@@ -234,7 +234,7 @@ public:
 
     // Scroll position used by web-exposed features (has legacy iOS behavior).
     WEBCORE_EXPORT IntPoint contentsScrollPosition() const;
-    void setContentsScrollPosition(const IntPoint&);
+    void setContentsScrollPosition(const IntPoint&, ScrollClamping = ScrollClamping::Clamped);
 
 #if PLATFORM(IOS_FAMILY)
     int actualScrollX() const { return unobscuredContentRect().x(); }
@@ -264,7 +264,7 @@ public:
     ScrollPosition cachedScrollPosition() const { return m_cachedScrollPosition; }
 
     // Functions for scrolling the view.
-    virtual void setScrollPosition(const ScrollPosition&);
+    virtual void setScrollPosition(const ScrollPosition&, ScrollClamping = ScrollClamping::Clamped);
     void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); }
 
     // This function scrolls by lines, pages or pixels.
index 0297295..4222b74 100644 (file)
@@ -227,7 +227,7 @@ void ScrollableArea::setScrollOffsetFromInternals(const ScrollOffset& offset)
 void ScrollableArea::setScrollOffsetFromAnimation(const ScrollOffset& offset)
 {
     ScrollPosition position = scrollPositionFromOffset(offset);
-    if (requestScrollPositionUpdate(position))
+    if (requestScrollPositionUpdate(position, currentScrollType()))
         return;
 
     scrollPositionChanged(position);
index b6d27fe..a854734 100644 (file)
@@ -73,7 +73,7 @@ public:
     // Allows subclasses to handle scroll position updates themselves. If this member function
     // returns true, the scrollable area won't actually update the scroll position and instead
     // expect it to happen sometime in the future.
-    virtual bool requestScrollPositionUpdate(const ScrollPosition&) { return false; }
+    virtual bool requestScrollPositionUpdate(const ScrollPosition&, ScrollType = ScrollType::User, ScrollClamping = ScrollClamping::Clamped) { return false; }
 
     WEBCORE_EXPORT bool handleWheelEvent(const PlatformWheelEvent&);
 
index 8f50e57..e85a15c 100644 (file)
@@ -2608,7 +2608,7 @@ void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType sc
     bool handled = false;
 #if ENABLE(ASYNC_SCROLLING)
     if (ScrollingCoordinator* scrollingCoordinator = page().scrollingCoordinator())
-        handled = scrollingCoordinator->requestScrollPositionUpdate(*this, scrollPositionFromOffset(clampedScrollOffset));
+        handled = scrollingCoordinator->requestScrollPositionUpdate(*this, scrollPositionFromOffset(clampedScrollOffset), scrollType, clamping);
 #endif
 
     if (!handled)
index 9e0586f..e8ea6d3 100644 (file)
@@ -1772,6 +1772,10 @@ ExceptionOr<void> Internals::unconstrainedScrollTo(Element& element, double x, d
         return Exception { InvalidAccessError };
 
     element.scrollTo({ x, y }, ScrollClamping::Unclamped);
+
+    auto& frameView = *document->view();
+    frameView.setViewportConstrainedObjectsNeedLayout();
+
     return { };
 }
 
index 3414987..abbb246 100644 (file)
         * WebProcess/Cache/WebCacheStorageConnection.cpp:
         (WebKit::WebCacheStorageConnection::updateQuotaBasedOnSpaceUsage):
 
+2020-01-22  Simon Fraser  <simon.fraser@apple.com>
+
+        Fixed elements no longer stay fixed with elastic overscroll
+        https://bugs.webkit.org/show_bug.cgi?id=206227
+        rdar://problem/58707084
+
+        Reviewed by Antti Koivisto.
+
+        Intended behavior on iOS and macOS is for position:fixed and sticky elements to maintain
+        their position relative to the view bounds when rubber-banding ("overscrolling"). This broke
+        some time back. This change restores the correct behavior with the call to layoutViewportRespectingRubberBanding()
+        in ScrollingTreeFixedNode::applyLayerPositions() and ScrollingTreeStickyNode::computeLayerPosition().
+        layoutViewportRespectingRubberBanding() computes a layout viewport without clamping.
+
+        The rest of the changes are to support testing. internals.unconstrainedScrollTo()
+        didn't work for main frame scrolling because of scroll position clamping in various places,
+        so propagate ScrollClamping in more places (and replace the redundant ScrollPositionClamp with ScrollClamping).
+
+        "requested scroll position" updates now carry along both clamping and "is programmatic" data, wrapped in a struct
+        which is passed around the scrolling tree. This allows us to not clamp the scroll position (for testing) in more places.
+
+        * Shared/RemoteLayerTree/RemoteScrollingCoordinatorTransaction.cpp:
+        (ArgumentCoder<ScrollingStateScrollingNode>::encode):
+        (ArgumentCoder<ScrollingStateScrollingNode>::decode):
+        (ArgumentCoder<RequestedScrollData>::encode):
+        (ArgumentCoder<RequestedScrollData>::decode):
+        (WebKit::dump):
+        * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp:
+        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll):
+        * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/RemoteLayerTree/RemoteScrollingTree.cpp:
+        (WebKit::RemoteScrollingTree::scrollingTreeNodeRequestsScroll):
+        * UIProcess/RemoteLayerTree/RemoteScrollingTree.h:
+        * UIProcess/RemoteLayerTree/ios/ScrollingTreeFrameScrollingNodeRemoteIOS.mm:
+        (WebKit::ScrollingTreeFrameScrollingNodeRemoteIOS::commitStateAfterChildren):
+        * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
+        (WebKit::ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren):
+
 2020-01-21  Daniel Bates  <dabates@apple.com>
 
         Add Legacy WebKit SPI and WebKit IPI to show and hide placeholder
index 0bb7041..bdbb5eb 100644 (file)
@@ -32,6 +32,7 @@
 #include "ArgumentCoders.h"
 #include "WebCoreArgumentCoders.h"
 #include <WebCore/GraphicsLayer.h>
+#include <WebCore/ScrollTypes.h>
 #include <WebCore/ScrollingStateFixedNode.h>
 #include <WebCore/ScrollingStateFrameHostingNode.h>
 #include <WebCore/ScrollingStateFrameScrollingNode.h>
@@ -92,6 +93,11 @@ template<> struct ArgumentCoder<ScrollingStatePositionedNode> {
     static bool decode(Decoder&, ScrollingStatePositionedNode&);
 };
 
+template<> struct ArgumentCoder<RequestedScrollData> {
+    static void encode(Encoder&, const RequestedScrollData&);
+    static bool decode(Decoder&, RequestedScrollData&);
+};
+
 } // namespace IPC
 
 using namespace IPC;
@@ -151,8 +157,7 @@ void ArgumentCoder<ScrollingStateScrollingNode>::encode(Encoder& encoder, const
     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::CurrentVerticalSnapOffsetIndex, currentVerticalSnapPointIndex)
 #endif
     SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::ScrollableAreaParams, scrollableAreaParameters)
-    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPosition)
-    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollPositionRepresentsProgrammaticScroll)
+    SCROLLING_NODE_ENCODE(ScrollingStateScrollingNode::RequestedScrollPosition, requestedScrollData)
 
     if (node.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer))
         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.scrollContainerLayer());
@@ -251,18 +256,7 @@ bool ArgumentCoder<ScrollingStateScrollingNode>::decode(Decoder& decoder, Scroll
     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::CurrentVerticalSnapOffsetIndex, unsigned, setCurrentVerticalSnapPointIndex);
 #endif
     SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::ScrollableAreaParams, ScrollableAreaParameters, setScrollableAreaParameters);
-    
-    if (node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        FloatPoint scrollPosition;
-        if (!decoder.decode(scrollPosition))
-            return false;
-
-        bool representsProgrammaticScroll;
-        if (!decoder.decode(representsProgrammaticScroll))
-            return false;
-
-        node.setRequestedScrollPosition(scrollPosition, representsProgrammaticScroll);
-    }
+    SCROLLING_NODE_DECODE(ScrollingStateScrollingNode::RequestedScrollPosition, RequestedScrollData, setRequestedScrollData);
 
     if (node.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer)) {
         GraphicsLayer::PlatformLayerID layerID;
@@ -450,6 +444,28 @@ bool ArgumentCoder<ScrollingStatePositionedNode>::decode(Decoder& decoder, Scrol
     return true;
 }
 
+
+void ArgumentCoder<RequestedScrollData>::encode(Encoder& encoder, const RequestedScrollData& scrollData)
+{
+    encoder << scrollData.scrollPosition;
+    encoder.encodeEnum(scrollData.scrollType);
+    encoder.encodeEnum(scrollData.clamping);
+}
+
+bool ArgumentCoder<RequestedScrollData>::decode(Decoder& decoder, RequestedScrollData& scrollData)
+{
+    if (!decoder.decode(scrollData.scrollPosition))
+        return false;
+
+    if (!decoder.decodeEnum(scrollData.scrollType))
+        return false;
+
+    if (!decoder.decodeEnum(scrollData.clamping))
+        return false;
+
+    return true;
+}
+
 namespace WebKit {
 
 static void encodeNodeAndDescendants(IPC::Encoder& encoder, const ScrollingStateNode& stateNode, int& encodedNodeCount)
@@ -607,8 +623,10 @@ static void dump(TextStream& ts, const ScrollingStateScrollingNode& node, bool c
         ts.dumpProperty("scroll-origin", node.scrollOrigin());
 
     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        ts.dumpProperty("requested-scroll-position", node.requestedScrollPosition());
-        ts.dumpProperty("requested-scroll-position-is-programatic", node.requestedScrollPositionRepresentsProgrammaticScroll());
+        const auto& requestedScrollData = node.requestedScrollData();
+        ts.dumpProperty("requested-scroll-position", requestedScrollData.scrollPosition);
+        ts.dumpProperty("requested-scroll-position-is-programatic", requestedScrollData.scrollType);
+        ts.dumpProperty("requested-scroll-position-clamping", requestedScrollData.clamping);
     }
 
     if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer))
index e7941a8..4b1a2da 100644 (file)
@@ -228,11 +228,11 @@ void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID
     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition, scrollingLayerPositionAction == ScrollingLayerPositionAction::Sync));
 }
 
-void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
+void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, ScrollType scrollType, ScrollClamping)
 {
     if (scrolledNodeID == rootScrollingNodeID() && m_requestedScrollInfo) {
         m_requestedScrollInfo->requestsScrollPositionUpdate = true;
-        m_requestedScrollInfo->requestIsProgrammaticScroll = representsProgrammaticScroll;
+        m_requestedScrollInfo->requestIsProgrammaticScroll = scrollType == ScrollType::Programmatic;
         m_requestedScrollInfo->requestedScrollPosition = scrollPosition;
     }
 }
index 104defc..b740761 100644 (file)
@@ -57,7 +57,7 @@ public:
 
     // Inform the web process that the scroll position changed (called from the scrolling tree)
     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, const Optional<WebCore::FloatPoint>& layoutViewportOrigin, WebCore::ScrollingLayerPositionAction);
-    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
+    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, WebCore::ScrollType, WebCore::ScrollClamping);
 
     WebCore::TrackingType eventTrackingTypeForPoint(const AtomString& eventName, WebCore::IntPoint) const;
 
index d0db77d..01a57d4 100644 (file)
@@ -107,9 +107,9 @@ void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&
     m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(node.scrollingNodeID(), node.currentScrollPosition(), layoutViewportOrigin, scrollingLayerPositionAction);
 }
 
-void RemoteScrollingTree::scrollingTreeNodeRequestsScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
+void RemoteScrollingTree::scrollingTreeNodeRequestsScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, ScrollType scrollType, ScrollClamping clamping)
 {
-    m_scrollingCoordinatorProxy.scrollingTreeNodeRequestsScroll(nodeID, scrollPosition, representsProgrammaticScroll);
+    m_scrollingCoordinatorProxy.scrollingTreeNodeRequestsScroll(nodeID, scrollPosition, scrollType, clamping);
 }
 
 Ref<ScrollingTreeNode> RemoteScrollingTree::createScrollingTreeNode(ScrollingNodeType nodeType, ScrollingNodeID nodeID)
index f531629..cc1f960 100644 (file)
@@ -52,7 +52,7 @@ public:
     const RemoteScrollingCoordinatorProxy& scrollingCoordinatorProxy() const { return m_scrollingCoordinatorProxy; }
 
     void scrollingTreeNodeDidScroll(WebCore::ScrollingTreeScrollingNode&, WebCore::ScrollingLayerPositionAction = WebCore::ScrollingLayerPositionAction::Sync) override;
-    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll) override;
+    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, WebCore::ScrollType, WebCore::ScrollClamping) override;
 
     void currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID, unsigned horizontal, unsigned vertical) override;
 
index 1bf563a..377a77f 100644 (file)
@@ -89,8 +89,8 @@ void ScrollingTreeFrameScrollingNodeRemoteIOS::commitStateAfterChildren(const Sc
 
     // Update the scroll position after child nodes have been updated, because they need to have updated their constraints before any scrolling happens.
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollTo(scrollingStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = scrollingStateNode.requestedScrollData();
+        scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 }
 
index e768983..8c6442d 100644 (file)
@@ -299,8 +299,8 @@ void ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren(const Scrol
     }
 
     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition)) {
-        auto scrollType = scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll() ? ScrollType::Programmatic : ScrollType::User;
-        scrollingNode().scrollTo(scrollingStateNode.requestedScrollPosition(), scrollType);
+        const auto& requestedScrollData = scrollingStateNode.requestedScrollData();
+        scrollingNode().scrollTo(requestedScrollData.scrollPosition, requestedScrollData.scrollType, requestedScrollData.clamping);
     }
 }