Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: chrome/browser/ui/cocoa/dev_tools_controller.mm

Issue 63173016: DevTools: place DevTools WebContents underneath inspected WebContents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/dev_tools_controller.h" 5 #import "chrome/browser/ui/cocoa/dev_tools_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath>
8 9
9 #include <Cocoa/Cocoa.h> 10 #include <Cocoa/Cocoa.h>
10 11
11 #include "base/prefs/pref_service.h" 12 #include "base/prefs/pref_service.h"
12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
14 #import "chrome/browser/ui/cocoa/view_id_util.h" 15 #import "chrome/browser/ui/cocoa/view_id_util.h"
15 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
16 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_view.h" 18 #include "content/public/browser/web_contents_view.h"
18 #include "ui/base/cocoa/focus_tracker.h" 19 #include "ui/base/cocoa/focus_tracker.h"
20 #include "ui/gfx/size_conversions.h"
19 21
20 using content::WebContents; 22 using content::WebContents;
21 23
22 @interface GraySplitView : NSSplitView { 24 @interface DevToolsContainerView : NSView {
23 BOOL dividerHidden_; 25 NSSize topLeftContentsOffset_;
26 NSSize bottomRightContentsOffset_;
27 NSView* devToolsView_;
28 NSView* contentsView_;
Avi (use Gerrit) 2013/12/09 16:13:36 Comment these as being weak (ownership via -subvie
dgozman 2013/12/10 14:51:47 Done.
24 } 29 }
25 30
26 @property(assign, nonatomic) BOOL dividerHidden; 31 - (void)setContentsOffsetsTopLeft:(NSSize)topLeft
27 32 bottomRight:(NSSize)bottomRight;
28 - (NSColor*)dividerColor; 33 - (void)adjustSubviews;
29 - (CGFloat)dividerThickness; 34 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize;
Avi (use Gerrit) 2013/12/09 16:13:36 unused; remove
dgozman 2013/12/10 14:51:47 This is an NSView override. Removed from interface
35 - (void)showDevTools:(NSView*)devToolsView;
36 - (void)hideDevTools;
30 37
31 @end 38 @end
32 39
33 40
34 @implementation GraySplitView 41 @implementation DevToolsContainerView
35 42
36 @synthesize dividerHidden = dividerHidden_; 43 - (DevToolsContainerView*) initWithFrame:(NSRect)frame {
Avi (use Gerrit) 2013/12/09 16:13:36 No space between ) and i.
dgozman 2013/12/10 14:51:47 Done.
37 44 if (self = [super initWithFrame:frame]) {
38 - (NSColor*)dividerColor { 45 devToolsView_ = nil;
39 return [NSColor darkGrayColor]; 46 contentsView_ = nil;
47 topLeftContentsOffset_ = NSZeroSize;
48 bottomRightContentsOffset_ = NSZeroSize;
Avi (use Gerrit) 2013/12/09 16:13:36 This initialization isn't needed; ivars start out
dgozman 2013/12/10 14:51:47 Done.
49 }
50 return self;
40 } 51 }
41 52
42 - (CGFloat)dividerThickness { 53 - (void)setContentsOffsetsTopLeft:(NSSize)topLeft
43 return dividerHidden_ ? 0 : [super dividerThickness]; 54 bottomRight:(NSSize)bottomRight {
55 topLeftContentsOffset_ = topLeft;
56 bottomRightContentsOffset_ = bottomRight;
57 }
58
59 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
Avi (use Gerrit) 2013/12/09 16:13:36 unused; remove
dgozman 2013/12/10 14:51:47 This is NSView override invoked when view is resiz
Avi (use Gerrit) 2013/12/10 16:32:40 Oh.
60 [self adjustSubviews];
61 }
62
63 - (void)showDevTools:(NSView*)devToolsView {
64 NSArray* subviews = [self subviews];
65 DCHECK_EQ([subviews count], 1u);
Avi (use Gerrit) 2013/12/09 16:13:36 In DCHECK land, expected values are the first para
dgozman 2013/12/10 14:51:47 Done.
66 contentsView_ = [subviews objectAtIndex:0];
67 devToolsView_ = devToolsView;
68 // Place DevTools under contents.
69 [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
70 }
71
72 - (void)hideDevTools {
73 DCHECK_EQ([[self subviews] count], 2u);
74 [devToolsView_ removeFromSuperview];
75 contentsView_ = nil;
76 devToolsView_ = nil;
77 }
78
79 - (void)adjustSubviews {
80 if (![[self subviews] count])
81 return;
82
83 if (!devToolsView_) {
84 DCHECK_EQ([[self subviews] count], 1u);
85 NSView* contents = [[self subviews] objectAtIndex:0];
86 [contents setFrame:[self bounds]];
87 return;
88 }
89
90 DCHECK_EQ([[self subviews] count], 2u);
91 NSRect bounds = [self bounds];
92
93 [devToolsView_ setFrame:bounds];
94
95 CGFloat contentsWidth = std::max(0.f, NSWidth(bounds) -
96 topLeftContentsOffset_.width - bottomRightContentsOffset_.width);
97 CGFloat contentsHeight = std::max(0.f, NSHeight(bounds) -
98 topLeftContentsOffset_.height - bottomRightContentsOffset_.height);
99 CGFloat contentsTop =
100 std::min(topLeftContentsOffset_.height, NSHeight(bounds));
101 CGFloat contentsLeft =
102 std::min(topLeftContentsOffset_.width, NSWidth(bounds));
103
104 [contentsView_ setFrame:NSMakeRect(
105 contentsLeft,
106 contentsTop,
107 contentsWidth,
108 contentsHeight)];
Avi (use Gerrit) 2013/12/09 16:13:36 Weird wrapping; can you get this to be on one line
dgozman 2013/12/10 14:51:47 Done.
44 } 109 }
45 110
46 @end 111 @end
47 112
48 @interface DevToolsController (Private) 113 @interface DevToolsController (Private)
49 - (void)showDevToolsContainer; 114 - (void)showDevToolsView;
50 - (void)hideDevToolsContainer; 115 - (void)hideDevToolsView;
51 - (void)updateDevToolsSplitPosition;
52 @end 116 @end
53 117
54 118
55 @implementation DevToolsController 119 @implementation DevToolsController
56 120
57 - (id)init { 121 - (id)init {
58 if ((self = [super init])) { 122 if ((self = [super init])) {
59 splitView_.reset([[GraySplitView alloc] initWithFrame:NSZeroRect]); 123 devToolsContainerView_.reset(
60 [splitView_ setDividerStyle:NSSplitViewDividerStyleThin]; 124 [[DevToolsContainerView alloc] initWithFrame:NSZeroRect]);
61 [splitView_ setVertical:NO]; 125 [devToolsContainerView_
62 [splitView_ setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; 126 setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
63 [splitView_ setDelegate:self];
64 [splitView_ setDividerHidden:NO];
65
66 dockSide_ = DEVTOOLS_DOCK_SIDE_BOTTOM;
67 } 127 }
68 return self; 128 return self;
69 } 129 }
70 130
71 - (void)dealloc {
72 [splitView_ setDelegate:nil];
73 [super dealloc];
74 }
75
76 - (NSView*)view { 131 - (NSView*)view {
77 return splitView_.get(); 132 return devToolsContainerView_.get();
78 }
79
80 - (NSSplitView*)splitView {
81 return splitView_.get();
82 } 133 }
83 134
84 - (void)updateDevToolsForWebContents:(WebContents*)contents 135 - (void)updateDevToolsForWebContents:(WebContents*)contents
85 withProfile:(Profile*)profile { 136 withProfile:(Profile*)profile {
86 DevToolsWindow* newDevToolsWindow = contents ? 137 DevToolsWindow* newDevToolsWindow = contents ?
87 DevToolsWindow::GetDockedInstanceForInspectedTab(contents) : NULL; 138 DevToolsWindow::GetDockedInstanceForInspectedTab(contents) : NULL;
88 139
89 // Fast return in case of the same window having same orientation. 140 bool shouldHide = devToolsWindow_ && devToolsWindow_ != newDevToolsWindow;
90 if (devToolsWindow_ == newDevToolsWindow) { 141 bool shouldShow = newDevToolsWindow && devToolsWindow_ != newDevToolsWindow;
91 if (!newDevToolsWindow || 142
92 (newDevToolsWindow->dock_side() == dockSide_)) { 143 if (shouldHide)
93 return; 144 [self hideDevToolsView];
94 } 145
146 devToolsWindow_ = newDevToolsWindow;
147 if (devToolsWindow_) {
148 gfx::Insets insets = devToolsWindow_->GetContentsInsets();;
Avi (use Gerrit) 2013/12/09 16:13:36 Too many semicolons.
dgozman 2013/12/10 14:51:47 Done.
149 devToolsWindow_->web_contents()->GetView()->SetOverlayView(
150 contents->GetView(), gfx::Point(insets.left(), insets.top()));
Avi (use Gerrit) 2013/12/09 16:13:36 Yikes. SetOverlayView takes a flipped Y? Can you a
dgozman 2013/12/10 14:51:47 SetOverlayView takes the usual coordinates (top-le
151
152 // Swap top and bottom offsets for NSView geometry.
Avi (use Gerrit) 2013/12/09 16:13:36 :( If you are calling parameters "top left" and "
dgozman 2013/12/10 14:51:47 Ok, so the right way is to always use logical top,
Avi (use Gerrit) 2013/12/10 16:32:40 Well, if you have a parameter called "top left" th
153 [devToolsContainerView_
154 setContentsOffsetsTopLeft:NSMakeSize(insets.left(), insets.bottom())
155 bottomRight:NSMakeSize(insets.right(), insets.top())];
Avi (use Gerrit) 2013/12/09 16:13:36 Oh wow, this is awkward. Cocoa's equivalent to gfx
dgozman 2013/12/10 14:51:47 Done.
156 } else {
157 [devToolsContainerView_
158 setContentsOffsetsTopLeft:NSZeroSize
Avi (use Gerrit) 2013/12/09 16:13:36 Surely this fits on the previous line.
dgozman 2013/12/10 14:51:47 Done.
159 bottomRight:NSZeroSize];
95 } 160 }
96 161
97 // Store last used position. 162 if (shouldShow)
98 if (devToolsWindow_) { 163 [self showDevToolsView];
99 NSArray* subviews = [splitView_ subviews];
100 DCHECK_EQ([subviews count], 2u);
101 NSView* devToolsView = [subviews objectAtIndex:1];
102 if (dockSide_ == DEVTOOLS_DOCK_SIDE_RIGHT)
103 devToolsWindow_->SetWidth(NSWidth([devToolsView frame]));
104 else if (dockSide_ == DEVTOOLS_DOCK_SIDE_BOTTOM)
105 devToolsWindow_->SetHeight(NSHeight([devToolsView frame]));
106 }
107 164
108 if (devToolsWindow_) 165 [devToolsContainerView_ adjustSubviews];
109 [self hideDevToolsContainer]; 166 if (shouldHide || shouldShow)
110 167 [[devToolsContainerView_ window] disableScreenUpdatesUntilFlush];
111 devToolsWindow_ = newDevToolsWindow;
112
113 if (devToolsWindow_) {
114 dockSide_ = devToolsWindow_->dock_side();
115 [self showDevToolsContainer];
116 }
117 } 168 }
118 169
119 - (void)showDevToolsContainer { 170 - (void)showDevToolsView {
120 NSArray* subviews = [splitView_ subviews];
121 DCHECK_EQ([subviews count], 1u);
122 WebContents* devToolsContents = devToolsWindow_->web_contents();
123 focusTracker_.reset( 171 focusTracker_.reset(
124 [[FocusTracker alloc] initWithWindow:[splitView_ window]]); 172 [[FocusTracker alloc] initWithWindow:[devToolsContainerView_ window]]);
125 173
126 // |devToolsView| is a TabContentsViewCocoa object, whose ViewID was 174 // |devToolsView| is a WebContentsViewCocoa object, whose ViewID was
Avi (use Gerrit) 2013/12/09 16:13:36 :)
127 // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to 175 // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
128 // VIEW_ID_DEV_TOOLS_DOCKED here. 176 // VIEW_ID_DEV_TOOLS_DOCKED here.
129 NSView* devToolsView = devToolsContents->GetView()->GetNativeView(); 177 NSView* devToolsView =
178 devToolsWindow_->web_contents()->GetView()->GetNativeView();
130 view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED); 179 view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED);
131 [splitView_ addSubview:devToolsView];
132 180
133 BOOL isVertical = devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_RIGHT; 181 [devToolsContainerView_ showDevTools:devToolsView];
134 [splitView_ setVertical:isVertical];
135 [self updateDevToolsSplitPosition];
136 } 182 }
137 183
138 - (void)hideDevToolsContainer { 184 - (void)hideDevToolsView {
139 NSArray* subviews = [splitView_ subviews]; 185 devToolsWindow_->web_contents()->GetView()->RemoveOverlayView();
140 DCHECK_EQ([subviews count], 2u); 186 [devToolsContainerView_ hideDevTools];
141 NSView* oldDevToolsContentsView = [subviews objectAtIndex:1]; 187 [focusTracker_ restoreFocusInWindow:[devToolsContainerView_ window]];
142 [oldDevToolsContentsView removeFromSuperview];
143 [splitView_ adjustSubviews];
144 [focusTracker_ restoreFocusInWindow:[splitView_ window]];
145 focusTracker_.reset(); 188 focusTracker_.reset();
146 } 189 }
147 190
148 - (void)updateDevToolsSplitPosition {
149 NSArray* subviews = [splitView_ subviews];
150
151 // It seems as if |-setPosition:ofDividerAtIndex:| should do what's needed,
152 // but I can't figure out how to use it. Manually resize web and devtools.
153 // TODO(alekseys): either make setPosition:ofDividerAtIndex: work or to add a
154 // category on NSSplitView to handle manual resizing.
155 NSView* webView = [subviews objectAtIndex:0];
156 NSRect webFrame = [webView frame];
157 NSView* devToolsView = [subviews objectAtIndex:1];
158 NSRect devToolsFrame = [devToolsView frame];
159
160 BOOL noDivider = devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_MINIMIZED;
161 [splitView_ setDividerHidden:noDivider];
162
163 if (devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_RIGHT) {
164 CGFloat size = devToolsWindow_->GetWidth(NSWidth([splitView_ frame]));
165 devToolsFrame.size.width = size;
166 webFrame.size.width =
167 NSWidth([splitView_ frame]) - ([splitView_ dividerThickness] + size);
168 } else {
169 CGFloat size =
170 devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_MINIMIZED ?
171 devToolsWindow_->GetMinimizedHeight() :
172 devToolsWindow_->GetHeight(NSHeight([splitView_ frame]));
173 devToolsFrame.size.height = size;
174 webFrame.size.height =
175 NSHeight([splitView_ frame]) - ([splitView_ dividerThickness] + size);
176 }
177
178 [[splitView_ window] disableScreenUpdatesUntilFlush];
179 [webView setFrame:webFrame];
180 [devToolsView setFrame:devToolsFrame];
181
182 [splitView_ adjustSubviews];
183 }
184
185 // NSSplitViewDelegate protocol.
186 - (BOOL)splitView:(NSSplitView *)splitView
187 shouldAdjustSizeOfSubview:(NSView *)subview {
188 // Return NO for the devTools view to indicate that it should not be resized
189 // automatically. It preserves the height set by the user and also keeps
190 // view height the same while changing tabs when one of the tabs shows infobar
191 // and others are not.
192 if ([[splitView_ subviews] indexOfObject:subview] == 1)
193 return NO;
194 return YES;
195 }
196
197 - (NSRect)splitView:(NSSplitView*)splitView
198 effectiveRect:(NSRect)proposedEffectiveRect
199 forDrawnRect:(NSRect)drawnRect
200 ofDividerAtIndex:(NSInteger)dividerIndex {
201 if (devToolsWindow_->dock_side() == DEVTOOLS_DOCK_SIDE_MINIMIZED) {
202 return NSZeroRect;
203 } else {
204 return proposedEffectiveRect;
205 }
206 }
207
208 - (CGFloat)splitView:(NSSplitView*)splitView
209 constrainMaxCoordinate:(CGFloat)proposedMax
210 ofSubviewAt:(NSInteger)dividerIndex {
211 if ([splitView_ isVertical]) {
212 return NSWidth([splitView_ frame]) - [splitView_ dividerThickness] -
213 devToolsWindow_->GetMinimumWidth();
214 } else {
215 return NSHeight([splitView_ frame]) - [splitView_ dividerThickness] -
216 devToolsWindow_->GetMinimumHeight();
217 }
218 }
219
220 - (CGFloat)splitView:(NSSplitView *)splitView
221 constrainSplitPosition:(CGFloat)proposedPosition
222 ofSubviewAt:(NSInteger)dividerIndex {
223 return round(proposedPosition);
224 }
225
226 -(void)splitViewWillResizeSubviews:(NSNotification *)notification {
227 [[splitView_ window] disableScreenUpdatesUntilFlush];
228 }
229
230 @end 191 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698