OLD | NEW |
---|---|
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 |
OLD | NEW |