Index: chrome/browser/ui/cocoa/info_bubble_window.mm |
diff --git a/chrome/browser/ui/cocoa/info_bubble_window.mm b/chrome/browser/ui/cocoa/info_bubble_window.mm |
index d4bff5d45190efbf3a0aea9cc8eb5ba57c9c39e5..b334baab2ce5bf6456865abb1baac01a024ea13d 100644 |
--- a/chrome/browser/ui/cocoa/info_bubble_window.mm |
+++ b/chrome/browser/ui/cocoa/info_bubble_window.mm |
@@ -12,21 +12,16 @@ |
#include "content/public/browser/notification_registrar.h" |
#include "content/public/browser/notification_service.h" |
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h" |
+#import "ui/base/cocoa/window_animator.h" |
namespace { |
const CGFloat kOrderInSlideOffset = 10; |
const NSTimeInterval kOrderInAnimationDuration = 0.075; |
const NSTimeInterval kOrderOutAnimationDuration = 0.15; |
-// The minimum representable time interval. This can be used as the value |
-// passed to +[NSAnimationContext setDuration:] to stop an in-progress |
-// animation as quickly as possible. |
-const NSTimeInterval kMinimumTimeInterval = |
- std::numeric_limits<NSTimeInterval>::min(); |
} // namespace |
@interface InfoBubbleWindow (Private) |
- (void)appIsTerminating; |
-- (void)finishCloseAfterAnimation; |
@end |
// A helper class to proxy app notifications to the window. |
@@ -60,37 +55,6 @@ class AppNotificationBridge : public content::NotificationObserver { |
DISALLOW_COPY_AND_ASSIGN(AppNotificationBridge); |
}; |
-// A delegate object for watching the alphaValue animation on InfoBubbleWindows. |
-// An InfoBubbleWindow instance cannot be the delegate for its own animation |
-// because CAAnimations retain their delegates, and since the InfoBubbleWindow |
-// retains its animations a retain loop would be formed. |
-@interface InfoBubbleWindowCloser : NSObject { |
- @private |
- InfoBubbleWindow* window_; // Weak. Window to close. |
-} |
-- (id)initWithWindow:(InfoBubbleWindow*)window; |
-@end |
- |
-@implementation InfoBubbleWindowCloser |
- |
-- (id)initWithWindow:(InfoBubbleWindow*)window { |
- if ((self = [super init])) { |
- window_ = window; |
- } |
- return self; |
-} |
- |
-// Callback for the alpha animation. Closes window_ if appropriate. |
-- (void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag { |
- // When alpha reaches zero, close window_. |
- if ([window_ alphaValue] == 0.0) { |
- [window_ finishCloseAfterAnimation]; |
- } |
-} |
- |
-@end |
- |
- |
@implementation InfoBubbleWindow |
@synthesize allowedAnimations = allowedAnimations_; |
@@ -118,19 +82,9 @@ class AppNotificationBridge : public content::NotificationObserver { |
// Start invisible. Will be made visible when ordered front. |
[self setAlphaValue:0.0]; |
- // Set up alphaValue animation so that self is delegate for the animation. |
- // Setting up the delegate is required so that the |
- // animationDidStop:finished: callback can be handled. |
- // Notice that only the alphaValue Animation is replaced in case |
- // superclasses set up animations. |
- CAAnimation* alphaAnimation = [CABasicAnimation animation]; |
- base::scoped_nsobject<InfoBubbleWindowCloser> delegate( |
- [[InfoBubbleWindowCloser alloc] initWithWindow:self]); |
- [alphaAnimation setDelegate:delegate]; |
- NSMutableDictionary* animations = |
- [NSMutableDictionary dictionaryWithDictionary:[self animations]]; |
- [animations setObject:alphaAnimation forKey:@"alphaValue"]; |
- [self setAnimations:animations]; |
+ animation_controller_.reset([[WindowAnimationController alloc] init]); |
+ [animation_controller_ setOrderInDuration:kOrderInAnimationDuration]; |
+ [animation_controller_ setOrderOutDuration:kOrderOutAnimationDuration]; |
} |
return self; |
} |
@@ -150,43 +104,24 @@ class AppNotificationBridge : public content::NotificationObserver { |
return allowShareParentKeyState_; |
} |
-- (void)close { |
- // Block the window from receiving events while it fades out. |
- closing_ = YES; |
- |
+- (void)animateClose { |
if ((allowedAnimations_ & info_bubble::kAnimateOrderOut) == 0) { |
- [self finishCloseAfterAnimation]; |
- } else { |
- // Apply animations to hide self. |
- [NSAnimationContext beginGrouping]; |
- [[NSAnimationContext currentContext] |
- gtm_setDuration:kOrderOutAnimationDuration |
- eventMask:NSLeftMouseUpMask]; |
- [[self animator] setAlphaValue:0.0]; |
- [NSAnimationContext endGrouping]; |
+ [self close]; |
+ return; |
} |
+ |
+ // Fade out in place and close. |
+ [animation_controller_ animateWindow:self |
+ targetOrigin:[self frame].origin |
+ closing:YES |
+ callback:base::Closure()]; |
} |
// If the app is terminating but the window is still fading out, cancel the |
// animation and close the window to prevent it from leaking. |
// See http://crbug.com/37717 |
- (void)appIsTerminating { |
- if ((allowedAnimations_ & info_bubble::kAnimateOrderOut) == 0) |
- return; // The close has already happened with no Core Animation. |
- |
- // Cancel the current animation so that it closes immediately, triggering |
- // |finishCloseAfterAnimation|. |
- [NSAnimationContext beginGrouping]; |
- [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval]; |
- [[self animator] setAlphaValue:0.0]; |
- [NSAnimationContext endGrouping]; |
-} |
- |
-// Called by InfoBubbleWindowCloser when the window is to be really closed |
-// after the fading animation is complete. |
-- (void)finishCloseAfterAnimation { |
- if (closing_) |
- [super close]; |
+ [animation_controller_ cancelAnimationWithCallback]; |
} |
// Adds animation for info bubbles being ordered to the front. |
@@ -205,18 +140,10 @@ class AppNotificationBridge : public content::NotificationObserver { |
newOrigin.y += kOrderInSlideOffset; |
[self setFrameOrigin:newOrigin]; |
- // Apply animations to show and move self. |
- [NSAnimationContext beginGrouping]; |
- // The star currently triggers on mouse down, not mouse up. |
- NSTimeInterval duration = |
- (allowedAnimations_ & info_bubble::kAnimateOrderIn) |
- ? kOrderInAnimationDuration : kMinimumTimeInterval; |
- [[NSAnimationContext currentContext] |
- gtm_setDuration:duration |
- eventMask:NSLeftMouseUpMask | NSLeftMouseDownMask]; |
- [[self animator] setAlphaValue:1.0]; |
- [[self animator] setFrame:frame display:YES]; |
- [NSAnimationContext endGrouping]; |
+ [animation_controller_ animateWindow:self |
+ targetOrigin:frame.origin |
+ closing:NO |
+ callback:base::Closure()]; |
} else { |
[super orderWindow:orderingMode relativeTo:otherWindowNumber]; |
} |
@@ -225,12 +152,12 @@ class AppNotificationBridge : public content::NotificationObserver { |
// If the window is currently animating a close, block all UI events to the |
// window. |
- (void)sendEvent:(NSEvent*)theEvent { |
- if (!closing_) |
+ if (![self isClosing]) |
[super sendEvent:theEvent]; |
} |
- (BOOL)isClosing { |
- return closing_; |
+ return [animation_controller_ isClosing]; |
} |
@end |