Chromium Code Reviews| Index: chrome/browser/ui/cocoa/chrome_tracking_area.mm |
| diff --git a/chrome/browser/ui/cocoa/chrome_tracking_area.mm b/chrome/browser/ui/cocoa/chrome_tracking_area.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ed626c20ecbdd75b7df36a4beb5df2cc6df2f6b0 |
| --- /dev/null |
| +++ b/chrome/browser/ui/cocoa/chrome_tracking_area.mm |
| @@ -0,0 +1,101 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#import "chrome/browser/ui/cocoa/chrome_tracking_area.h" |
| + |
| +#include "base/logging.h" |
| + |
| +// NSTrackingArea does not retain its |owner| so CrTrackingArea wraps the real |
| +// owner in this proxy, which can stop forwarding messages to the owner when |
| +// it is no longer |alive_|. |
| +@interface CrTrackingAreaOwnerProxy : NSProxy { |
| + @private |
| + // Whether or not the owner is "alive" and should forward calls to the real |
| + // owner object. |
| + BOOL alive_; |
| + |
| + // The real object for which this is a proxy. Weak. |
| + id owner_; |
| +} |
| + |
| +@property(nonatomic, assign) BOOL alive; |
| +@property(nonatomic, assign) id owner; |
| + |
| +- (id)initWithOwner:(id)owner; |
| + |
| +@end |
| + |
| +@implementation CrTrackingAreaOwnerProxy |
| + |
| +@synthesize alive = alive_; |
| +@synthesize owner = owner_; |
| + |
| +- (id)initWithOwner:(id)owner { |
| + alive_ = YES; |
| + owner_ = owner; |
| + return self; |
| +} |
| + |
| +- (void)forwardInvocation:(NSInvocation*)invocation { |
| + if (!alive_) |
| + return; |
| + [invocation setTarget:owner_]; |
| + [invocation invoke]; |
| +} |
| + |
| +- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel { |
| + // Even if the owner is not alive, return the method signature so that the |
| + // runtime does not throw an exception. |-forwardInvocation:| will block the |
| + // message. |
| + return [owner_ methodSignatureForSelector:sel]; |
| +} |
| + |
| +@end |
| + |
| +// Private Interface /////////////////////////////////////////////////////////// |
| + |
| +@interface CrTrackingArea (Private) |
| +- (void)windowWillClose:(NSNotification*)notif; |
| +@end |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +@implementation CrTrackingArea |
| + |
| +- (id)initWithRect:(NSRect)rect |
| + options:(NSTrackingAreaOptions)options |
| + owner:(id)owner |
| + userInfo:(NSDictionary*)userInfo { |
| + ownerProxy_.reset([[CrTrackingAreaOwnerProxy alloc] initWithOwner:owner]); |
| + if ((self = static_cast<id>([super initWithRect:rect |
| + options:options |
| + owner:ownerProxy_.get() |
| + userInfo:userInfo]))) { |
|
Scott Hess - ex-Googler
2011/02/11 01:17:12
No need for the empty if(). Actually, the static_
Robert Sesek
2011/02/11 02:30:50
if() is just for convention. The static_cast<> is
|
| + } |
| + return self; |
| +} |
| + |
| +- (void)dealloc { |
| + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| + [super dealloc]; |
| +} |
| + |
| +- (void)clearOwner { |
| + [ownerProxy_ setAlive:NO]; |
| +} |
| + |
| +- (void)clearOwnerWhenWindowWillClose:(NSWindow*)window { |
| + DCHECK(window); |
| + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; |
| + [center addObserver:self |
| + selector:@selector(windowWillClose:) |
| + name:NSWindowWillCloseNotification |
| + object:window]; |
| +} |
| + |
| +- (void)windowWillClose:(NSNotification*)notif { |
| + [self clearOwner]; |
| +} |
| + |
| +@end |