930a110b1cb230df2ddcb0bcb8a638295f0cc99b
[WebKit-https.git] / Source / WebKit2 / UIProcess / Scrolling / RemoteScrollingCoordinatorProxy.cpp
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RemoteScrollingCoordinatorProxy.h"
28
29 #if ENABLE(ASYNC_SCROLLING)
30
31 #include "ArgumentCoders.h"
32 #include "RemoteLayerTreeDrawingAreaProxy.h"
33 #include "RemoteScrollingCoordinator.h"
34 #include "RemoteScrollingCoordinatorMessages.h"
35 #include "RemoteScrollingCoordinatorTransaction.h"
36 #include "WebPageProxy.h"
37 #include "WebProcessProxy.h"
38 #include <WebCore/ScrollingStateFrameScrollingNode.h>
39 #include <WebCore/ScrollingStateOverflowScrollingNode.h>
40 #include <WebCore/ScrollingStateTree.h>
41 #include <WebCore/ScrollingTreeScrollingNode.h>
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 RemoteScrollingCoordinatorProxy::RemoteScrollingCoordinatorProxy(WebPageProxy& webPageProxy)
48     : m_webPageProxy(webPageProxy)
49     , m_scrollingTree(RemoteScrollingTree::create(*this))
50     , m_requestedScrollInfo(nullptr)
51     , m_propagatesMainFrameScrolls(true)
52 {
53 }
54
55 RemoteScrollingCoordinatorProxy::~RemoteScrollingCoordinatorProxy()
56 {
57 }
58
59 ScrollingNodeID RemoteScrollingCoordinatorProxy::rootScrollingNodeID() const
60 {
61     if (!m_scrollingTree->rootNode())
62         return 0;
63
64     return m_scrollingTree->rootNode()->scrollingNodeID();
65 }
66
67 const RemoteLayerTreeHost* RemoteScrollingCoordinatorProxy::layerTreeHost() const
68 {
69     DrawingAreaProxy* drawingArea = m_webPageProxy.drawingArea();
70     if (!is<RemoteLayerTreeDrawingAreaProxy>(drawingArea)) {
71         ASSERT_NOT_REACHED();
72         return nullptr;
73     }
74
75     RemoteLayerTreeDrawingAreaProxy& remoteDrawingArea = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea);
76     return &remoteDrawingArea.remoteLayerTreeHost();
77 }
78
79 void RemoteScrollingCoordinatorProxy::commitScrollingTreeState(const RemoteScrollingCoordinatorTransaction& transaction, RequestedScrollInfo& requestedScrollInfo)
80 {
81     m_requestedScrollInfo = &requestedScrollInfo;
82
83     // FIXME: There must be a better idiom for this.
84     std::unique_ptr<ScrollingStateTree> stateTree(const_cast<RemoteScrollingCoordinatorTransaction&>(transaction).scrollingStateTree().release());
85
86     const RemoteLayerTreeHost* layerTreeHost = this->layerTreeHost();
87     if (!layerTreeHost) {
88         ASSERT_NOT_REACHED();
89         return;
90     }
91
92     connectStateNodeLayers(*stateTree, *layerTreeHost);
93     m_scrollingTree->commitTreeState(WTFMove(stateTree));
94
95     m_requestedScrollInfo = nullptr;
96 }
97
98 #if !PLATFORM(IOS)
99 void RemoteScrollingCoordinatorProxy::connectStateNodeLayers(ScrollingStateTree& stateTree, const RemoteLayerTreeHost& layerTreeHost)
100 {
101     for (auto& currNode : stateTree.nodeMap().values()) {
102         if (currNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))
103             currNode->setLayer(layerTreeHost.getLayer(currNode->layer()));
104
105         switch (currNode->nodeType()) {
106         case FrameScrollingNode: {
107             ScrollingStateFrameScrollingNode& scrollingStateNode = downcast<ScrollingStateFrameScrollingNode>(*currNode);
108             
109             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer))
110                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.getLayer(scrollingStateNode.scrolledContentsLayer()));
111
112             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer))
113                 scrollingStateNode.setCounterScrollingLayer(layerTreeHost.getLayer(scrollingStateNode.counterScrollingLayer()));
114
115             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer))
116                 scrollingStateNode.setInsetClipLayer(layerTreeHost.getLayer(scrollingStateNode.insetClipLayer()));
117
118             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer))
119                 scrollingStateNode.setContentShadowLayer(layerTreeHost.getLayer(scrollingStateNode.contentShadowLayer()));
120
121             // FIXME: we should never have header and footer layers coming from the WebProcess.
122             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderLayer))
123                 scrollingStateNode.setHeaderLayer(layerTreeHost.getLayer(scrollingStateNode.headerLayer()));
124
125             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterLayer))
126                 scrollingStateNode.setFooterLayer(layerTreeHost.getLayer(scrollingStateNode.footerLayer()));
127             break;
128         }
129         case OverflowScrollingNode: {
130             ScrollingStateOverflowScrollingNode& scrollingStateNode = downcast<ScrollingStateOverflowScrollingNode>(*currNode);
131
132             if (scrollingStateNode.hasChangedProperty(ScrollingStateOverflowScrollingNode::ScrolledContentsLayer))
133                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.getLayer(scrollingStateNode.scrolledContentsLayer()));
134             break;
135         }
136         case FixedNode:
137         case StickyNode:
138             break;
139         }
140     }
141 }
142 #endif
143
144 bool RemoteScrollingCoordinatorProxy::handleWheelEvent(const PlatformWheelEvent& event)
145 {
146     ScrollingTree::EventResult result = m_scrollingTree->tryToHandleWheelEvent(event);
147     return result == ScrollingTree::DidHandleEvent; // FIXME: handle other values.
148 }
149
150 TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint p) const
151 {
152     return m_scrollingTree->eventTrackingTypeForPoint(eventName, p);
153 }
154
155 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale)
156 {
157     m_scrollingTree->viewportChangedViaDelegatedScrolling(nodeID, fixedPositionRect, scale);
158 }
159
160 void RemoteScrollingCoordinatorProxy::currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID nodeID, unsigned horizontal, unsigned vertical)
161 {
162     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::CurrentSnapPointIndicesChangedForNode(nodeID, horizontal, vertical));
163 }
164
165 // This comes from the scrolling tree.
166 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
167 {
168     // Scroll updates for the main frame are sent via WebPageProxy::updateVisibleContentRects()
169     // so don't send them here.
170     if (!m_propagatesMainFrameScrolls && scrolledNodeID == rootScrollingNodeID())
171         return;
172
173 #if PLATFORM(IOS)
174     m_webPageProxy.overflowScrollViewDidScroll();
175 #endif
176     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition, scrollingLayerPositionAction));
177 }
178
179 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
180 {
181     if (scrolledNodeID == rootScrollingNodeID() && m_requestedScrollInfo) {
182         m_requestedScrollInfo->requestsScrollPositionUpdate = true;
183         m_requestedScrollInfo->requestIsProgrammaticScroll = representsProgrammaticScroll;
184         m_requestedScrollInfo->requestedScrollPosition = scrollPosition;
185     }
186 }
187
188 } // namespace WebKit
189
190 #endif // ENABLE(ASYNC_SCROLLING)