chrome_render_widget_host_view_mac_history_swiper.h revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_RENDERER_HOST_CHROME_RENDER_WIDGET_HOST_VIEW_MAC_HISTORY_SWIPER_
6#define CHROME_BROWSER_RENDERER_HOST_CHROME_RENDER_WIDGET_HOST_VIEW_MAC_HISTORY_SWIPER_
7
8#import <Cocoa/Cocoa.h>
9
10@class HistorySwiper;
11@protocol HistorySwiperDelegate
12// Return NO from this method is the view/render_widget_host should not
13// allow history swiping.
14- (BOOL)shouldAllowHistorySwiping;
15// The history overlay is added to the view returning from this method.
16- (NSView*)viewThatWantsHistoryOverlay;
17@end
18
19namespace history_swiper {
20
21enum NavigationDirection {
22  kBackwards = 0,
23  kForwards,
24};
25
26enum GestureHandledState {
27  kPending,    // Still waiting to determine whether the gesture was handled.
28  kHandled,    // At least 1 event in the gesture was handled by blink.
29  kUnhandled,  // No events so far have been handled by blink.
30};
31
32} // history_swiper
33
34// Responsible for maintaining state for 2-finger swipe history navigation.
35// Relevant blink/NSWindow touch events must be passed to this class.
36// We want to be able to cancel history swipes if the user's swipe has a lot of
37// vertical motion. The API [NSEvent trackSwipeEventWithOptions] doesn't give
38// vertical swipe distance, and it swallows the touch events so that we can't
39// independently gather them either. Instead of using that api, we manually
40// track all touch events using the low level APIs touches*WithEvent:
41@class HistoryOverlayController;
42@interface HistorySwiper : NSObject {
43 @private
44  // Whether blink has handled the gesture.  This enum gets reset to kPending
45  // whenever a new gesture starts.  History swiping is only enabled if blink
46  // has never handled any of the events in the gesture.
47  history_swiper::GestureHandledState gestureHandledState_;
48
49  // This controller will exist if and only if the UI is in history swipe mode.
50  HistoryOverlayController* historyOverlay_;
51  // Each gesture received by the window is given a unique id.
52  // The id is monotonically increasing.
53  int currentGestureId_;
54  // The location of the fingers when the gesture started.
55  NSPoint gestureStartPoint_;
56  // The current location of the fingers in the gesture.
57  NSPoint gestureCurrentPoint_;
58  // A flag that indicates that there is an ongoing gesture.
59  // The method [NSEvent touchesMatchingPhase:inView:] is only valid for events
60  // that are part of a gesture.
61  BOOL inGesture_;
62  // Each time a new gesture begins, we must get a new start point.
63  // This ivar determines whether the start point is valid.
64  int gestureStartPointValid_;
65  // The id of the last gesture that we processed as a history swipe.
66  int lastProcessedGestureId_;
67  // A flag that indicates that we cancelled the history swipe for the current
68  // gesture.
69  BOOL historySwipeCancelled_;
70  // A flag that indicates the user's intended direction with the history swipe.
71  history_swiper::NavigationDirection historySwipeDirection_;
72  // A flag that indicates whether the gesture has its direction inverted.
73  BOOL historySwipeDirectionInverted_;
74
75  id<HistorySwiperDelegate> delegate_;
76
77  // Magic mouse and touchpad swipe events are identical except magic mouse
78  // events do not generate NSTouch callbacks. Since we rely on NSTouch
79  // callbacks to determine vertical scrolling, magic mouse swipe events use an
80  // entirely different set of logic.
81  //
82  // The two event types do not play well together. Just calling the API
83  // `[NSEvent trackSwipeEventWithOptions:]` will block touches{Began, Moved, *}
84  // callbacks for a non-deterministic period of time (even after the swipe has
85  // completed).
86  BOOL receivedTouch_;
87  // Cumulative scroll delta since scroll gesture start. Only valid during
88  // scroll gesture handling. Used for history swiping.
89  NSSize mouseScrollDelta_;
90}
91
92// Many event types are passed in, but the only one we care about is
93// NSScrollWheel. We look at the phase to determine whether to trigger history
94// swiping
95- (BOOL)handleEvent:(NSEvent*)event;
96- (void)gotWheelEventConsumed:(BOOL)consumed;
97
98// The event passed in is a gesture event, and has touch data associated with
99// the trackpad.
100- (void)touchesBeganWithEvent:(NSEvent*)event;
101- (void)touchesMovedWithEvent:(NSEvent*)event;
102- (void)touchesCancelledWithEvent:(NSEvent*)event;
103- (void)touchesEndedWithEvent:(NSEvent*)event;
104- (void)beginGestureWithEvent:(NSEvent*)event;
105- (void)endGestureWithEvent:(NSEvent*)event;
106
107// These methods control whether a given view is allowed to rubberband in the
108// given direction. This is inversely related to whether the view is allowed to
109// 2-finger history swipe in the given direction.
110- (BOOL)canRubberbandLeft:(NSView*)view;
111- (BOOL)canRubberbandRight:(NSView*)view;
112
113// Designated initializer.
114- (id)initWithDelegate:(id<HistorySwiperDelegate>)delegate;
115
116@property (nonatomic, assign) id<HistorySwiperDelegate> delegate;
117
118@end
119
120// Exposed only for unit testing, do not call directly.
121@interface HistorySwiper (PrivateExposedForTesting)
122+ (void)resetMagicMouseState;
123@end
124
125#endif // CHROME_BROWSER_RENDERER_HOST_CHROME_RENDER_WIDGET_HOST_VIEW_MAC_HISTORY_SWIPER_
126