1/*
2 * Copyright (C) 2013, 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#ifndef ViewGestureController_h
27#define ViewGestureController_h
28
29#include "MessageReceiver.h"
30#include "SameDocumentNavigationType.h"
31#include "WeakObjCPtr.h"
32#include <WebCore/FloatRect.h>
33#include <wtf/RetainPtr.h>
34#include <wtf/RunLoop.h>
35
36OBJC_CLASS CALayer;
37
38#if PLATFORM(IOS)
39OBJC_CLASS UIView;
40OBJC_CLASS WKSwipeTransitionController;
41OBJC_CLASS WKWebView;
42OBJC_CLASS _UIViewControllerTransitionContext;
43OBJC_CLASS _UINavigationInteractiveTransitionBase;
44#else
45OBJC_CLASS NSEvent;
46OBJC_CLASS NSView;
47OBJC_CLASS WKSwipeCancellationTracker;
48#endif
49
50namespace WebCore {
51class IOSurface;
52}
53
54namespace WebKit {
55
56class ViewSnapshot;
57class WebBackForwardListItem;
58class WebPageProxy;
59
60class ViewGestureController : private IPC::MessageReceiver {
61    WTF_MAKE_NONCOPYABLE(ViewGestureController);
62public:
63    ViewGestureController(WebPageProxy&);
64    ~ViewGestureController();
65
66    enum class ViewGestureType {
67        None,
68#if PLATFORM(MAC)
69        Magnification,
70        SmartMagnification,
71#endif
72        Swipe
73    };
74
75    enum class SwipeTransitionStyle {
76        Overlap,
77        Push
78    };
79
80    enum class SwipeDirection {
81        Left,
82        Right
83    };
84
85    enum class PendingSwipeReason {
86        None,
87        WebCoreMayScroll,
88        InsufficientMagnitude
89    };
90
91#if PLATFORM(MAC)
92    double magnification() const;
93
94    void handleMagnificationGesture(double scale, WebCore::FloatPoint origin);
95    void handleSmartMagnificationGesture(WebCore::FloatPoint origin);
96
97    bool handleScrollWheelEvent(NSEvent *);
98    void wheelEventWasNotHandledByWebCore(NSEvent *);
99
100    void setCustomSwipeViews(Vector<RetainPtr<NSView>> views) { m_customSwipeViews = WTF::move(views); }
101    void setCustomSwipeViewsTopContentInset(float topContentInset) { m_customSwipeViewsTopContentInset = topContentInset; }
102    WebCore::FloatRect windowRelativeBoundsForCustomSwipeViews() const;
103    void setDidMoveSwipeSnapshotCallback(void(^)(CGRect));
104
105    void endActiveGesture();
106
107    bool shouldIgnorePinnedState() { return m_shouldIgnorePinnedState; }
108    void setShouldIgnorePinnedState(bool ignore) { m_shouldIgnorePinnedState = ignore; }
109
110    void didFirstVisuallyNonEmptyLayoutForMainFrame();
111    void didFinishLoadForMainFrame();
112    void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType);
113#else
114    void installSwipeHandler(UIView *gestureRecognizerView, UIView *swipingView);
115    void setAlternateBackForwardListSourceView(WKWebView *);
116    bool canSwipeInDirection(SwipeDirection);
117    void beginSwipeGesture(_UINavigationInteractiveTransitionBase *, SwipeDirection);
118    void endSwipeGesture(WebBackForwardListItem* targetItem, _UIViewControllerTransitionContext *, bool cancelled);
119    void willCommitPostSwipeTransitionLayerTree(bool);
120    void setRenderTreeSize(uint64_t);
121#endif
122
123    void removeSwipeSnapshot();
124
125private:
126    // IPC::MessageReceiver.
127    virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override;
128
129    void swipeSnapshotWatchdogTimerFired();
130
131#if PLATFORM(MAC)
132    // Message handlers.
133    void didCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds, bool frameHandlesMagnificationGesture);
134    void didCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool isReplacedElement, double viewportMinimumScale, double viewportMaximumScale);
135    void didHitRenderTreeSizeThreshold();
136    void removeSwipeSnapshotAfterRepaint();
137    void activeLoadMonitoringTimerFired();
138
139    void endMagnificationGesture();
140    WebCore::FloatPoint scaledMagnificationOrigin(WebCore::FloatPoint origin, double scale);
141
142    void trackSwipeGesture(NSEvent *, SwipeDirection);
143    void beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection);
144    void handleSwipeGesture(WebBackForwardListItem* targetItem, double progress, SwipeDirection);
145    void endSwipeGesture(WebBackForwardListItem* targetItem, bool cancelled);
146    bool deltaIsSufficientToBeginSwipe(NSEvent *);
147    bool scrollEventCanBecomeSwipe(NSEvent *, SwipeDirection&);
148    bool shouldUseSnapshotForSize(ViewSnapshot&, WebCore::FloatSize swipeLayerSize, float topContentInset);
149
150    CALayer *determineSnapshotLayerParent() const;
151    CALayer *determineLayerAdjacentToSnapshotForParent(SwipeDirection, CALayer *snapshotLayerParent) const;
152    void applyDebuggingPropertiesToSwipeViews();
153    void didMoveSwipeSnapshotLayer();
154#endif
155
156    WebPageProxy& m_webPageProxy;
157    ViewGestureType m_activeGestureType;
158
159    RunLoop::Timer<ViewGestureController> m_swipeWatchdogTimer;
160
161#if USE(IOSURFACE)
162    RefPtr<WebCore::IOSurface> m_currentSwipeSnapshotSurface;
163#endif
164
165#if PLATFORM(MAC)
166    RunLoop::Timer<ViewGestureController> m_swipeWatchdogAfterFirstVisuallyNonEmptyLayoutTimer;
167    RunLoop::Timer<ViewGestureController> m_swipeActiveLoadMonitoringTimer;
168
169    double m_magnification;
170    WebCore::FloatPoint m_magnificationOrigin;
171
172    WebCore::FloatRect m_lastSmartMagnificationUnscaledTargetRect;
173    bool m_lastMagnificationGestureWasSmartMagnification;
174    WebCore::FloatPoint m_lastSmartMagnificationOrigin;
175
176    WebCore::FloatRect m_visibleContentRect;
177    bool m_visibleContentRectIsValid;
178    bool m_frameHandlesMagnificationGesture;
179
180    RetainPtr<WKSwipeCancellationTracker> m_swipeCancellationTracker;
181    RetainPtr<CALayer> m_swipeLayer;
182    RetainPtr<CALayer> m_swipeSnapshotLayer;
183    Vector<RetainPtr<CALayer>> m_currentSwipeLiveLayers;
184
185    SwipeTransitionStyle m_swipeTransitionStyle;
186    Vector<RetainPtr<NSView>> m_customSwipeViews;
187    float m_customSwipeViewsTopContentInset;
188    WebCore::FloatRect m_currentSwipeCustomViewBounds;
189
190    // If we need to wait for content to decide if it is going to consume
191    // the scroll event that would have started a swipe, we'll fill these in.
192    PendingSwipeReason m_pendingSwipeReason;
193    SwipeDirection m_pendingSwipeDirection;
194    WebCore::FloatSize m_cumulativeDeltaForPendingSwipe;
195
196    void (^m_didMoveSwipeSnapshotCallback)(CGRect);
197
198    bool m_shouldIgnorePinnedState;
199
200    bool m_swipeWaitingForVisuallyNonEmptyLayout;
201    bool m_swipeWaitingForRenderTreeSizeThreshold;
202    bool m_swipeWaitingForRepaint;
203    bool m_swipeInProgress;
204#else
205    UIView *m_liveSwipeView;
206    RetainPtr<UIView> m_liveSwipeViewClippingView;
207    RetainPtr<UIView> m_snapshotView;
208    RetainPtr<UIView> m_transitionContainerView;
209    RetainPtr<WKSwipeTransitionController> m_swipeInteractiveTransitionDelegate;
210    uint64_t m_snapshotRemovalTargetRenderTreeSize;
211    bool m_shouldRemoveSnapshotWhenTargetRenderTreeSizeHit;
212    WeakObjCPtr<WKWebView> m_alternateBackForwardListSourceView;
213    RefPtr<WebPageProxy> m_webPageProxyForBackForwardListForCurrentSwipe;
214#endif
215};
216
217} // namespace WebKit
218
219#endif // ViewGestureController_h
220