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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/message_center/cocoa/popup_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/message_center/cocoa/popup_controller.h" 5 #import "ui/message_center/cocoa/popup_controller.h"
6 6
7 #include <cmath>
8
9 #import "base/mac/foundation_util.h"
7 #import "ui/base/cocoa/window_size_constants.h" 10 #import "ui/base/cocoa/window_size_constants.h"
8 #import "ui/message_center/cocoa/notification_controller.h" 11 #import "ui/message_center/cocoa/notification_controller.h"
9 #include "ui/message_center/message_center.h" 12 #include "ui/message_center/message_center.h"
10 13
11 #if !defined(MAC_OS_X_VERSION_10_7) || \ 14 #if !defined(MAC_OS_X_VERSION_10_7) || \
12 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 15 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
13 enum { 16 enum {
14 NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8 17 NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8
15 }; 18 };
19
20 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
21 NSEventPhaseNone = 0, // event not associated with a phase.
22 NSEventPhaseBegan = 0x1 << 0,
23 NSEventPhaseStationary = 0x1 << 1,
24 NSEventPhaseChanged = 0x1 << 2,
25 NSEventPhaseEnded = 0x1 << 3,
26 NSEventPhaseCancelled = 0x1 << 4,
27 };
28 typedef NSUInteger NSEventPhase;
29
30 enum {
31 NSEventSwipeTrackingLockDirection = 0x1 << 0,
32 NSEventSwipeTrackingClampGestureAmount = 0x1 << 1
33 };
34 typedef NSUInteger NSEventSwipeTrackingOptions;
35
36 @interface NSEvent (LionAPI)
37 - (NSEventPhase)phase;
38 - (CGFloat)scrollingDeltaX;
39 - (CGFloat)scrollingDeltaY;
40 - (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options
41 dampenAmountThresholdMin:(CGFloat)minDampenThreshold
42 max:(CGFloat)maxDampenThreshold
43 usingHandler:(void (^)(CGFloat gestureAmount,
44 NSEventPhase phase,
45 BOOL isComplete,
46 BOOL* stop))trackingHandler;
47 @end
16 #endif // MAC_OS_X_VERSION_10_7 48 #endif // MAC_OS_X_VERSION_10_7
17 49
50 ////////////////////////////////////////////////////////////////////////////////
51
52 @interface MCPopupController (Private)
53 - (void)notificationSwipeStarted;
54 - (void)notificationSwipeMoved:(CGFloat)amount;
55 - (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete;
56 @end
57
58 // Window Subclass /////////////////////////////////////////////////////////////
59
60 @interface MCPopupWindow : NSWindow {
61 // The cumulative X and Y scrollingDeltas since the -scrollWheel: event began.
62 NSPoint totalScrollDelta_;
63 }
64 @end
65
66 @implementation MCPopupWindow
67
68 - (void)scrollWheel:(NSEvent*)event {
69 // Gesture swiping only exists on 10.7+.
70 if (![event respondsToSelector:@selector(phase)])
71 return;
72
73 NSEventPhase phase = [event phase];
74 BOOL shouldTrackSwipe = NO;
75
76 if (phase == NSEventPhaseBegan) {
77 totalScrollDelta_ = NSZeroPoint;
78 } else if (phase == NSEventPhaseChanged) {
79 shouldTrackSwipe = YES;
80 totalScrollDelta_.x += [event scrollingDeltaX];
81 totalScrollDelta_.y += [event scrollingDeltaY];
82 }
83
84 // Only allow horizontal scrolling.
85 if (std::abs(totalScrollDelta_.x) < std::abs(totalScrollDelta_.y))
86 return;
87
88 if (shouldTrackSwipe) {
89 MCPopupController* controller =
90 base::mac::ObjCCastStrict<MCPopupController>([self windowController]);
91
92 auto handler = ^(CGFloat gestureAmount, NSEventPhase phase,
93 BOOL isComplete, BOOL* stop) {
94 if (phase == NSEventPhaseBegan) {
95 [controller notificationSwipeStarted];
96 return;
97 }
98
99 [controller notificationSwipeMoved:gestureAmount];
100
101 BOOL ended = phase == NSEventPhaseEnded;
102 if (ended || isComplete)
103 [controller notificationSwipeEnded:ended complete:isComplete];
104 };
105 [event trackSwipeEventWithOptions:0
106 dampenAmountThresholdMin:-1
107 max:1
108 usingHandler:handler];
109 }
110 }
111
112 @end
113
114 ////////////////////////////////////////////////////////////////////////////////
115
18 @implementation MCPopupController 116 @implementation MCPopupController
19 117
20 - (id)initWithNotification:(const message_center::Notification*)notification 118 - (id)initWithNotification:(const message_center::Notification*)notification
21 messageCenter:(message_center::MessageCenter*)messageCenter { 119 messageCenter:(message_center::MessageCenter*)messageCenter {
22 scoped_nsobject<NSWindow> window( 120 scoped_nsobject<MCPopupWindow> window(
23 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater 121 [[MCPopupWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
24 styleMask:NSBorderlessWindowMask 122 styleMask:NSBorderlessWindowMask
25 backing:NSBackingStoreBuffered 123 backing:NSBackingStoreBuffered
26 defer:YES]); 124 defer:YES]);
27 if ((self = [super initWithWindow:window])) { 125 if ((self = [super initWithWindow:window])) {
126 messageCenter_ = messageCenter;
28 notificationController_.reset( 127 notificationController_.reset(
29 [[MCNotificationController alloc] initWithNotification:notification 128 [[MCNotificationController alloc] initWithNotification:notification
30 messageCenter:messageCenter]); 129 messageCenter:messageCenter_]);
31 [window setReleasedWhenClosed:NO]; 130 [window setReleasedWhenClosed:NO];
32 131
33 [window setLevel:NSFloatingWindowLevel]; 132 [window setLevel:NSFloatingWindowLevel];
34 [window setExcludedFromWindowsMenu:YES]; 133 [window setExcludedFromWindowsMenu:YES];
35 [window setCollectionBehavior: 134 [window setCollectionBehavior:
36 NSWindowCollectionBehaviorIgnoresCycle | 135 NSWindowCollectionBehaviorIgnoresCycle |
37 NSWindowCollectionBehaviorFullScreenAuxiliary]; 136 NSWindowCollectionBehaviorFullScreenAuxiliary];
38 137
39 [window setHasShadow:YES]; 138 [window setHasShadow:YES];
40 [window setFrame:[[notificationController_ view] frame] display:NO]; 139 [window setFrame:[[notificationController_ view] frame] display:NO];
41 [window setContentView:[notificationController_ view]]; 140 [window setContentView:[notificationController_ view]];
42 } 141 }
43 return self; 142 return self;
44 } 143 }
45 144
46 - (MCNotificationController*)notificationController { 145 - (MCNotificationController*)notificationController {
47 return notificationController_.get(); 146 return notificationController_.get();
48 } 147 }
49 148
50 - (const message_center::Notification*)notification { 149 - (const message_center::Notification*)notification {
51 return [notificationController_ notification]; 150 return [notificationController_ notification];
52 } 151 }
53 152
54 - (const std::string&)notificationID { 153 - (const std::string&)notificationID {
55 return [notificationController_ notificationID]; 154 return [notificationController_ notificationID];
56 } 155 }
57 156
157 // Private /////////////////////////////////////////////////////////////////////
158
159 - (void)notificationSwipeStarted {
160 originalFrame_ = [[self window] frame];
161 swipeGestureEnded_ = NO;
162 }
163
164 - (void)notificationSwipeMoved:(CGFloat)amount {
165 NSWindow* window = [self window];
166
167 [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
168 NSRect frame = [window frame];
169 CGFloat originalMin = NSMinX(originalFrame_);
170 frame.origin.x = originalMin + (NSMidX(originalFrame_) - originalMin) *
171 -amount;
172 [window setFrame:frame display:YES];
173 }
174
175 - (void)notificationSwipeEnded:(BOOL)ended complete:(BOOL)isComplete {
176 swipeGestureEnded_ |= ended;
177 if (swipeGestureEnded_ && isComplete)
178 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
179 }
180
58 @end 181 @end
OLDNEW
« 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