diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 22:43:39 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 22:43:39 +0000 |
commit | 9fc42652e59b3bbc94ba454467650e2fab987ead (patch) | |
tree | c04f927d0ddba308fe83994771d346e61c326cf2 /chrome | |
parent | 7b7b68ff19e6e56fa5f7f908ab7a6ef4ae55d043 (diff) | |
download | chromium_src-9fc42652e59b3bbc94ba454467650e2fab987ead.zip chromium_src-9fc42652e59b3bbc94ba454467650e2fab987ead.tar.gz chromium_src-9fc42652e59b3bbc94ba454467650e2fab987ead.tar.bz2 |
[Mac] Add two-finger gesture support for Lion, which respects the system preference.
BUG=78676
TEST=With two-finger gestures enabled, swipe left/right with two fingers. Page goes back/forward.
Review URL: http://codereview.chromium.org/7488023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93720 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
4 files changed, 128 insertions, 2 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index f36a9a9..5c11b8e 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h @@ -47,7 +47,6 @@ class TabContents; @class TabStripView; @class ToolbarController; - @interface BrowserWindowController : TabWindowController<NSUserInterfaceValidations, BookmarkBarControllerDelegate, @@ -96,6 +95,12 @@ class TabContents; // NO on growth. BOOL isShrinkingFromZoomed_; + // Touch event data for two-finger gestures. Only available on Lion or higher + // with two-finger gestures enabled in the Trackpad preferences. This will + // contain the NSTouch objects from |-beginGestureWithEvent:| keyed by the + // touch's |identity|. + scoped_nsobject<NSMutableDictionary> twoFingerGestureTouches_; + // The raw accumulated zoom value and the actual zoom increments made for an // an in-progress pinch gesture. CGFloat totalMagnifyGestureAmount_; diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index e1d8109..06cbcfb 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm @@ -5,6 +5,7 @@ #import "chrome/browser/ui/cocoa/browser_window_controller.h" #include <Carbon/Carbon.h> +#include <numeric> #include "base/command_line.h" #include "base/mac/mac_util.h" @@ -141,7 +142,6 @@ // longer indicate that the window is shrinking from an apparent zoomed state) // and if it's set we continue to constrain the resize. - @interface NSWindow (NSPrivateApis) // Note: These functions are private, use -[NSObject respondsToSelector:] // before calling them. @@ -152,6 +152,33 @@ @end +// Forward-declare symbols that are part of the 10.6 SDK. +#if !defined(MAC_OS_X_VERSION_10_6) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + +enum { + NSTouchPhaseBegan = 1U << 0, + NSTouchPhaseMoved = 1U << 1, + NSTouchPhaseStationary = 1U << 2, + NSTouchPhaseEnded = 1U << 3, + NSTouchPhaseCancelled = 1U << 4, + NSTouchPhaseTouching = NSTouchPhaseBegan | NSTouchPhaseMoved | + NSTouchPhaseStationary, + NSTouchPhaseAny = NSUIntegerMax +}; +typedef NSUInteger NSTouchPhase; + +@interface NSEvent (SnowLeopardDeclarations) +- (NSSet*)touchesMatchingPhase:(NSTouchPhase)phase inView:(NSView*)view; +@end + +@interface NSTouch : NSObject +- (NSPoint)normalizedPosition; +- (id<NSObject, NSCopying>)identity; +@end + +#endif // MAC_OS_X_VERSION_10_6 + // Provide the forward-declarations of new 10.7 SDK symbols so they can be // called when building with the 10.5 SDK. #if !defined(MAC_OS_X_VERSION_10_7) || \ @@ -1705,6 +1732,71 @@ typedef NSInteger NSWindowAnimationBehavior; - (void)beginGestureWithEvent:(NSEvent*)event { totalMagnifyGestureAmount_ = 0; currentZoomStepDelta_ = 0; + + // On Lion, there's support controlled by a System Preference for two- and + // three-finger navigational gestures. If set to allow three-finger gestures, + // the system gesture recognizer will automatically call |-swipeWithEvent:| + // and that will be handled as it would be on Snow Leopard. The two-finger + // gesture does not do this, so it must be manually recognized. See the note + // inside |-recognizeTwoFingerGestures| for detailed information on the + // interaction of the different preferences. + NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseAny + inView:nil]; + if ([self recognizeTwoFingerGestures] && [touches count] >= 2) { + twoFingerGestureTouches_.reset([[NSMutableDictionary alloc] init]); + for (NSTouch* touch in touches) { + [twoFingerGestureTouches_ setObject:touch forKey:touch.identity]; + } + } +} + +- (void)endGestureWithEvent:(NSEvent*)event { + // This method only needs to process gesture events for two-finger navigation. + if (!twoFingerGestureTouches_.get()) + return; + + // When a multi-touch gesture ends, only one touch will be in the "End" phase. + // Other touches will be in "Moved" or "Unknown" phases. So long as one is + // ended, which it is by virtue of this method being called, the gesture can + // be committed so long as the magnitude is great enough. + NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseAny + inView:nil]; + + // Store the touch data locally and reset the ivar so that new gestures can + // begin. + scoped_nsobject<NSDictionary> beginTouches( + twoFingerGestureTouches_.release()); + + // Construct a vector of magnitudes. Since gesture events do not have the + // |-deltaX| property set, this creates the X magnitude for each finger. + std::vector<CGFloat> magnitudes; + for (NSTouch* touch in touches) { + NSTouch* beginTouch = [beginTouches objectForKey:touch.identity]; + if (!beginTouch) + continue; + + // The |normalizedPosition| is scaled from (0,1). + magnitudes.push_back(touch.normalizedPosition.x - + beginTouch.normalizedPosition.x); + } + + // Need at least two points to gesture. + if (magnitudes.size() < 2) + return; + + CGFloat sum = std::accumulate(magnitudes.begin(), magnitudes.end(), 0.0f); + int command_id = 0; + if (sum > 0.3) + command_id = IDC_FORWARD; + else if (sum < -0.3) + command_id = IDC_BACK; + else + return; + + if (browser_->command_updater()->IsCommandEnabled(command_id)) { + browser_->ExecuteCommandWithDisposition(command_id, + event_utils::WindowOpenDispositionFromNSEvent(event)); + } } // Delegate method called when window is resized. diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index 48d39f6..5e9606b 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h @@ -119,6 +119,10 @@ // hacky code is necessary. - (void)setUpOSFullScreenButton; +// On Lion, Apple introduced a new gesture for navigating pages using two-finger +// gestures. Returns YES if two-finger gestures should be recognized. +- (BOOL)recognizeTwoFingerGestures; + @end // @interface BrowserWindowController(Private) diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 85b230f..577decf 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm @@ -5,6 +5,7 @@ #import "chrome/browser/ui/cocoa/browser_window_controller_private.h" #include "base/command_line.h" +#include "base/mac/mac_util.h" #import "base/memory/scoped_nsobject.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_service.h" @@ -543,4 +544,28 @@ willPositionSheet:(NSWindow*)sheet // TOOD(rsesek): Properly implement Lion fullscreen <http://crbug.com/74065>. } +- (BOOL)recognizeTwoFingerGestures { + // Lion or higher will have support for two-finger swipe gestures. + if (!base::mac::IsOSLionOrLater()) + return NO; + + // A note about preferences: + // On Lion System Preferences, the swipe gesture behavior is controlled by the + // setting in Trackpad --> More Gestures --> Swipe between pages. This setting + // has three values: + // A) Scroll left or right with two fingers. This should perform a cool + // scrolling animation, but doesn't yet <http://crbug.com/90228>. + // B) Swipe left or right with three fingers. + // C) Swipe with two or three fingers. + // + // The three-finger gesture is controlled by the integer preference + // |com.apple.trackpad.threeFingerHorizSwipeGesture|. Its value is 0 for (A) + // and 1 for (B, C). + // + // The two-finger gesture is controlled by the preference below and is boolean + // YES for (A, C) and NO for (B). + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + return [defaults boolForKey:@"AppleEnableSwipeNavigateWithScrolls"]; +} + @end // @implementation BrowserWindowController(Private) |