Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Unified Diff: chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm

Issue 657323003: Mac: Don't allow history swiping after substantial vertical motion. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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)

Powered by Google App Engine
This is Rietveld 408576698