OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/info_bubble_window.h" | 5 #import "chrome/browser/ui/cocoa/info_bubble_window.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/mac/foundation_util.h" | |
10 #include "base/memory/scoped_nsobject.h" | 9 #include "base/memory/scoped_nsobject.h" |
11 #include "content/public/browser/notification_observer.h" | 10 #include "content/public/browser/notification_observer.h" |
12 #include "content/public/browser/notification_registrar.h" | 11 #include "content/public/browser/notification_registrar.h" |
13 #include "content/public/browser/notification_service.h" | 12 #include "content/public/browser/notification_service.h" |
14 #include "content/public/browser/notification_types.h" | 13 #include "content/public/browser/notification_types.h" |
15 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" | 14 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" |
16 | 15 |
17 namespace { | 16 namespace { |
18 const CGFloat kOrderInSlideOffset = 10; | 17 const CGFloat kOrderInSlideOffset = 10; |
19 const NSTimeInterval kOrderInAnimationDuration = 0.075; | 18 const NSTimeInterval kOrderInAnimationDuration = 0.075; |
20 const NSTimeInterval kOrderOutAnimationDuration = 0.15; | 19 const NSTimeInterval kOrderOutAnimationDuration = 0.15; |
21 // The minimum representable time interval. This can be used as the value | 20 // The minimum representable time interval. This can be used as the value |
22 // passed to +[NSAnimationContext setDuration:] to stop an in-progress | 21 // passed to +[NSAnimationContext setDuration:] to stop an in-progress |
23 // animation as quickly as possible. | 22 // animation as quickly as possible. |
24 const NSTimeInterval kMinimumTimeInterval = | 23 const NSTimeInterval kMinimumTimeInterval = |
25 std::numeric_limits<NSTimeInterval>::min(); | 24 std::numeric_limits<NSTimeInterval>::min(); |
26 } // namespace | 25 } // namespace |
27 | 26 |
28 // Forward declare private window server functions used to style the window. | |
29 extern "C" { | |
30 typedef int CGSConnection; | |
31 typedef int CGSWindow; | |
32 typedef void* CGSWindowFilterRef; | |
33 | |
34 CGSConnection _CGSDefaultConnection(); | |
35 CGError CGSNewCIFilterByName(CGSConnection cid, | |
36 CFStringRef filterName, | |
37 CGSWindowFilterRef *outFilter); | |
38 CGError CGSAddWindowFilter(CGSConnection cid, | |
39 CGSWindow wid, | |
40 CGSWindowFilterRef filter, | |
41 int flags); | |
42 CGError CGSReleaseCIFilter(CGSConnection cid, CGSWindowFilterRef filter); | |
43 CGError CGSSetCIFilterValuesFromDictionary( | |
44 CGSConnection cid, CGSWindowFilterRef filter, CFDictionaryRef filterValues); | |
45 } // extern "C" | |
46 | |
47 @interface InfoBubbleWindow (Private) | 27 @interface InfoBubbleWindow (Private) |
48 - (void)appIsTerminating; | 28 - (void)appIsTerminating; |
49 - (void)finishCloseAfterAnimation; | 29 - (void)finishCloseAfterAnimation; |
50 @end | 30 @end |
51 | 31 |
52 // A helper class to proxy app notifications to the window. | 32 // A helper class to proxy app notifications to the window. |
53 class AppNotificationBridge : public content::NotificationObserver { | 33 class AppNotificationBridge : public content::NotificationObserver { |
54 public: | 34 public: |
55 explicit AppNotificationBridge(InfoBubbleWindow* owner) : owner_(owner) { | 35 explicit AppNotificationBridge(InfoBubbleWindow* owner) : owner_(owner) { |
56 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, | 36 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 88 } |
109 } | 89 } |
110 | 90 |
111 @end | 91 @end |
112 | 92 |
113 | 93 |
114 @implementation InfoBubbleWindow | 94 @implementation InfoBubbleWindow |
115 | 95 |
116 @synthesize delayOnClose = delayOnClose_; | 96 @synthesize delayOnClose = delayOnClose_; |
117 @synthesize canBecomeKeyWindow = canBecomeKeyWindow_; | 97 @synthesize canBecomeKeyWindow = canBecomeKeyWindow_; |
118 @synthesize hasBlurredBackground = hasBlurredBackground_; | |
119 | 98 |
120 - (id)initWithContentRect:(NSRect)contentRect | 99 - (id)initWithContentRect:(NSRect)contentRect |
121 styleMask:(NSUInteger)aStyle | 100 styleMask:(NSUInteger)aStyle |
122 backing:(NSBackingStoreType)bufferingType | 101 backing:(NSBackingStoreType)bufferingType |
123 defer:(BOOL)flag { | 102 defer:(BOOL)flag { |
124 if ((self = [super initWithContentRect:contentRect | 103 if ((self = [super initWithContentRect:contentRect |
125 styleMask:NSBorderlessWindowMask | 104 styleMask:NSBorderlessWindowMask |
126 backing:bufferingType | 105 backing:bufferingType |
127 defer:flag])) { | 106 defer:flag])) { |
128 [self setBackgroundColor:[NSColor clearColor]]; | 107 [self setBackgroundColor:[NSColor clearColor]]; |
129 [self setExcludedFromWindowsMenu:YES]; | 108 [self setExcludedFromWindowsMenu:YES]; |
130 [self setOpaque:NO]; | 109 [self setOpaque:NO]; |
131 [self setHasShadow:YES]; | 110 [self setHasShadow:YES]; |
132 delayOnClose_ = YES; | 111 delayOnClose_ = YES; |
133 canBecomeKeyWindow_ = YES; | 112 canBecomeKeyWindow_ = YES; |
134 hasBlurredBackground_ = YES; | |
135 notificationBridge_.reset(new AppNotificationBridge(self)); | 113 notificationBridge_.reset(new AppNotificationBridge(self)); |
136 | 114 |
137 // Start invisible. Will be made visible when ordered front. | 115 // Start invisible. Will be made visible when ordered front. |
138 [self setAlphaValue:0.0]; | 116 [self setAlphaValue:0.0]; |
139 | 117 |
140 // Set up alphaValue animation so that self is delegate for the animation. | 118 // Set up alphaValue animation so that self is delegate for the animation. |
141 // Setting up the delegate is required so that the | 119 // Setting up the delegate is required so that the |
142 // animationDidStop:finished: callback can be handled. | 120 // animationDidStop:finished: callback can be handled. |
143 // Notice that only the alphaValue Animation is replaced in case | 121 // Notice that only the alphaValue Animation is replaced in case |
144 // superclasses set up animations. | 122 // superclasses set up animations. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 // Order self appropriately assuming that its alpha is zero as set up | 195 // Order self appropriately assuming that its alpha is zero as set up |
218 // in the designated initializer. | 196 // in the designated initializer. |
219 [super orderWindow:orderingMode relativeTo:otherWindowNumber]; | 197 [super orderWindow:orderingMode relativeTo:otherWindowNumber]; |
220 | 198 |
221 // Set up frame so it can be adjust down by a few pixels. | 199 // Set up frame so it can be adjust down by a few pixels. |
222 NSRect frame = [self frame]; | 200 NSRect frame = [self frame]; |
223 NSPoint newOrigin = frame.origin; | 201 NSPoint newOrigin = frame.origin; |
224 newOrigin.y += kOrderInSlideOffset; | 202 newOrigin.y += kOrderInSlideOffset; |
225 [self setFrameOrigin:newOrigin]; | 203 [self setFrameOrigin:newOrigin]; |
226 | 204 |
227 // Add a gaussian blur to the window. | |
228 if (hasBlurredBackground_) { | |
229 CGSConnection cgsConnection = _CGSDefaultConnection(); | |
230 CGSWindowFilterRef filter; | |
231 if (CGSNewCIFilterByName(cgsConnection, CFSTR("CIGaussianBlur"), | |
232 &filter) == kCGErrorSuccess) { | |
233 NSDictionary* blurOptions = | |
234 [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.5] | |
235 forKey:@"inputRadius"]; | |
236 | |
237 if (CGSSetCIFilterValuesFromDictionary(cgsConnection, filter, | |
238 base::mac::NSToCFCast(blurOptions)) == kCGErrorSuccess) { | |
239 CGSAddWindowFilter(cgsConnection, [self windowNumber], filter, 1); | |
240 } | |
241 | |
242 CGSReleaseCIFilter(cgsConnection, filter); | |
243 } | |
244 } | |
245 | |
246 // Apply animations to show and move self. | 205 // Apply animations to show and move self. |
247 [NSAnimationContext beginGrouping]; | 206 [NSAnimationContext beginGrouping]; |
248 // The star currently triggers on mouse down, not mouse up. | 207 // The star currently triggers on mouse down, not mouse up. |
249 [[NSAnimationContext currentContext] | 208 [[NSAnimationContext currentContext] |
250 gtm_setDuration:kOrderInAnimationDuration | 209 gtm_setDuration:kOrderInAnimationDuration |
251 eventMask:NSLeftMouseUpMask|NSLeftMouseDownMask]; | 210 eventMask:NSLeftMouseUpMask|NSLeftMouseDownMask]; |
252 [[self animator] setAlphaValue:1.0]; | 211 [[self animator] setAlphaValue:1.0]; |
253 [[self animator] setFrame:frame display:YES]; | 212 [[self animator] setFrame:frame display:YES]; |
254 [NSAnimationContext endGrouping]; | 213 [NSAnimationContext endGrouping]; |
255 } else { | 214 } else { |
256 [super orderWindow:orderingMode relativeTo:otherWindowNumber]; | 215 [super orderWindow:orderingMode relativeTo:otherWindowNumber]; |
257 } | 216 } |
258 } | 217 } |
259 | 218 |
260 // If the window is currently animating a close, block all UI events to the | 219 // If the window is currently animating a close, block all UI events to the |
261 // window. | 220 // window. |
262 - (void)sendEvent:(NSEvent*)theEvent { | 221 - (void)sendEvent:(NSEvent*)theEvent { |
263 if (!closing_) | 222 if (!closing_) |
264 [super sendEvent:theEvent]; | 223 [super sendEvent:theEvent]; |
265 } | 224 } |
266 | 225 |
267 - (BOOL)isClosing { | 226 - (BOOL)isClosing { |
268 return closing_; | 227 return closing_; |
269 } | 228 } |
270 | 229 |
271 @end | 230 @end |
OLD | NEW |