| Index: chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
|
| diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
|
| index c8ccabc5f5007c6327a02aecca8b464e84566808..1d3be093c79539a9078005b550536715c30e3257 100644
|
| --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
|
| +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
|
| @@ -49,6 +49,46 @@ BOOL forceMagicMouse = NO;
|
| // Returns whether the wheel event should be consumed, and not passed to the
|
| // renderer.
|
| - (BOOL)shouldConsumeWheelEvent:(NSEvent*)event;
|
| +
|
| +// Shows the history swiper overlay.
|
| +- (void)showHistoryOverlay:(history_swiper::NavigationDirection)direction;
|
| +
|
| +// Removes the history swiper overlay.
|
| +- (void)removeHistoryOverlay;
|
| +
|
| +// Returns YES if the event was consumed or NO if it should be passed on to the
|
| +// renderer. If |event| was generated by a Magic Mouse, this method forwards to
|
| +// handleMagicMouseWheelEvent. Otherwise, this method attempts to transition
|
| +// the state machine from kPending -> kPotential. If it performs the
|
| +// transition, it also shows the history overlay. In order for a history swipe
|
| +// gesture to be recognized, the transition must occur.
|
| +//
|
| +// There are 4 types of scroll wheel events:
|
| +// 1. Magic mouse swipe events.
|
| +// These are identical to magic trackpad events, except that there are no
|
| +// -[NSView touches*WithEvent:] callbacks. The only way to accurately
|
| +// track these events is with the `trackSwipeEventWithOptions:` API.
|
| +// scrollingDelta{X,Y} is not accurate over long distances (it is computed
|
| +// using the speed of the swipe, rather than just the distance moved by
|
| +// the fingers).
|
| +// 2. Magic trackpad swipe events.
|
| +// These are the most common history swipe events. The logic of this
|
| +// method is predominantly designed to handle this use case.
|
| +// 3. Traditional mouse scrollwheel events.
|
| +// These should not initiate scrolling. They can be distinguished by the
|
| +// fact that `phase` and `momentumPhase` both return NSEventPhaseNone.
|
| +// 4. Momentum swipe events.
|
| +// After a user finishes a swipe, the system continues to generate
|
| +// artificial callbacks. `phase` returns NSEventPhaseNone, but
|
| +// `momentumPhase` does not. Unfortunately, the callbacks don't work
|
| +// properly (OSX 10.9). Sometimes, the system start sending momentum swipe
|
| +// events instead of trackpad swipe events while the user is still
|
| +// 2-finger swiping.
|
| +- (BOOL)handleScrollWheelEvent:(NSEvent*)event;
|
| +
|
| +// Returns YES if the event was consumed or NO if it should be passed on to the
|
| +// renderer. Attempts to initiate history swiping for Magic Mouse events.
|
| +- (BOOL)handleMagicMouseWheelEvent:(NSEvent*)theEvent;
|
| @end
|
|
|
| @implementation HistorySwiper
|
| @@ -57,25 +97,21 @@ BOOL forceMagicMouse = NO;
|
| - (id)initWithDelegate:(id<HistorySwiperDelegate>)delegate {
|
| self = [super init];
|
| if (self) {
|
| - // Gesture ids start at 0.
|
| - currentGestureId_ = 0;
|
| - // No gestures have been processed
|
| - lastProcessedGestureId_ = -1;
|
| delegate_ = delegate;
|
| }
|
| return self;
|
| }
|
|
|
| - (void)dealloc {
|
| - [self endHistorySwipe];
|
| + [self removeHistoryOverlay];
|
| [super dealloc];
|
| }
|
|
|
| - (BOOL)handleEvent:(NSEvent*)event {
|
| - if ([event type] == NSScrollWheel)
|
| - return [self maybeHandleHistorySwiping:event];
|
| + if ([event type] != NSScrollWheel)
|
| + return NO;
|
|
|
| - return NO;
|
| + return [self handleScrollWheelEvent:event];
|
| }
|
|
|
| - (void)rendererHandledWheelEvent:(const blink::WebMouseWheelEvent&)event
|
| @@ -155,8 +191,14 @@ BOOL forceMagicMouse = NO;
|
| }
|
|
|
| - (void)updateGestureCurrentPointFromEvent:(NSEvent*)event {
|
| + NSPoint averagePosition = [self averagePositionInEvent:event];
|
| +
|
| + // If the start point is valid, then so is the current point.
|
| + if (gestureStartPointValid_)
|
| + gestureTotalY_ += fabs(averagePosition.y - gestureCurrentPoint_.y);
|
| +
|
| // Update the current point of the gesture.
|
| - gestureCurrentPoint_ = [self averagePositionInEvent:event];
|
| + gestureCurrentPoint_ = averagePosition;
|
|
|
| // If the gesture doesn't have a start point, set one.
|
| if (!gestureStartPointValid_) {
|
| @@ -170,10 +212,10 @@ BOOL forceMagicMouse = NO;
|
| // available after the gesture begins.
|
| - (void)touchesBeganWithEvent:(NSEvent*)event {
|
| receivingTouches_ = YES;
|
| - ++currentGestureId_;
|
|
|
| // Reset state pertaining to previous gestures.
|
| gestureStartPointValid_ = NO;
|
| + gestureTotalY_ = 0;
|
| mouseScrollDelta_ = NSZeroSize;
|
| beganEventUnconsumed_ = NO;
|
| recognitionState_ = history_swiper::kPending;
|
| @@ -194,7 +236,6 @@ BOOL forceMagicMouse = NO;
|
|
|
| - (void)touchesEndedWithEvent:(NSEvent*)event {
|
| receivingTouches_ = NO;
|
| -
|
| if (![self processTouchEventForHistorySwiping:event])
|
| return;
|
|
|
| @@ -205,8 +246,8 @@ BOOL forceMagicMouse = NO;
|
| if (finished)
|
| [self navigateBrowserInDirection:historySwipeDirection_];
|
|
|
| - // Remove the history overlay.
|
| - [self endHistorySwipe];
|
| + [self removeHistoryOverlay];
|
| +
|
| // The gesture was completed.
|
| recognitionState_ = history_swiper::kCompleted;
|
| }
|
| @@ -224,8 +265,6 @@ BOOL forceMagicMouse = NO;
|
| case history_swiper::kCompleted:
|
| return NO;
|
| case history_swiper::kPending:
|
| - [self updateGestureCurrentPointFromEvent:event];
|
| - return NO;
|
| case history_swiper::kPotential:
|
| case history_swiper::kTracking:
|
| break;
|
| @@ -240,6 +279,10 @@ BOOL forceMagicMouse = NO;
|
| return NO;
|
| }
|
|
|
| + // Don't do any more processing if the state machine is in the pending state.
|
| + if (recognitionState_ == history_swiper::kPending)
|
| + return NO;
|
| +
|
| if (recognitionState_ == history_swiper::kPotential) {
|
| // The user is in the process of doing history swiping. If the history
|
| // swipe has progressed sufficiently far, stop sending events to the
|
| @@ -259,7 +302,7 @@ BOOL forceMagicMouse = NO;
|
| // vertical swipe.
|
| - (BOOL)shouldCancelHorizontalSwipeWithCurrentPoint:(NSPoint)currentPoint
|
| startPoint:(NSPoint)startPoint {
|
| - CGFloat yDelta = fabs(currentPoint.y - startPoint.y);
|
| + CGFloat yDelta = gestureTotalY_;
|
| CGFloat xDelta = fabs(currentPoint.x - startPoint.x);
|
|
|
| // The gesture is pretty clearly more vertical than horizontal.
|
| @@ -278,11 +321,11 @@ BOOL forceMagicMouse = NO;
|
| }
|
|
|
| - (void)cancelHistorySwipe {
|
| - [self endHistorySwipe];
|
| + [self removeHistoryOverlay];
|
| recognitionState_ = history_swiper::kCancelled;
|
| }
|
|
|
| -- (void)endHistorySwipe {
|
| +- (void)removeHistoryOverlay {
|
| [historyOverlay_ dismiss];
|
| [historyOverlay_ release];
|
| historyOverlay_ = nil;
|
| @@ -323,19 +366,11 @@ BOOL forceMagicMouse = NO;
|
| return NO;
|
| }
|
|
|
| -// goForward indicates whether the user is starting a forward or backward
|
| -// history swipe.
|
| -// Creates and displays a history overlay controller.
|
| -// Responsible for cleaning up after itself when the gesture is finished.
|
| -// Responsible for starting a browser navigation if necessary.
|
| -// Does not prevent swipe events from propagating to other handlers.
|
| -- (void)beginHistorySwipeInDirection:
|
| - (history_swiper::NavigationDirection)direction
|
| - event:(NSEvent*)event {
|
| +- (void)showHistoryOverlay:(history_swiper::NavigationDirection)direction {
|
| // We cannot make any assumptions about the current state of the
|
| // historyOverlay_, since users may attempt to use multiple gesture input
|
| // devices simultaneously, which confuses Cocoa.
|
| - [self endHistorySwipe];
|
| + [self removeHistoryOverlay];
|
|
|
| HistoryOverlayController* historyOverlay = [[HistoryOverlayController alloc]
|
| initForMode:(direction == history_swiper::kForwards)
|
| @@ -343,11 +378,6 @@ BOOL forceMagicMouse = NO;
|
| : kHistoryOverlayModeBack];
|
| [historyOverlay showPanelForView:[delegate_ viewThatWantsHistoryOverlay]];
|
| historyOverlay_ = historyOverlay;
|
| -
|
| - // Record whether the user was swiping forwards or backwards.
|
| - historySwipeDirection_ = direction;
|
| - // Record the user's settings.
|
| - historySwipeDirectionInverted_ = [self isEventDirectionInverted:event];
|
| }
|
|
|
| - (BOOL)systemSettingsAllowHistorySwiping:(NSEvent*)event {
|
| @@ -383,9 +413,7 @@ BOOL forceMagicMouse = NO;
|
| }
|
| }
|
|
|
| -// We use an entirely different set of logic for magic mouse swipe events,
|
| -// since we do not get NSTouch callbacks.
|
| -- (BOOL)maybeHandleMagicMouseHistorySwiping:(NSEvent*)theEvent {
|
| +- (BOOL)handleMagicMouseWheelEvent:(NSEvent*)theEvent {
|
| // The 'trackSwipeEventWithOptions:' api doesn't handle momentum events.
|
| if ([theEvent phase] == NSEventPhaseNone)
|
| return NO;
|
| @@ -483,31 +511,7 @@ BOOL forceMagicMouse = NO;
|
| }];
|
| }
|
|
|
| -// Checks if |theEvent| should trigger history swiping, and if so, does
|
| -// history swiping. Returns YES if the event was consumed or NO if it should
|
| -// be passed on to the renderer.
|
| -//
|
| -// There are 4 types of scroll wheel events:
|
| -// 1. Magic mouse swipe events.
|
| -// These are identical to magic trackpad events, except that there are no
|
| -// NSTouch callbacks. The only way to accurately track these events is
|
| -// with the `trackSwipeEventWithOptions:` API. scrollingDelta{X,Y} is not
|
| -// accurate over long distances (it is computed using the speed of the
|
| -// swipe, rather than just the distance moved by the fingers).
|
| -// 2. Magic trackpad swipe events.
|
| -// These are the most common history swipe events. Our logic is
|
| -// predominantly designed to handle this use case.
|
| -// 3. Traditional mouse scrollwheel events.
|
| -// These should not initiate scrolling. They can be distinguished by the
|
| -// fact that `phase` and `momentumPhase` both return NSEventPhaseNone.
|
| -// 4. Momentum swipe events.
|
| -// After a user finishes a swipe, the system continues to generate
|
| -// artificial callbacks. `phase` returns NSEventPhaseNone, but
|
| -// `momentumPhase` does not. Unfortunately, the callbacks don't work
|
| -// properly (OSX 10.9). Sometimes, the system start sending momentum swipe
|
| -// events instead of trackpad swipe events while the user is still
|
| -// 2-finger swiping.
|
| -- (BOOL)maybeHandleHistorySwiping:(NSEvent*)theEvent {
|
| +- (BOOL)handleScrollWheelEvent:(NSEvent*)theEvent {
|
| if (![theEvent respondsToSelector:@selector(phase)])
|
| return NO;
|
|
|
| @@ -520,8 +524,7 @@ BOOL forceMagicMouse = NO;
|
| }
|
|
|
| // We've already processed this gesture.
|
| - if (lastProcessedGestureId_ == currentGestureId_ &&
|
| - recognitionState_ != history_swiper::kPending) {
|
| + if (recognitionState_ != history_swiper::kPending) {
|
| return [self shouldConsumeWheelEvent:theEvent];
|
| }
|
|
|
| @@ -546,7 +549,7 @@ BOOL forceMagicMouse = NO;
|
| // callbacks to perform history swiping, magic mouse swipe events use an
|
| // entirely different set of logic.
|
| if ((inGesture_ && !receivingTouches_) || forceMagicMouse)
|
| - return [self maybeHandleMagicMouseHistorySwiping:theEvent];
|
| + return [self handleMagicMouseWheelEvent:theEvent];
|
|
|
| // The scrollWheel: callback is only relevant if it happens while the user is
|
| // still actively using the touchpad.
|
| @@ -573,9 +576,10 @@ BOOL forceMagicMouse = NO;
|
| if (!browserCanMove)
|
| return NO;
|
|
|
| - lastProcessedGestureId_ = currentGestureId_;
|
| - [self beginHistorySwipeInDirection:direction event:theEvent];
|
| + historySwipeDirection_ = direction;
|
| + historySwipeDirectionInverted_ = [self isEventDirectionInverted:theEvent];
|
| recognitionState_ = history_swiper::kPotential;
|
| + [self showHistoryOverlay:direction];
|
| return [self shouldConsumeWheelEvent:theEvent];
|
| }
|
|
|
| @@ -594,6 +598,7 @@ BOOL forceMagicMouse = NO;
|
| return event.scrollingDeltaY == 0;
|
| }
|
| }
|
| +
|
| @end
|
|
|
| @implementation HistorySwiper (PrivateExposedForTesting)
|
|
|