summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 22:43:39 +0000
committerrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 22:43:39 +0000
commit9fc42652e59b3bbc94ba454467650e2fab987ead (patch)
treec04f927d0ddba308fe83994771d346e61c326cf2 /chrome
parent7b7b68ff19e6e56fa5f7f908ab7a6ef4ae55d043 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.h7
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.mm94
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.h4
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.mm25
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)