Chromium Code Reviews| Index: chrome/browser/ui/cocoa/tracking_area.mm |
| diff --git a/chrome/browser/ui/cocoa/tracking_area.mm b/chrome/browser/ui/cocoa/tracking_area.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..77f66f730c301f37b1a683d9c7aee006cc5bd3de |
| --- /dev/null |
| +++ b/chrome/browser/ui/cocoa/tracking_area.mm |
| @@ -0,0 +1,108 @@ |
| +// 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/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 { |
|
Scott Hess - ex-Googler
2011/02/14 19:25:38
I'm a tiny bit nervous about using NSProxy. I thi
Robert Sesek
2011/02/14 20:46:35
At this point, with the three dynamic messaging me
|
| + @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_; |
| + |
| + // The Class of |owner_|. When the actual object is no longer alive (and could |
| + // be zombie), this allows for introspection. |
| + Class ownerClass_; |
| +} |
| + |
| +@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; |
| + ownerClass_ = [owner class]; |
| + return self; |
| +} |
| + |
| +- (void)forwardInvocation:(NSInvocation*)invocation { |
| + if (!alive_) |
| + return; |
| + [invocation invokeWithTarget:owner_]; |
| +} |
| + |
| +- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel { |
| + // This can be called if |owner_| is not |alive_|, so use the Class to |
| + // generate the signature. |-forwardInvocation:| will block the actual call. |
| + return [ownerClass_ instanceMethodSignatureForSelector:sel]; |
| +} |
| + |
| +- (BOOL)respondsToSelector:(SEL)aSelector { |
| + return YES; |
|
Scott Hess - ex-Googler
2011/02/14 19:25:38
Seems like [ownerClass_ instancesRespondToSelector
Robert Sesek
2011/02/14 20:46:35
Do'h. I was looking for that method but couldn't f
|
| +} |
| + |
| +@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]); |
|
Scott Hess - ex-Googler
2011/02/14 19:25:38
You can get away with this, but I don't think you
Robert Sesek
2011/02/14 20:46:35
Done.
|
| + if ((self = static_cast<id>([super initWithRect:rect |
| + options:options |
| + owner:ownerProxy_.get() |
| + userInfo:userInfo]))) { |
| + } |
| + 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 |