Chromium Code Reviews| Index: chrome/browser/ui/cocoa/browser_window_controller.mm |
| diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm |
| index e1d8109199c0f37b0dae5e53b03e584bb728429c..70ed3644d5df0888278302440d4a2d64cb72b7dd 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. |
| @@ -1705,6 +1705,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 recogniezd. See the note |
|
Nico
2011/07/22 20:21:14
recognized
mnemonic: "i before e except around z"
Robert Sesek
2011/07/22 20:26:23
I fixed sooo many typos before I uploaded this. I'
|
| + // 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. |
|
Nico
2011/07/22 20:21:14
So two-finger drag followed by lifting one finger
Robert Sesek
2011/07/22 20:26:23
Yeah; it's funky but is also what Safari does. I t
|
| + 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; |
|
Nico
2011/07/22 20:21:14
Does this ever happen in practice? I'd assume ever
Robert Sesek
2011/07/22 20:26:23
Yes, it can. You can add new fingers mid-gesture.
|
| + |
| + // The |normalizedPosition| scaled from (0,1). |
|
Nico
2011/07/22 20:21:14
"is scaled"?
Robert Sesek
2011/07/22 20:26:23
Done.
|
| + 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. |