3f86de0720ac11f67363add83329a7ff1d0c5ffe
[WebKit-https.git] / Source / WebKit / UIProcess / RemoteLayerTree / 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/ScrollingStatePositionedNode.h>
41 #include <WebCore/ScrollingStateTree.h>
42 #include <WebCore/ScrollingTreeScrollingNode.h>
43
44 namespace WebKit {
45 using namespace WebCore;
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_FAMILY)
99
100 void RemoteScrollingCoordinatorProxy::connectStateNodeLayers(ScrollingStateTree& stateTree, const RemoteLayerTreeHost& layerTreeHost)
101 {
102     for (auto& currNode : stateTree.nodeMap().values()) {
103         if (currNode->hasChangedProperty(ScrollingStateNode::Layer))
104             currNode->setLayer(layerTreeHost.layerForID(currNode->layer()));
105
106         switch (currNode->nodeType()) {
107         case ScrollingNodeType::MainFrame:
108         case ScrollingNodeType::Subframe: {
109             ScrollingStateFrameScrollingNode& scrollingStateNode = downcast<ScrollingStateFrameScrollingNode>(*currNode);
110             
111             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer))
112                 scrollingStateNode.setScrollContainerLayer(layerTreeHost.layerForID(scrollingStateNode.scrollContainerLayer()));
113
114             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
115                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.layerForID(scrollingStateNode.scrolledContentsLayer()));
116
117             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer))
118                 scrollingStateNode.setCounterScrollingLayer(layerTreeHost.layerForID(scrollingStateNode.counterScrollingLayer()));
119
120             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::InsetClipLayer))
121                 scrollingStateNode.setInsetClipLayer(layerTreeHost.layerForID(scrollingStateNode.insetClipLayer()));
122
123             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::ContentShadowLayer))
124                 scrollingStateNode.setContentShadowLayer(layerTreeHost.layerForID(scrollingStateNode.contentShadowLayer()));
125
126             // FIXME: we should never have header and footer layers coming from the WebProcess.
127             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderLayer))
128                 scrollingStateNode.setHeaderLayer(layerTreeHost.layerForID(scrollingStateNode.headerLayer()));
129
130             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterLayer))
131                 scrollingStateNode.setFooterLayer(layerTreeHost.layerForID(scrollingStateNode.footerLayer()));
132
133             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::VerticalScrollbarLayer))
134                 scrollingStateNode.setVerticalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.verticalScrollbarLayer()));
135
136             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HorizontalScrollbarLayer))
137                 scrollingStateNode.setHorizontalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.horizontalScrollbarLayer()));
138
139             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::RootContentsLayer))
140                 scrollingStateNode.setRootContentsLayer(layerTreeHost.layerForID(scrollingStateNode.rootContentsLayer()));
141             break;
142         }
143         case ScrollingNodeType::Overflow: {
144             ScrollingStateOverflowScrollingNode& scrollingStateNode = downcast<ScrollingStateOverflowScrollingNode>(*currNode);
145             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer))
146                 scrollingStateNode.setScrollContainerLayer(layerTreeHost.layerForID(scrollingStateNode.scrollContainerLayer()));
147
148             if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrolledContentsLayer))
149                 scrollingStateNode.setScrolledContentsLayer(layerTreeHost.layerForID(scrollingStateNode.scrolledContentsLayer()));
150
151             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::VerticalScrollbarLayer))
152                 scrollingStateNode.setVerticalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.verticalScrollbarLayer()));
153
154             if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HorizontalScrollbarLayer))
155                 scrollingStateNode.setHorizontalScrollbarLayer(layerTreeHost.layerForID(scrollingStateNode.horizontalScrollbarLayer()));
156             break;
157         }
158         case ScrollingNodeType::FrameHosting:
159         case ScrollingNodeType::Fixed:
160         case ScrollingNodeType::Sticky:
161         case ScrollingNodeType::Positioned:
162             break;
163         }
164     }
165 }
166 #endif
167
168 bool RemoteScrollingCoordinatorProxy::handleWheelEvent(const PlatformWheelEvent& event)
169 {
170     ScrollingEventResult result = m_scrollingTree->tryToHandleWheelEvent(event);
171     return result == ScrollingEventResult::DidHandleEvent; // FIXME: handle other values.
172 }
173
174 void RemoteScrollingCoordinatorProxy::handleMouseEvent(const WebCore::PlatformMouseEvent& event)
175 {
176     m_scrollingTree->handleMouseEvent(event);
177 }
178
179 TrackingType RemoteScrollingCoordinatorProxy::eventTrackingTypeForPoint(const AtomicString& eventName, IntPoint p) const
180 {
181     return m_scrollingTree->eventTrackingTypeForPoint(eventName, p);
182 }
183
184 void RemoteScrollingCoordinatorProxy::viewportChangedViaDelegatedScrolling(const FloatPoint& scrollPosition, const FloatRect& layoutViewport, double scale)
185 {
186     m_scrollingTree->mainFrameViewportChangedViaDelegatedScrolling(scrollPosition, layoutViewport, scale);
187 }
188
189 void RemoteScrollingCoordinatorProxy::applyScrollingTreeLayerPositions()
190 {
191     m_scrollingTree->applyLayerPositions();
192 }
193
194 void RemoteScrollingCoordinatorProxy::currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID nodeID, unsigned horizontal, unsigned vertical)
195 {
196     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::CurrentSnapPointIndicesChangedForNode(nodeID, horizontal, vertical));
197 }
198
199 // This comes from the scrolling tree.
200 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, ScrollingLayerPositionAction scrollingLayerPositionAction)
201 {
202     // Scroll updates for the main frame are sent via WebPageProxy::updateVisibleContentRects()
203     // so don't send them here.
204     if (!m_propagatesMainFrameScrolls && scrolledNodeID == rootScrollingNodeID())
205         return;
206
207     if (m_webPageProxy.scrollingUpdatesDisabledForTesting())
208         return;
209
210 #if PLATFORM(IOS_FAMILY)
211     m_webPageProxy.scrollingNodeScrollViewDidScroll();
212 #endif
213     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition, scrollingLayerPositionAction == ScrollingLayerPositionAction::Sync));
214 }
215
216 void RemoteScrollingCoordinatorProxy::scrollingTreeNodeRequestsScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
217 {
218     if (scrolledNodeID == rootScrollingNodeID() && m_requestedScrollInfo) {
219         m_requestedScrollInfo->requestsScrollPositionUpdate = true;
220         m_requestedScrollInfo->requestIsProgrammaticScroll = representsProgrammaticScroll;
221         m_requestedScrollInfo->requestedScrollPosition = scrollPosition;
222     }
223 }
224
225 String RemoteScrollingCoordinatorProxy::scrollingTreeAsText() const
226 {
227     if (m_scrollingTree)
228         return m_scrollingTree->scrollingTreeAsText();
229     
230     return emptyString();
231 }
232
233 #if ENABLE(POINTER_EVENTS)
234 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataAtPoint(const IntPoint p) const
235 {
236     return m_scrollingTree->touchActionDataAtPoint(p);
237 }
238
239 Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID(ScrollingNodeID scrollingNodeID) const
240 {
241     for (auto& touchActionData : m_touchActionDataByTouchIdentifier.values()) {
242         if (touchActionData.scrollingNodeID == scrollingNodeID)
243             return touchActionData;
244     }
245     return WTF::nullopt;
246 }
247
248 void RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier(TouchActionData touchActionData, unsigned touchIdentifier)
249 {
250     m_touchActionDataByTouchIdentifier.set(touchIdentifier, touchActionData);
251 }
252
253 void RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier(unsigned touchIdentifier)
254 {
255     m_touchActionDataByTouchIdentifier.remove(touchIdentifier);
256 }
257
258 #endif
259
260 } // namespace WebKit
261
262 #endif // ENABLE(ASYNC_SCROLLING)