| Index: chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
|
| diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
|
| index c9ad41d24aa20bcb7e999a5f36361328c4f687cc..75746c4150f6ea20f906db8941a5fe902d55a6df 100644
|
| --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
|
| +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
|
| @@ -7,6 +7,10 @@
|
|
|
| #import <Cocoa/Cocoa.h>
|
|
|
| +namespace blink {
|
| +class WebMouseWheelEvent;
|
| +}
|
| +
|
| @class HistorySwiper;
|
| @protocol HistorySwiperDelegate
|
| // Return NO from this method is the view/render_widget_host should not
|
| @@ -21,33 +25,92 @@ enum NavigationDirection {
|
| kBackwards = 0,
|
| kForwards,
|
| };
|
| +enum RecognitionState {
|
| + // Waiting to see whether the renderer will handle the event with phase
|
| + // NSEventPhaseBegan. The state machine will also stay in this state if
|
| + // external conditions prohibit the initialization of history swiping. New
|
| + // gestures always start in this state.
|
| + // Events are forwarded to the renderer.
|
| + kPending,
|
| + // The gesture looks like the beginning of a history swipe.
|
| + // Events are forwarded to the renderer.
|
| + // The history overlay is visible.
|
| + kPotential,
|
| + // The gesture is definitely a history swipe.
|
| + // Events are not forwarded to the renderer.
|
| + // The history overlay is visible.
|
| + kTracking,
|
| + // The history swipe gesture has finished.
|
| + // Events are not forwarded to the renderer.
|
| + kCompleted,
|
| + // The history swipe gesture was cancelled.
|
| + // Events are forwarded to the renderer.
|
| + kCancelled,
|
| +};
|
| } // history_swiper
|
|
|
| -// Responsible for maintaining state for 2-finger swipe history navigation.
|
| -// Relevant blink/NSWindow touch events must be passed to this class.
|
| -// We want to be able to cancel history swipes if the user's swipe has a lot of
|
| -// vertical motion. The API [NSEvent trackSwipeEventWithOptions] doesn't give
|
| -// vertical swipe distance, and it swallows the touch events so that we can't
|
| -// independently gather them either. Instead of using that api, we manually
|
| -// track all touch events using the low level APIs touches*WithEvent:
|
| +// History swiping is the feature wherein a horizontal 2-finger swipe of of a
|
| +// trackpad causes the browser to navigate forwards or backwards.
|
| +// Unfortunately, the act of 2-finger swiping is overloaded, and has 3 possible
|
| +// effects. In descending order of priority, the swipe should:
|
| +// 1. Scroll the content on the web page.
|
| +// 2. Perform a history swipe.
|
| +// 3. Rubberband/overscroll the content past the edge of the window.
|
| +// Effects (1) and (3) are managed by the renderer, whereas effect (2) is
|
| +// managed by this class.
|
| +//
|
| +// Touches on the trackpad enter the run loop as NSEvents, grouped into
|
| +// gestures. The phases of NSEvents within a gesture follow a well defined
|
| +// order.
|
| +// 1. NSEventPhaseMayBegin. (exactly 1 event with this phase)
|
| +// 2. NSEventPhaseBegan. (exactly 1 event with this phase)
|
| +// 3. NSEventPhaseMoved. (many events with this phase)
|
| +// 4. NSEventPhaseEnded. (exactly 1 event with this phase)
|
| +// Events with the phase NSEventPhaseCancelled may come in at any time, and
|
| +// generally mean that an entity within the Cocoa framework has consumed the
|
| +// gesture, and wants to "cancel" previous NSEvents that have been passed to
|
| +// this class.
|
| +//
|
| +// The event handling stack in Chrome passes all events to this class, which is
|
| +// given the opportunity to process and consume the event. If the event is not
|
| +// consumed, it is passed to the renderer via IPC. The renderer returns an IPC
|
| +// indicating whether the event was consumed. To prevent spamming the renderer
|
| +// with IPCs, the browser waits for an ACK from the renderer from the previous
|
| +// event before sending the next one. While waiting for an ACK, the browser
|
| +// coalesces NSEvents with the same phase. It is common for dozens of events
|
| +// with the phase NSEventPhaseMoved to be coalesced.
|
| +//
|
| +// It is difficult to determine from the initial events in a gesture whether
|
| +// the gesture was intended to be a history swipe. The loss of information from
|
| +// the coalescing of events with phase NSEventPhaseMoved before they are passed
|
| +// to the renderer is also problematic. The general approach is as follows:
|
| +// 1. Wait for the renderer to return an ACK for the event with phase
|
| +// NSEventPhaseBegan. If that event was not consumed, change the state to
|
| +// kPotential. If the renderer is not certain about whether the event should
|
| +// be consumed, it tries to not consume the event.
|
| +// 2. In the state kPotential, this class will process events and update its
|
| +// internal state machine, but it will also continue to pass events to the
|
| +// renderer. This class tries to aggressively cancel history swiping to make
|
| +// up for the fact that the renderer errs on the side of allowing history
|
| +// swiping to occur.
|
| +// 3. As more events come in, if the gesture continues to appear horizontal,
|
| +// then this class will transition to the state kTracking. Events are
|
| +// consumed, and not passed to the renderer.
|
| +//
|
| +// There are multiple APIs that provide information about gestures on the
|
| +// trackpad. This class uses two different set of APIs.
|
| +// 1. The -[NSView touches*WithEvent:] APIs provide detailed information
|
| +// about the touches within a gesture. The callbacks happen with more
|
| +// frequency, and have higher accuracy. These APIs are used to transition
|
| +// between all state, exception for kPending -> kPotential.
|
| +// 2. The -[NSView scrollWheel:] API provides less information, but the
|
| +// events are passed to the renderer. This class must process these events so
|
| +// that it can decide whether to consume the events and prevent them from
|
| +// being passed to the renderer. This API is used to transition from kPending
|
| +// -> kPotential.
|
| @class HistoryOverlayController;
|
| @interface HistorySwiper : NSObject {
|
| @private
|
| - // If the viewport is scrolled all the way to the left or right.
|
| - // Used for history swiping.
|
| - BOOL isPinnedLeft_;
|
| - BOOL isPinnedRight_;
|
| -
|
| - // If the main frame has a horizontal scrollbar.
|
| - // Used for history swiping.
|
| - BOOL hasHorizontalScrollbar_;
|
| -
|
| - // If a scroll event came back unhandled from the renderer. Set to |NO| at
|
| - // the start of a scroll gesture, and then to |YES| if a scroll event comes
|
| - // back unhandled from the renderer.
|
| - // Used for history swiping.
|
| - BOOL gotUnhandledWheelEvent_;
|
| -
|
| // This controller will exist if and only if the UI is in history swipe mode.
|
| HistoryOverlayController* historyOverlay_;
|
| // Each gesture received by the window is given a unique id.
|
| @@ -66,14 +129,16 @@ enum NavigationDirection {
|
| int gestureStartPointValid_;
|
| // The id of the last gesture that we processed as a history swipe.
|
| int lastProcessedGestureId_;
|
| - // A flag that indicates that we cancelled the history swipe for the current
|
| - // gesture.
|
| - BOOL historySwipeCancelled_;
|
| // A flag that indicates the user's intended direction with the history swipe.
|
| history_swiper::NavigationDirection historySwipeDirection_;
|
| // A flag that indicates whether the gesture has its direction inverted.
|
| BOOL historySwipeDirectionInverted_;
|
|
|
| + // Whether the event with phase NSEventPhaseBegan was not consumed by the
|
| + // renderer. This variables defaults to NO for new gestures.
|
| + BOOL beganEventUnconsumed_;
|
| + history_swiper::RecognitionState recognitionState_;
|
| +
|
| id<HistorySwiperDelegate> delegate_;
|
|
|
| // Magic mouse and touchpad swipe events are identical except magic mouse
|
| @@ -95,9 +160,8 @@ enum NavigationDirection {
|
| // NSScrollWheel. We look at the phase to determine whether to trigger history
|
| // swiping
|
| - (BOOL)handleEvent:(NSEvent*)event;
|
| -- (void)gotUnhandledWheelEvent;
|
| -- (void)scrollOffsetPinnedToLeft:(BOOL)left toRight:(BOOL)right;
|
| -- (void)setHasHorizontalScrollbar:(BOOL)hasHorizontalScrollbar;
|
| +- (void)rendererHandledWheelEvent:(const blink::WebMouseWheelEvent&)event
|
| + consumed:(BOOL)consumed;
|
|
|
| // The event passed in is a gesture event, and has touch data associated with
|
| // the trackpad.
|
|
|