[WK2 iOS] Scrolling to anchor links is broken
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Apr 2014 19:49:37 +0000 (19:49 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Apr 2014 19:49:37 +0000 (19:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131618
<rdar://problem/16599144>

Source/WebCore:

Reviewed by Tim Horton.

Have ScrollingTreeScrollingNode pass RequestedScrollPosition updates
to the scrolling tree, so that the scrolling tree can have custom behavior
for them if necessary.

* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::scrollingTreeNodeRequestsScroll):
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::updateAfterChildren):
* page/scrolling/ScrollingTreeScrollingNode.h:

Source/WebKit2:

Reviewed by Tim Horton.

The RemoteScrollingTree implements scrollingTreeNodeRequestsScroll
to get informed about requested scroll position updates, and passes
them along via the RemoteScrollingCoordinatorProxy, WebPageProxy and PageClient
to the WKWebView, which performs a scroll.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _scrollToContentOffset:WebCore::]): Scroll to content offset,
taking page scale and insets into account.
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/CoordinatedGraphics/WebView.cpp:
(WebKit::WebView::requestScroll):
* UIProcess/CoordinatedGraphics/WebView.h:
* UIProcess/PageClient.h:
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll):
Pass scrolls along to the WebPageProxy for the root node. We will also need
to handle programmatic scrolls for overflow soon.
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
* UIProcess/Scrolling/RemoteScrollingTree.cpp:
(WebKit::RemoteScrollingTree::scrollingTreeNodeRequestsScroll):
* UIProcess/Scrolling/RemoteScrollingTree.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::requestScroll):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::canScrollView):
(WebKit::PageClientImpl::requestScroll):
* UIProcess/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::requestScroll):

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

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/scrolling/ScrollingTree.h
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h
Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp
Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h
Source/WebKit2/UIProcess/CoordinatedGraphics/WebView.cpp
Source/WebKit2/UIProcess/CoordinatedGraphics/WebView.h
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/ios/PageClientImplIOS.h
Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm
Source/WebKit2/UIProcess/mac/PageClientImpl.mm

index 93d0d1e5db9033dccaeb22583cc2c94890b12e8c..fda85afc783e2cf72f0feb8896ee6c6f1bbd2ad8 100644 (file)
@@ -1,3 +1,21 @@
+2014-04-14  Simon Fraser  <simon.fraser@apple.com>
+
+        [WK2 iOS] Scrolling to anchor links is broken
+        https://bugs.webkit.org/show_bug.cgi?id=131618
+        <rdar://problem/16599144>
+
+        Reviewed by Tim Horton.
+
+        Have ScrollingTreeScrollingNode pass RequestedScrollPosition updates
+        to the scrolling tree, so that the scrolling tree can have custom behavior
+        for them if necessary.
+
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::scrollingTreeNodeRequestsScroll):
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::updateAfterChildren):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+
 2014-04-14  Brian J. Burg  <burg@cs.washington.edu>
 
         Web Replay: memoize fallback time values for document.lastModified
index aca64fd1a289875c4f94faeab3fd98370d19344b..2f47a6ac5a38f2c42f6b3a60ab9313c403ab9b4e 100644 (file)
@@ -75,6 +75,9 @@ public:
     // Updates FrameView/RenderLayer scrolling state and GraphicsLayers.
     virtual void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) = 0;
 
+    // Called for requested scroll position updates.
+    virtual void scrollingTreeNodeRequestsScroll(ScrollingNodeID, const FloatPoint& /*scrollPosition*/, bool /*representsProgrammaticScroll*/) { }
+
     // Delegated scrolling/zooming has caused the viewport to change, so update viewport-constrained layers
     // (but don't cause scroll events to be fired).
     virtual void viewportChangedViaDelegatedScrolling(ScrollingNodeID, const WebCore::FloatRect& viewportRect, double scale);
index f841397a8736e5841094a5c33c46315606a49563..f5d8b3afd7a1ddbd27d062eee4fe27016359be55 100644 (file)
@@ -87,6 +87,13 @@ void ScrollingTreeScrollingNode::updateBeforeChildren(const ScrollingStateNode&
         m_behaviorForFixed = state.scrollBehaviorForFixedElements();
 }
 
+void ScrollingTreeScrollingNode::updateAfterChildren(const ScrollingStateNode& stateNode)
+{
+    const ScrollingStateScrollingNode& scrollingStateNode = toScrollingStateScrollingNode(stateNode);
+    if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition))
+        scrollingTree().scrollingTreeNodeRequestsScroll(scrollingNodeID(), scrollingStateNode.requestedScrollPosition(), scrollingStateNode.requestedScrollPositionRepresentsProgrammaticScroll());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(ASYNC_SCROLLING)
index 2c72bfd45ef281767a04b05166e28cd13bbaec0e..1f1815be823aaecad96410f8210a9ba3e0b13d00 100644 (file)
@@ -45,6 +45,7 @@ public:
     virtual ~ScrollingTreeScrollingNode();
 
     virtual void updateBeforeChildren(const ScrollingStateNode&) override;
+    virtual void updateAfterChildren(const ScrollingStateNode&) override;
 
     // FIXME: We should implement this when we support ScrollingTreeScrollingNodes as children.
     virtual void parentScrollPositionDidChange(const FloatRect& /*viewportRect*/, const FloatSize& /*cumulativeDelta*/) override { }
index 3e6546b077afa1d82ef048137e959c5c5685773c..56da2924fa7f04fc1682d907c38bbcc454363145 100644 (file)
@@ -1,3 +1,42 @@
+2014-04-14  Simon Fraser  <simon.fraser@apple.com>
+
+        [WK2 iOS] Scrolling to anchor links is broken
+        https://bugs.webkit.org/show_bug.cgi?id=131618
+        <rdar://problem/16599144>
+
+        Reviewed by Tim Horton.
+        
+        The RemoteScrollingTree implements scrollingTreeNodeRequestsScroll
+        to get informed about requested scroll position updates, and passes
+        them along via the RemoteScrollingCoordinatorProxy, WebPageProxy and PageClient
+        to the WKWebView, which performs a scroll.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _scrollToContentOffset:WebCore::]): Scroll to content offset,
+        taking page scale and insets into account.
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/CoordinatedGraphics/WebView.cpp:
+        (WebKit::WebView::requestScroll):
+        * UIProcess/CoordinatedGraphics/WebView.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
+        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll):
+        Pass scrolls along to the WebPageProxy for the root node. We will also need
+        to handle programmatic scrolls for overflow soon.
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/Scrolling/RemoteScrollingTree.cpp:
+        (WebKit::RemoteScrollingTree::scrollingTreeNodeRequestsScroll):
+        * UIProcess/Scrolling/RemoteScrollingTree.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::requestScroll):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::canScrollView):
+        (WebKit::PageClientImpl::requestScroll):
+        * UIProcess/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::requestScroll):
+
 2014-04-12  Antti Koivisto  <antti@apple.com>
 
         Keep secondary tile grid for zoomed-out scale
index 2ad46f7d665fc052c57921a3bc16c0ec75535ecf..21eb2051cb079f740fecffdac20b18a46595e10e 100644 (file)
@@ -544,6 +544,18 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     return contentOffset;
 }
 
+- (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffset
+{
+    WebCore::FloatPoint scaledOffset = contentOffset;
+    CGFloat zoomScale = contentZoomScale(self);
+    scaledOffset.scale(zoomScale, zoomScale);
+
+    UIEdgeInsets inset = [_scrollView contentInset];
+    scaledOffset += WebCore::FloatSize(-inset.left, -inset.top);
+
+    [_scrollView setContentOffset:scaledOffset];
+}
+
 - (BOOL)_scrollToRect:(WebCore::FloatRect)targetRect origin:(WebCore::FloatPoint)origin minimumScrollDistance:(float)minimumScrollDistance
 {
     WebCore::FloatRect unobscuredContentRect([self _contentRectForUserInteraction]);
index 6f9d2b38fd44a45095f1f24305ad07ac3c510be7..5cf91e2473e0becc82d58ac6d9e7d93dc5f03a5e 100644 (file)
@@ -64,6 +64,7 @@ class WebPageProxy;
 
 - (RetainPtr<CGImageRef>)_takeViewSnapshot;
 
+- (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffset;
 - (BOOL)_scrollToRect:(WebCore::FloatRect)targetRect origin:(WebCore::FloatPoint)origin minimumScrollDistance:(float)minimumScrollDistance;
 - (BOOL)_zoomToRect:(WebCore::FloatRect)targetRect withOrigin:(WebCore::FloatPoint)origin fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale minimumScrollDistance:(float)minimumScrollDistance;
 - (void)_zoomOutWithOrigin:(WebCore::FloatPoint)origin;
index 91fac08aaeae56b43ec604cafff4dfb4667aacd6..c6fc610dd70c01028b1f8bd2146193b1564d7a3d 100644 (file)
@@ -83,6 +83,11 @@ void PageClientImpl::scrollView(const WebCore::IntRect& scrollRect, const WebCor
     setViewNeedsDisplay(scrollRect);
 }
 
+void PageClientImpl::requestScroll(const WebCore::FloatPoint&, bool)
+{
+    notImplemented();
+}
+
 WebCore::IntSize PageClientImpl::viewSize()
 {
     if (!gtk_widget_get_realized(m_viewWidget))
index 5209208279119e8d7f17bcd563da07c715d72ad0..a4142fab45a47edf1fb136f61e5e67ceb4bf8caf 100644 (file)
@@ -65,6 +65,7 @@ private:
     virtual void displayView() override;
     virtual bool canScrollView() override { return false; }
     virtual void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) override;
+    virtual void requestScroll(const WebCore::FloatPoint& scrollPosition, bool isProgrammaticScroll) override;
     virtual WebCore::IntSize viewSize() override;
     virtual bool isViewWindowActive() override;
     virtual bool isViewFocused() override;
index e617df1293ca2b0cefa9c496504e5845a6759826..6144aba24c7178c487ba00a6f0af1d21f185b954 100644 (file)
@@ -304,6 +304,11 @@ void WebView::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntS
     setViewNeedsDisplay(scrollRect);
 }
 
+void WebView::requestScroll(const WebCore::FloatPoint&, bool)
+{
+    notImplemented();
+}
+
 WebCore::IntSize WebView::viewSize()
 {
     return roundedIntSize(dipSize());
index c4419741d4784a4ef05a31babac033d54925a522..754fa2adc111d28f8d734983e192dd2862f26b7e 100644 (file)
@@ -131,6 +131,7 @@ protected:
 
     virtual bool canScrollView() override { return false; }
     virtual void scrollView(const WebCore::IntRect&, const WebCore::IntSize&) override;
+    virtual void requestScroll(const WebCore::FloatPoint&, bool) override;
 
     virtual WebCore::IntSize viewSize() override;
 
index fce15ac2d5b0be5165d5069b4591df7411935013..33b6274926dbf80146d13a9f633ace1877f8105b 100644 (file)
@@ -93,6 +93,8 @@ public:
     virtual bool canScrollView() = 0;
     // Tell the view to scroll scrollRect by scrollOffset.
     virtual void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) = 0;
+    // Tell the view to scroll to the given position, and whether this was a programmatic scroll.
+    virtual void requestScroll(const WebCore::FloatPoint& scrollPosition, bool isProgrammaticScroll) = 0;
 
     // Return the size of the view the page is associated with.
     virtual WebCore::IntSize viewSize() = 0;
index 10a0f48cc9ae0e5724039310faa341c276a2f971..94b14ad9c85c9b33baffea8cda5b0313a8a6ab1f 100644 (file)
@@ -160,6 +160,12 @@ void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(WebCore::Scroll
     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition));
 }
 
+void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
+{
+    if (scrolledNodeID == rootScrollingNodeID())
+        m_webPageProxy.requestScroll(scrollPosition, representsProgrammaticScroll);
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(ASYNC_SCROLLING)
index 16c8d487d770a8b5ec9114defbb5cfb60ce1c6b2..b73aaf1e4e218e73dc0cdc1b43fd5a528e528988 100644 (file)
@@ -53,6 +53,7 @@ public:
     
     // Inform the web process that the scroll position changed (called from the scrolling tree)
     void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition);
+    void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
 
     bool isPointInNonFastScrollableRegion(const WebCore::IntPoint&) const;
 
index f8c95cb6da85fb7fcf79977ad8754b0610723e23..fb0df372c63d23552434ff9aed6d30925ddf1eca 100644 (file)
@@ -82,6 +82,11 @@ void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, con
     m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(nodeID, scrollPosition);
 }
 
+void RemoteScrollingTree::scrollingTreeNodeRequestsScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
+{
+    m_scrollingCoordinatorProxy.scrollingTreeNodeRequestsScroll(nodeID, scrollPosition, representsProgrammaticScroll);
+}
+
 PassOwnPtr<ScrollingTreeNode> RemoteScrollingTree::createNode(ScrollingNodeType nodeType, ScrollingNodeID nodeID)
 {
     switch (nodeType) {
index 51f0adf4af135cc64c66f0ce7855e5525d0ad728..bcd751d3a8f7835358a0288190e380ea9c5a51a0 100644 (file)
@@ -47,6 +47,7 @@ public:
     const RemoteScrollingCoordinatorProxy& scrollingCoordinatorProxy() const { return m_scrollingCoordinatorProxy; }
 
     virtual void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, WebCore::SetOrSyncScrollingLayerPosition = WebCore::SyncScrollingLayerPosition) override;
+    virtual void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll) override;
 
 private:
     explicit RemoteScrollingTree(RemoteScrollingCoordinatorProxy&);
index 4aaee45b3256e9cfd3b868f61bc54d1dce567b3c..3d351391d2753788233a7724f6d5a70fa091664c 100644 (file)
@@ -1008,6 +1008,11 @@ void WebPageProxy::scrollView(const IntRect& scrollRect, const IntSize& scrollOf
     m_pageClient.scrollView(scrollRect, scrollOffset);
 }
 
+void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
+{
+    m_pageClient.requestScroll(scrollPosition, isProgrammaticScroll);
+}
+
 void WebPageProxy::updateViewState(ViewState::Flags flagsToUpdate)
 {
     m_viewState &= ~flagsToUpdate;
index 229a5e6db945aec3512ba56b1aed477da74a9be8..1ccdf0054cb453e74346fa32ec1d8fce63b1c95a 100644 (file)
@@ -545,7 +545,8 @@ public:
     void setViewNeedsDisplay(const WebCore::IntRect&);
     void displayView();
     bool canScrollView();
-    void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset);
+    void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset); // FIXME: CoordinatedGraphics should use requestScroll().
+    void requestScroll(const WebCore::FloatPoint& scrollPosition, bool isProgrammaticScroll);
     
     void setDelegatesScrolling(bool delegatesScrolling) { m_delegatesScrolling = delegatesScrolling; }
     bool delegatesScrolling() const { return m_delegatesScrolling; }
index 6dd391085680dd24c6188d6413669178d24d48a7..db60692c434000fb0662c6e1c3458451c4e9745a 100644 (file)
@@ -53,6 +53,7 @@ private:
     virtual void displayView() override;
     virtual bool canScrollView() override;
     virtual void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) override;
+    virtual void requestScroll(const WebCore::FloatPoint& scrollPosition, bool isProgrammaticScroll) override;
     virtual WebCore::IntSize viewSize() override;
     virtual bool isViewWindowActive() override;
     virtual bool isViewFocused() override;
index a408666fbe116b42b50c29ddbda8530d286b9074..e912438244c8a3345b7c11ba5dcf81a772e83ee8 100644 (file)
@@ -82,15 +82,21 @@ void PageClientImpl::displayView()
     ASSERT_NOT_REACHED();
 }
 
+bool PageClientImpl::canScrollView()
+{
+    notImplemented();
+    return false;
+}
+
 void PageClientImpl::scrollView(const IntRect&, const IntSize&)
 {
     ASSERT_NOT_REACHED();
 }
 
-bool PageClientImpl::canScrollView()
+void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
 {
-    notImplemented();
-    return false;
+    UNUSED_PARAM(isProgrammaticScroll);
+    [m_webView _scrollToContentOffset:scrollPosition];
 }
 
 IntSize PageClientImpl::viewSize()
index 19b638a6a7a333cf267cdf5d710273ee1c3dfd82..6b7b1c0ee9ed4d5b9ea7a8583aacf0c1c6288fd3 100644 (file)
@@ -170,6 +170,11 @@ void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scroll
     ASSERT_NOT_REACHED();
 }
 
+void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
+{
+    ASSERT_NOT_REACHED();
+}
+
 IntSize PageClientImpl::viewSize()
 {
     return IntSize([m_wkView bounds].size);