1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "chrome/browser/ui/cocoa/dev_tools_controller.h" 6 7#include <algorithm> 8#include <cmath> 9 10#include <Cocoa/Cocoa.h> 11 12#include "base/prefs/pref_service.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/profiles/profile.h" 15#import "chrome/browser/ui/cocoa/view_id_util.h" 16#include "chrome/common/pref_names.h" 17#include "content/public/browser/web_contents.h" 18#include "ui/base/cocoa/base_view.h" 19#include "ui/base/cocoa/focus_tracker.h" 20#include "ui/gfx/mac/scoped_ns_disable_screen_updates.h" 21#include "ui/gfx/size_conversions.h" 22 23using content::WebContents; 24 25@interface DevToolsContainerView : BaseView { 26 DevToolsContentsResizingStrategy strategy_; 27 28 // Weak references. Ownership via -subviews. 29 NSView* devToolsView_; 30 NSView* contentsView_; 31} 32 33- (void)setDevToolsView:(NSView*)devToolsView 34 withStrategy:(const DevToolsContentsResizingStrategy&)strategy; 35- (void)adjustSubviews; 36- (BOOL)hasDevToolsView; 37 38@end 39 40 41@implementation DevToolsContainerView 42 43- (void)setDevToolsView:(NSView*)devToolsView 44 withStrategy:(const DevToolsContentsResizingStrategy&)strategy { 45 strategy_.CopyFrom(strategy); 46 if (devToolsView == devToolsView_) { 47 if (contentsView_) 48 [contentsView_ setHidden:strategy.hide_inspected_contents()]; 49 return; 50 } 51 52 if (devToolsView_) { 53 DCHECK_EQ(2u, [[self subviews] count]); 54 [devToolsView_ removeFromSuperview]; 55 [contentsView_ setHidden:NO]; 56 contentsView_ = nil; 57 devToolsView_ = nil; 58 } 59 60 if (devToolsView) { 61 NSArray* subviews = [self subviews]; 62 DCHECK_EQ(1u, [subviews count]); 63 contentsView_ = [subviews objectAtIndex:0]; 64 devToolsView_ = devToolsView; 65 // Place DevTools under contents. 66 [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil]; 67 68 [contentsView_ setHidden:strategy.hide_inspected_contents()]; 69 } 70} 71 72- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize { 73 [self adjustSubviews]; 74} 75 76- (BOOL)hasDevToolsView { 77 return devToolsView_ != nil; 78} 79 80- (void)adjustSubviews { 81 if (![[self subviews] count]) 82 return; 83 84 if (!devToolsView_) { 85 DCHECK_EQ(1u, [[self subviews] count]); 86 NSView* contents = [[self subviews] objectAtIndex:0]; 87 [contents setFrame:[self bounds]]; 88 return; 89 } 90 91 DCHECK_EQ(2u, [[self subviews] count]); 92 93 gfx::Rect new_devtools_bounds; 94 gfx::Rect new_contents_bounds; 95 ApplyDevToolsContentsResizingStrategy( 96 strategy_, gfx::Size(NSSizeToCGSize([self bounds].size)), 97 &new_devtools_bounds, &new_contents_bounds); 98 [devToolsView_ setFrame:[self flipRectToNSRect:new_devtools_bounds]]; 99 [contentsView_ setFrame:[self flipRectToNSRect:new_contents_bounds]]; 100} 101 102@end 103 104 105@implementation DevToolsController 106 107- (id)init { 108 if ((self = [super init])) { 109 devToolsContainerView_.reset( 110 [[DevToolsContainerView alloc] initWithFrame:NSZeroRect]); 111 [devToolsContainerView_ 112 setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; 113 } 114 return self; 115} 116 117- (NSView*)view { 118 return devToolsContainerView_.get(); 119} 120 121- (void)updateDevToolsForWebContents:(WebContents*)contents 122 withProfile:(Profile*)profile { 123 DevToolsContentsResizingStrategy strategy; 124 WebContents* devTools = DevToolsWindow::GetInTabWebContents( 125 contents, &strategy); 126 127 // Make sure we do not draw any transient arrangements of views. 128 gfx::ScopedNSDisableScreenUpdates disabler; 129 130 if (devTools && ![devToolsContainerView_ hasDevToolsView]) { 131 focusTracker_.reset( 132 [[FocusTracker alloc] initWithWindow:[devToolsContainerView_ window]]); 133 } 134 135 if (!devTools && [devToolsContainerView_ hasDevToolsView]) { 136 [focusTracker_ restoreFocusInWindow:[devToolsContainerView_ window]]; 137 focusTracker_.reset(); 138 } 139 140 NSView* devToolsView = nil; 141 if (devTools) { 142 devToolsView = devTools->GetNativeView(); 143 // |devToolsView| is a WebContentsViewCocoa object, whose ViewID was 144 // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to 145 // VIEW_ID_DEV_TOOLS_DOCKED here. 146 view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED); 147 148 devTools->SetAllowOtherViews(true); 149 contents->SetAllowOtherViews(true); 150 } else { 151 contents->SetAllowOtherViews(false); 152 } 153 154 [devToolsContainerView_ setDevToolsView:devToolsView withStrategy:strategy]; 155 [devToolsContainerView_ adjustSubviews]; 156} 157 158@end 159