Index: ui/message_center/cocoa/popup_controller.mm |
diff --git a/ui/message_center/cocoa/popup_controller.mm b/ui/message_center/cocoa/popup_controller.mm |
index f574fc08062d87bb0ea1ba5d4ce5b43e124436c0..05635b7ce66713b4c7c04fe36a023ca819e0edb4 100644 |
--- a/ui/message_center/cocoa/popup_controller.mm |
+++ b/ui/message_center/cocoa/popup_controller.mm |
@@ -4,6 +4,9 @@ |
#import "ui/message_center/cocoa/popup_controller.h" |
+#include <cmath> |
+ |
+#import "base/mac/foundation_util.h" |
#import "ui/base/cocoa/window_size_constants.h" |
#import "ui/message_center/cocoa/notification_controller.h" |
#include "ui/message_center/message_center.h" |
@@ -13,21 +16,117 @@ |
enum { |
NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 |
}; |
+ |
+enum { |
Robert Sesek
2013/05/22 23:54:29
This is copied verbatim from RenderWidgetHostViewD
Nico
2013/05/23 01:02:56
Probably a good idea. Can be in a follow-up if you
|
+ NSEventPhaseNone = 0, // event not associated with a phase. |
+ NSEventPhaseBegan = 0x1 << 0, |
+ NSEventPhaseStationary = 0x1 << 1, |
+ NSEventPhaseChanged = 0x1 << 2, |
+ NSEventPhaseEnded = 0x1 << 3, |
+ NSEventPhaseCancelled = 0x1 << 4, |
+}; |
+typedef NSUInteger NSEventPhase; |
+ |
+enum { |
+ NSEventSwipeTrackingLockDirection = 0x1 << 0, |
+ NSEventSwipeTrackingClampGestureAmount = 0x1 << 1 |
+}; |
+typedef NSUInteger NSEventSwipeTrackingOptions; |
+ |
+@interface NSEvent (LionAPI) |
+- (NSEventPhase)phase; |
+- (CGFloat)scrollingDeltaX; |
+- (CGFloat)scrollingDeltaY; |
+- (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options |
+ dampenAmountThresholdMin:(CGFloat)minDampenThreshold |
+ max:(CGFloat)maxDampenThreshold |
+ usingHandler:(void (^)(CGFloat gestureAmount, |
+ NSEventPhase phase, |
+ BOOL isComplete, |
+ BOOL* stop))trackingHandler; |
+@end |
#endif // MAC_OS_X_VERSION_10_7 |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+@interface MCPopupController (Private) |
+- (void)notificationSwipeStarted; |
+- (void)notificationSwipeMoved:(CGFloat)amount; |
+- (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete; |
+@end |
+ |
+// Window Subclass ///////////////////////////////////////////////////////////// |
+ |
+@interface MCPopupWindow : NSWindow { |
+ // The cumulative X and Y scrollingDeltas since the -scrollWheel: event began. |
+ NSPoint totalScrollDelta_; |
+} |
+@end |
+ |
+@implementation MCPopupWindow |
+ |
+- (void)scrollWheel:(NSEvent*)event { |
+ // Gesture swiping only exists on 10.7+. |
+ if (![event respondsToSelector:@selector(phase)]) |
+ return; |
+ |
+ NSEventPhase phase = [event phase]; |
+ BOOL shouldTrackSwipe = NO; |
+ |
+ if (phase == NSEventPhaseBegan) { |
+ totalScrollDelta_ = NSZeroPoint; |
+ } else if (phase == NSEventPhaseChanged) { |
+ shouldTrackSwipe = YES; |
+ totalScrollDelta_.x += [event scrollingDeltaX]; |
+ totalScrollDelta_.y += [event scrollingDeltaY]; |
+ } |
+ |
+ // Only allow horizontal scrolling. |
+ if (std::abs(totalScrollDelta_.x) < std::abs(totalScrollDelta_.y)) |
+ return; |
+ |
+ if (shouldTrackSwipe) { |
+ MCPopupController* controller = |
+ base::mac::ObjCCastStrict<MCPopupController>([self windowController]); |
+ |
+ auto handler = ^(CGFloat gestureAmount, NSEventPhase phase, |
+ BOOL isComplete, BOOL* stop) { |
+ if (phase == NSEventPhaseBegan) { |
+ [controller notificationSwipeStarted]; |
+ return; |
+ } |
+ |
+ [controller notificationSwipeMoved:gestureAmount]; |
+ |
+ BOOL ended = phase == NSEventPhaseEnded; |
+ if (ended || isComplete) |
+ [controller notificationSwipeEnded:ended complete:isComplete]; |
+ }; |
+ [event trackSwipeEventWithOptions:0 |
+ dampenAmountThresholdMin:-1 |
+ max:1 |
+ usingHandler:handler]; |
+ } |
+} |
+ |
+@end |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
@implementation MCPopupController |
- (id)initWithNotification:(const message_center::Notification*)notification |
messageCenter:(message_center::MessageCenter*)messageCenter { |
- scoped_nsobject<NSWindow> window( |
- [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater |
- styleMask:NSBorderlessWindowMask |
- backing:NSBackingStoreBuffered |
- defer:YES]); |
+ scoped_nsobject<MCPopupWindow> window( |
+ [[MCPopupWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater |
+ styleMask:NSBorderlessWindowMask |
+ backing:NSBackingStoreBuffered |
+ defer:YES]); |
if ((self = [super initWithWindow:window])) { |
+ messageCenter_ = messageCenter; |
notificationController_.reset( |
[[MCNotificationController alloc] initWithNotification:notification |
- messageCenter:messageCenter]); |
+ messageCenter:messageCenter_]); |
[window setReleasedWhenClosed:NO]; |
[window setLevel:NSFloatingWindowLevel]; |
@@ -55,4 +154,28 @@ enum { |
return [notificationController_ notificationID]; |
} |
+// Private ///////////////////////////////////////////////////////////////////// |
+ |
+- (void)notificationSwipeStarted { |
+ originalFrame_ = [[self window] frame]; |
+ swipeGestureEnded_ = NO; |
+} |
+ |
+- (void)notificationSwipeMoved:(CGFloat)amount { |
+ NSWindow* window = [self window]; |
+ |
+ [window setAlphaValue:1.0 - std::abs(amount)]; |
dewittj
2013/05/23 16:28:37
Is the linear reduction of alpha the most natural?
Robert Sesek
2013/05/23 16:31:13
This isn't actually linear. |amount| is done throu
|
+ NSRect frame = [window frame]; |
+ CGFloat originalMin = NSMinX(originalFrame_); |
+ frame.origin.x = originalMin + (NSMidX(originalFrame_) - originalMin) * |
+ -amount; |
+ [window setFrame:frame display:YES]; |
+} |
+ |
+- (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete { |
+ swipeGestureEnded_ |= ended; |
+ if (swipeGestureEnded_ && isComplete) |
+ messageCenter_->RemoveNotification([self notificationID], /*by_user=*/true); |
Nico
2013/05/23 01:02:56
If the user cancels a swipe, does appkit animate b
Robert Sesek
2013/05/23 13:00:58
Yup! AppKit will run the animation back for us.
dewittj
2013/05/23 16:28:37
nit: spaces between comment markers and other text
Robert Sesek
2013/05/23 16:31:13
When doing this to "name" parameters, I think this
|
+} |
+ |
@end |