Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(811)

Unified Diff: ui/message_center/cocoa/popup_controller.mm

Issue 15757005: [Mac][MC] Allow popup notifications to be dismissed with a swipe gesture. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/message_center/cocoa/popup_controller.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « ui/message_center/cocoa/popup_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698