[Mac] Implement basic hit testing in the scrolling tree
[WebKit-https.git] / Source / WebCore / page / scrolling / mac / ScrollingCoordinatorMac.mm
1 /*
2  * Copyright (C) 2011 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
28 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(MAC)
29
30 #import "ScrollingCoordinatorMac.h"
31
32 #include "Frame.h"
33 #include "FrameView.h"
34 #include "Logging.h"
35 #include "Page.h"
36 #include "PlatformWheelEvent.h"
37 #include "Region.h"
38 #include "ScrollingStateTree.h"
39 #include "ScrollingThread.h"
40 #include "ScrollingTreeFixedNode.h"
41 #include "ScrollingTreeFrameScrollingNodeMac.h"
42 #include "ScrollingTreeMac.h"
43 #include "ScrollingTreeStickyNode.h"
44 #include "TiledBacking.h"
45 #include <wtf/MainThread.h>
46
47 namespace WebCore {
48
49 Ref<ScrollingCoordinator> ScrollingCoordinator::create(Page* page)
50 {
51     return adoptRef(*new ScrollingCoordinatorMac(page));
52 }
53
54 ScrollingCoordinatorMac::ScrollingCoordinatorMac(Page* page)
55     : AsyncScrollingCoordinator(page)
56     , m_scrollingStateTreeCommitterTimer(*this, &ScrollingCoordinatorMac::commitTreeState)
57 {
58     setScrollingTree(ScrollingTreeMac::create(*this));
59 }
60
61 ScrollingCoordinatorMac::~ScrollingCoordinatorMac()
62 {
63     ASSERT(!scrollingTree());
64 }
65
66 void ScrollingCoordinatorMac::pageDestroyed()
67 {
68     AsyncScrollingCoordinator::pageDestroyed();
69
70     m_scrollingStateTreeCommitterTimer.stop();
71
72     // Invalidating the scrolling tree will break the reference cycle between the ScrollingCoordinator and ScrollingTree objects.
73     RefPtr<ThreadedScrollingTree> scrollingTree = static_pointer_cast<ThreadedScrollingTree>(releaseScrollingTree());
74     ScrollingThread::dispatch([scrollingTree] {
75         scrollingTree->invalidate();
76     });
77 }
78
79 void ScrollingCoordinatorMac::commitTreeStateIfNeeded()
80 {
81     commitTreeState();
82     m_scrollingStateTreeCommitterTimer.stop();
83 }
84
85 ScrollingEventResult ScrollingCoordinatorMac::handleWheelEvent(FrameView&, const PlatformWheelEvent& wheelEvent)
86 {
87     ASSERT(isMainThread());
88     ASSERT(m_page);
89
90     if (scrollingTree()->willWheelEventStartSwipeGesture(wheelEvent))
91         return ScrollingEventResult::DidNotHandleEvent;
92
93     RefPtr<ThreadedScrollingTree> threadedScrollingTree = downcast<ThreadedScrollingTree>(scrollingTree());
94     ScrollingThread::dispatch([threadedScrollingTree, wheelEvent] {
95         threadedScrollingTree->handleWheelEvent(wheelEvent);
96     });
97     return ScrollingEventResult::DidHandleEvent;
98 }
99
100 void ScrollingCoordinatorMac::scheduleTreeStateCommit()
101 {
102     ASSERT(scrollingStateTree()->hasChangedProperties() || eventTrackingRegionsDirty());
103
104     if (m_scrollingStateTreeCommitterTimer.isActive())
105         return;
106
107     LOG(Scrolling, "ScrollingCoordinatorMac::scheduleTreeStateCommit");
108     m_scrollingStateTreeCommitterTimer.startOneShot(0_s);
109 }
110
111 void ScrollingCoordinatorMac::commitTreeState()
112 {
113     willCommitTree();
114
115     LOG(Scrolling, "ScrollingCoordinatorMac::commitTreeState, has changes %d", scrollingStateTree()->hasChangedProperties());
116
117     if (!scrollingStateTree()->hasChangedProperties())
118         return;
119
120     LOG(Scrolling, "%s", scrollingStateTreeAsText(ScrollingStateTreeAsTextBehaviorDebug).utf8().data());
121
122     RefPtr<ThreadedScrollingTree> threadedScrollingTree = downcast<ThreadedScrollingTree>(scrollingTree());
123     ScrollingStateTree* unprotectedTreeState = scrollingStateTree()->commit(LayerRepresentation::PlatformLayerRepresentation).release();
124
125     ScrollingThread::dispatch([threadedScrollingTree, unprotectedTreeState] {
126         std::unique_ptr<ScrollingStateTree> treeState(unprotectedTreeState);
127         threadedScrollingTree->commitTreeState(WTFMove(treeState));
128     });
129
130     updateTiledScrollingIndicator();
131 }
132
133 void ScrollingCoordinatorMac::updateTiledScrollingIndicator()
134 {
135     FrameView* frameView = m_page->mainFrame().view();
136     if (!frameView)
137         return;
138     
139     TiledBacking* tiledBacking = frameView->tiledBacking();
140     if (!tiledBacking)
141         return;
142
143     ScrollingModeIndication indicatorMode;
144     if (shouldUpdateScrollLayerPositionSynchronously(*frameView))
145         indicatorMode = SynchronousScrollingBecauseOfStyleIndication;
146     else
147         indicatorMode = AsyncScrollingIndication;
148     
149     tiledBacking->setScrollingModeIndication(indicatorMode);
150 }
151
152 } // namespace WebCore
153
154 #endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(MAC)