summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h17
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm72
2 files changed, 48 insertions, 41 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index 67c8abf..0e65cef 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -32,7 +32,7 @@ class RWHVMEditCommandHelper;
@interface RenderWidgetHostViewCocoa
: BaseView <RenderWidgetHostViewMacOwner, NSTextInput, NSChangeSpelling> {
@private
- RenderWidgetHostViewMac* renderWidgetHostView_; // Owned by us.
+ scoped_ptr<RenderWidgetHostViewMac> renderWidgetHostView_;
BOOL canBeKeyView_;
BOOL closeOnDeactivate_;
scoped_ptr<RWHVMEditCommandHelper> editCommand_helper_;
@@ -41,7 +41,7 @@ class RWHVMEditCommandHelper;
id trackingRectOwner_; // (not retained)
void *trackingRectUserData_;
NSTrackingRectTag lastToolTipTag_;
- NSString* toolTip_;
+ scoped_nsobject<NSString> toolTip_;
BOOL ignoreKeyEvents_;
scoped_nsobject<NSEvent> lastKeyPressedEvent_;
@@ -195,8 +195,13 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
// invoke it from the message loop.
void ShutdownHost();
- // The associated view.
- RenderWidgetHostViewCocoa* cocoa_view_; // WEAK
+ // The associated view. This is weak and is inserted into the view hierarchy
+ // to own this RenderWidgetHostViewMac object unless is_popup_menu_ is true.
+ // In that case, cocoa_view_ is never inserted into the view hierarchy, so
+ // the RenderWidgetHostViewMac will treat it as a strong reference and will
+ // release it when told to destroy (for example, because a pop-up menu has
+ // closed).
+ RenderWidgetHostViewCocoa* cocoa_view_;
// The cursor for the page. This is passed up from the renderer.
WebCursor current_cursor_;
@@ -207,6 +212,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
// true if the View is not visible.
bool is_hidden_;
+ // True if the widget is a native popup menu. The renderer code calls this
+ // an "external popup."
+ bool is_popup_menu_;
+
// The text to be shown in the tooltip, supplied by the renderer.
std::wstring tooltip_text_;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 1c5469c..1d4121c 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -68,6 +68,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
im_composing_(false),
is_loading_(false),
is_hidden_(false),
+ is_popup_menu_(false),
shutdown_factory_(this),
parent_view_(NULL) {
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away.
@@ -296,16 +297,30 @@ void RenderWidgetHostViewMac::Destroy() {
// time Destroy() was called. On the Mac we have to destroy all the popups
// ourselves.
- // Depth-first destroy all popups. Use ShutdownHost() to enforce deepest-first
- // ordering.
- for (RenderWidgetHostViewCocoa* subview in [cocoa_view_ subviews]) {
- [subview renderWidgetHostViewMac]->ShutdownHost();
- }
+ if (!is_popup_menu_) {
+ // Depth-first destroy all popups. Use ShutdownHost() to enforce
+ // deepest-first ordering.
+ for (RenderWidgetHostViewCocoa* subview in [cocoa_view_ subviews]) {
+ [subview renderWidgetHostViewMac]->ShutdownHost();
+ }
+
+ // We've been told to destroy.
+ [cocoa_view_ retain];
+ [cocoa_view_ removeFromSuperview];
+ [cocoa_view_ autorelease];
+ } else {
+ // From the renderer's perspective, the pop-up menu is represented by a
+ // RenderWidget. The actual Mac implementation uses a native pop-up menu
+ // and doesn't actually make use of the RenderWidgetHostViewCocoa that
+ // was allocated to own it in its constructor. When the pop-up menu goes
+ // away, free the RenderWidgetHostViewCocoa. Its deallocation will result
+ // in this object's destruction.
- // We've been told to destroy.
- [cocoa_view_ retain];
- [cocoa_view_ removeFromSuperview];
- [cocoa_view_ autorelease];
+ DCHECK([[cocoa_view_ subviews] count] == 0);
+ DCHECK([cocoa_view_ superview] == nil);
+
+ [cocoa_view_ autorelease];
+ }
// We get this call just before |render_widget_host_| deletes
// itself. But we are owned by |cocoa_view_|, which may be retained
@@ -346,6 +361,8 @@ void RenderWidgetHostViewMac::ShowPopupWithItems(
int item_height,
int selected_item,
const std::vector<WebMenuItem>& items) {
+ is_popup_menu_ = true;
+
NSRect view_rect = [cocoa_view_ bounds];
NSRect parent_rect = [parent_view_ bounds];
int y_offset = bounds.y() + bounds.height();
@@ -377,19 +394,6 @@ void RenderWidgetHostViewMac::ShowPopupWithItems(
NativeWebKeyboardEvent keyboard_event(event);
render_widget_host_->ForwardKeyboardEvent(keyboard_event);
}
-
- // From the renderer's perspective, the pop-up menu is represented by a
- // RenderWidget. The actual Mac implementation uses a native pop-up menu
- // and doesn't actually make use of the RenderWidgetHostViewCocoa that
- // was allocated to own it in its constructor. When the pop-up menu goes
- // away, shut down the RenderWidgetHost (and RenderWidget), and then free
- // the RenderWidgetHostViewCocoa, which will result in the destruction of
- // this object.
- //
- // TODO(mark): This is a little bit dirty. Figure out a more proper
- // ownership model. http://crbug.com/26876
- ShutdownHost();
- [cocoa_view_ release];
}
void RenderWidgetHostViewMac::KillSelf() {
@@ -527,20 +531,13 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
editCommand_helper_.reset(new RWHVMEditCommandHelper);
editCommand_helper_->AddEditingSelectorsToClass([self class]);
- renderWidgetHostView_ = r;
+ renderWidgetHostView_.reset(r);
canBeKeyView_ = YES;
closeOnDeactivate_ = NO;
}
return self;
}
-- (void)dealloc {
- delete renderWidgetHostView_;
- [toolTip_ release];
-
- [super dealloc];
-}
-
- (void)setCanBeKeyView:(BOOL)can {
canBeKeyView_ = can;
}
@@ -884,7 +881,7 @@ void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) {
}
- (RenderWidgetHostViewMac*)renderWidgetHostViewMac {
- return renderWidgetHostView_;
+ return renderWidgetHostView_.get();
}
// Determine whether we should autohide the cursor (i.e., hide it until mouse
@@ -1103,16 +1100,17 @@ static const NSTrackingRectTag kTrackingRectTag = 0xBADFACE;
// appears after a delay.) Pass null to remove the tooltip.
- (void)setToolTipAtMousePoint:(NSString *)string {
NSString *toolTip = [string length] == 0 ? nil : string;
- NSString *oldToolTip = toolTip_;
- if ((toolTip == nil || oldToolTip == nil) ? toolTip == oldToolTip
- : [toolTip isEqualToString:oldToolTip]) {
+ if ((toolTip && toolTip_ && [toolTip isEqualToString:toolTip_]) ||
+ (!toolTip && !toolTip_)) {
return;
}
- if (oldToolTip) {
+
+ if (toolTip_) {
[self _sendToolTipMouseExited];
- [oldToolTip release];
}
- toolTip_ = [toolTip copy];
+
+ toolTip_.reset([toolTip copy]);
+
if (toolTip) {
// See radar 3500217 for why we remove all tooltips
// rather than just the single one we created.