// Copyright (c) 2012 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/tab_contents/tab_contents_controller.h" #include #include "base/memory/scoped_nsobject.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" using content::WebContents; @implementation TabContentsController @synthesize webContents = contents_; - (id)initWithContents:(WebContents*)contents { if ((self = [super initWithNibName:nil bundle:nil])) { contents_ = contents; } return self; } - (void)dealloc { // make sure our contents have been removed from the window [[self view] removeFromSuperview]; [super dealloc]; } - (void)loadView { scoped_nsobject view([[NSView alloc] initWithFrame:NSZeroRect]); [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable]; [self setView:view]; } - (void)ensureContentsSizeDoesNotChange { NSView* contentsContainer = [self view]; NSArray* subviews = [contentsContainer subviews]; if ([subviews count] > 0) [contents_->GetNativeView() setAutoresizingMask:NSViewNotSizable]; } // Call when the tab view is properly sized and the render widget host view // should be put into the view hierarchy. - (void)ensureContentsVisible { if (!contents_) return; NSView* contentsContainer = [self view]; NSArray* subviews = [contentsContainer subviews]; NSView* contentsNativeView = contents_->GetNativeView(); [contentsNativeView setFrame:[contentsContainer frame]]; if ([subviews count] == 0) { [contentsContainer addSubview:contentsNativeView]; } else if ([subviews objectAtIndex:0] != contentsNativeView) { [contentsContainer replaceSubview:[subviews objectAtIndex:0] with:contentsNativeView]; } [contentsNativeView setAutoresizingMask:NSViewWidthSizable| NSViewHeightSizable]; } - (void)changeWebContents:(WebContents*)newContents { contents_ = newContents; } // Returns YES if the tab represented by this controller is the front-most. - (BOOL)isCurrentTab { // We're the current tab if we're in the view hierarchy, otherwise some other // tab is. return [[self view] superview] ? YES : NO; } - (void)willBecomeUnselectedTab { // The RWHV is ripped out of the view hierarchy on tab switches, so it never // formally resigns first responder status. Handle this by explicitly sending // a Blur() message to the renderer, but only if the RWHV currently has focus. content::RenderViewHost* rvh = [self webContents]->GetRenderViewHost(); if (rvh && rvh->GetView() && rvh->GetView()->HasFocus()) rvh->Blur(); } - (void)willBecomeSelectedTab { // Do not explicitly call Focus() here, as the RWHV may not actually have // focus (for example, if the omnibox has focus instead). The WebContents // logic will restore focus to the appropriate view. } - (void)tabDidChange:(WebContents*)updatedContents { // Calling setContentView: here removes any first responder status // the view may have, so avoid changing the view hierarchy unless // the view is different. if ([self webContents] != updatedContents) { contents_ = updatedContents; [self ensureContentsVisible]; } } @end