+@end
+
+@interface StatusBubbleWindow : NSWindow {
+ @private
+ void (^completionHandler_)(void);
+}
+
+- (id)animationForKey:(NSString *)key;
+- (void)runAnimationGroup:(void (^)(NSAnimationContext *context))changes
+ completionHandler:(void (^)(void))completionHandler;
+@end
+
+@implementation StatusBubbleWindow
+
+- (id)animationForKey:(NSString *)key {
+ CAAnimation* animation = [super animationForKey:key];
+ // If completionHandler_ isn't nil, then this is the first of (potentially)
+ // multiple animations in a grouping; give it the completion handler. If
+ // completionHandler_ is nil, then some other animation was tagged with the
+ // completion handler.
+ if (completionHandler_) {
+ DCHECK(![NSAnimationContext respondsToSelector:
+ @selector(runAnimationGroup:completionHandler:)]);
+ StatusBubbleAnimationDelegate* animation_delegate =
+ [[StatusBubbleAnimationDelegate alloc]
+ initWithCompletionHandler:completionHandler_];
+ [animation setDelegate:animation_delegate];
+ completionHandler_ = nil;
+ }
+ return animation;
+}
+
+- (void)runAnimationGroup:(void (^)(NSAnimationContext *context))changes
+ completionHandler:(void (^)(void))completionHandler {
+ if ([NSAnimationContext respondsToSelector:
+ @selector(runAnimationGroup:completionHandler:)]) {
+ [NSAnimationContext runAnimationGroup:changes
+ completionHandler:completionHandler];
+ } else {
+ // Mac OS 10.6 does not have completion handler callbacks at the Cocoa
+ // level, only at the CoreAnimation level. So intercept calls made to
+ // -animationForKey: and tag one of the animations with a delegate that will
+ // execute the completion handler.
+ completionHandler_ = completionHandler;
+ [NSAnimationContext beginGrouping];
+ changes([NSAnimationContext currentContext]);
+ // At this point, -animationForKey should have been called by CoreAnimation
+ // to set up the animation to run. Verify this.
+ DCHECK(completionHandler_ == nil);
+ [NSAnimationContext endGrouping];
+ }