diff options
author | erikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-11 02:48:44 +0000 |
---|---|---|
committer | erikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-11 02:48:44 +0000 |
commit | 756d4dd9706d14afdc2465260b20e047b01deab2 (patch) | |
tree | 72c369b3b24d085d5bdc78d453c3b27e4aac21dd /content | |
parent | d66e2fd0194cf3a5155dd606c416e20107b9b21a (diff) | |
download | chromium_src-756d4dd9706d14afdc2465260b20e047b01deab2.zip chromium_src-756d4dd9706d14afdc2465260b20e047b01deab2.tar.gz chromium_src-756d4dd9706d14afdc2465260b20e047b01deab2.tar.bz2 |
Mac: History swiping can be cancelled with vertical motion.
Users accidentally initiate history swiping (which requires horizontal motion)
when they intend to scroll content (which requires vertical motion). Once the
browser enters history swiping mode, subsequent vertical motions are discarded.
This change causes the browser to continue to observe vertical motions, and if
the user's horizontal swipe gains sufficient vertical motion, breaks out of
history swipe mode and into content swipe mode.
This CL enables touch events for the RWHVMac. I stopped using the API
trackSwipeEventWithOptions, since the block callback discards vertical motion,
and the method prevents the window from receiving touches. Instead, I record
all touches received by the window, and manually track the user's horizontal
and/or vertical motion.
Another independent change is that 2-finger swipe zone required to initiate
horizontal swipe mode was reduced. (Diagonal 45 degree swipes now initiate
content scrolling, rather than history swiping).
BUG=138175
TEST=Populate the browser's navigation history by visiting many different urls.
Use a 2-finger horizontal swipe on the track pad to begin a back/forward
navigation. Without lifting your fingers, swipe vertically. The history swipe
should be cancelled, and the content on the page should be scrolled. This
change should not have any effect on existing vertical content scrolling.
Interesting edge cases: Users use both short horizontal 2-finger flicks, and
long horizontal 2-finger swipes to navigate forwards/backwards. This behavior
should not be affected. When the content does not occupy the full horizontal
space (try reducing the browser window horizontal size by dragging the right
side close to the left side), horizontal swipes should swipe the content
horizontally, rather than triggering the history-swipe mode.
Review URL: https://codereview.chromium.org/87573003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239976 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
3 files changed, 73 insertions, 10 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index aae648c..9b5de7f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -2013,7 +2013,6 @@ void RenderWidgetHostViewMac::FrameSwapped() { // RenderWidgetHostViewCocoa --------------------------------------------------- @implementation RenderWidgetHostViewCocoa - @synthesize selectedRange = selectedRange_; @synthesize suppressNextEscapeKeyUp = suppressNextEscapeKeyUp_; @synthesize markedRange = markedRange_; @@ -2022,6 +2021,7 @@ void RenderWidgetHostViewMac::FrameSwapped() { - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { self = [super initWithFrame:NSZeroRect]; if (self) { + self.acceptsTouchEvents = YES; editCommand_helper_.reset(new RenderWidgetHostViewMacEditCommandHelper); editCommand_helper_->AddEditingSelectorsToClass([self class]); @@ -2075,8 +2075,8 @@ void RenderWidgetHostViewMac::FrameSwapped() { } - (void)scrollOffsetPinnedToLeft:(BOOL)left toRight:(BOOL)right { - if (delegate_ && [delegate_ respondsToSelector: - @selector(scrollOffsetPinnedToLeft:toRight:)]) { + if (delegate_ && [delegate_ + respondsToSelector:@selector(scrollOffsetPinnedToLeft:toRight:)]) { [delegate_ scrollOffsetPinnedToLeft:left toRight:right]; } } @@ -2542,6 +2542,47 @@ void RenderWidgetHostViewMac::FrameSwapped() { } } +- (void)beginGestureWithEvent:(NSEvent*)event { + [delegate_ beginGestureWithEvent:event]; +} +- (void)endGestureWithEvent:(NSEvent*)event { + [delegate_ endGestureWithEvent:event]; +} +- (void)touchesMovedWithEvent:(NSEvent*)event { + [delegate_ touchesMovedWithEvent:event]; +} +- (void)touchesBeganWithEvent:(NSEvent*)event { + [delegate_ touchesBeganWithEvent:event]; +} +- (void)touchesCancelledWithEvent:(NSEvent*)event { + [delegate_ touchesCancelledWithEvent:event]; +} +- (void)touchesEndedWithEvent:(NSEvent*)event { + [delegate_ touchesEndedWithEvent:event]; +} + +// This method handles 2 different types of hardware events. +// (Apple does not distinguish between them). +// a. Scrolling the middle wheel of a mouse. +// b. Swiping on the track pad. +// +// This method is responsible for 2 types of behavior: +// a. Scrolling the content of window. +// b. Navigating forwards/backwards in history. +// +// This is a brief description of the logic: +// 1. If the content can be scrolled, scroll the content. +// (This requires a roundtrip to blink to determine whether the content +// can be scrolled.) +// Once this logic is triggered, the navigate logic cannot be triggered +// until the gesture finishes. +// 2. If the user is making a horizontal swipe, start the navigate +// forward/backwards UI. +// Once this logic is triggered, the user can either cancel or complete +// the gesture. If the user completes the gesture, all remaining touches +// are swallowed, and not allowed to scroll the content. If the user +// cancels the gesture, all remaining touches are forwarded to the content +// scroll logic. The user cannot trigger the navigation logic again. - (void)scrollWheel:(NSEvent*)event { if (delegate_ && [delegate_ respondsToSelector:@selector(handleEvent:)]) { BOOL handled = [delegate_ handleEvent:event]; @@ -2556,13 +2597,14 @@ void RenderWidgetHostViewMac::FrameSwapped() { if (base::mac::IsOSLionOrLater() && [event phase] == NSEventPhaseBegan && !endWheelMonitor_) { endWheelMonitor_ = - [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask - handler:^(NSEvent* blockEvent) { - [self shortCircuitScrollWheelEvent:blockEvent]; - return blockEvent; - }]; + [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask + handler:^(NSEvent* blockEvent) { + [self shortCircuitScrollWheelEvent:blockEvent]; + return blockEvent; + }]; } + // This is responsible for content scrolling! if (renderWidgetHostView_->render_widget_host_) { const WebMouseWheelEvent& webEvent = WebInputEventFactory::mouseWheelEvent(event, self); @@ -2994,8 +3036,9 @@ void RenderWidgetHostViewMac::FrameSwapped() { } - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { - if (delegate_ && [delegate_ respondsToSelector: - @selector(validateUserInterfaceItem:isValidItem:)]) { + if (delegate_ && + [delegate_ respondsToSelector:@selector(validateUserInterfaceItem: + isValidItem:)]) { BOOL valid; BOOL known = [delegate_ validateUserInterfaceItem:item isValidItem:&valid]; diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 69252d4..2515496 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -83,6 +83,12 @@ typedef NSUInteger NSEventPhase; - (void)gotUnhandledWheelEvent { unhandledWheelEventReceived_ = true; } +- (void)touchesBeganWithEvent:(NSEvent*)event{} +- (void)touchesMovedWithEvent:(NSEvent*)event{} +- (void)touchesCancelledWithEvent:(NSEvent*)event{} +- (void)touchesEndedWithEvent:(NSEvent*)event{} +- (void)beginGestureWithEvent:(NSEvent*)event{} +- (void)endGestureWithEvent:(NSEvent*)event{} @end diff --git a/content/public/browser/render_widget_host_view_mac_delegate.h b/content/public/browser/render_widget_host_view_mac_delegate.h index 4e79fcb..6bcf744 100644 --- a/content/public/browser/render_widget_host_view_mac_delegate.h +++ b/content/public/browser/render_widget_host_view_mac_delegate.h @@ -16,6 +16,7 @@ // Like any Objective-C delegate, it is not retained by the delegator object. // The delegator object will call the -viewGone: method when it is going away. +@class NSEvent; @protocol RenderWidgetHostViewMacDelegate @optional // Notification that the view is gone. @@ -41,6 +42,19 @@ - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item isValidItem:(BOOL*)valid; +@required +// Notification of when a gesture begins/ends. +- (void)beginGestureWithEvent:(NSEvent*)event; +- (void)endGestureWithEvent:(NSEvent*)event; + +// This is a low level API which provides touches associated with an event. +// It is used in conjunction with gestures to determine finger placement +// on the trackpad. +- (void)touchesMovedWithEvent:(NSEvent*)event; +- (void)touchesBeganWithEvent:(NSEvent*)event; +- (void)touchesCancelledWithEvent:(NSEvent*)event; +- (void)touchesEndedWithEvent:(NSEvent*)event; + @end #endif // CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_MAC_DELEGATE_H_ |