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 23 using 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