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

Side by Side Diff: chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm

Issue 2138213003: Mac: Do layout before adding the WebContents to the view hierarchy when switching tabs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: selfnits Created 4 years, 5 months 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/tab_contents/tab_contents_controller.h" 5 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 } 64 }
65 65
66 private: 66 private:
67 TabContentsController* const controller_; 67 TabContentsController* const controller_;
68 68
69 DISALLOW_COPY_AND_ASSIGN(FullscreenObserver); 69 DISALLOW_COPY_AND_ASSIGN(FullscreenObserver);
70 }; 70 };
71 71
72 @interface TabContentsController (TabContentsContainerViewDelegate) 72 @interface TabContentsController (TabContentsContainerViewDelegate)
73 - (BOOL)contentsInFullscreenCaptureMode; 73 - (BOOL)contentsInFullscreenCaptureMode;
74 // Computes and returns the frame to use for the contents view within the 74 // Computes and returns the frame to use for the contents view using the size of
75 // container view. 75 // |container| as the target size.
76 - (NSRect)frameForContentsView; 76 - (NSRect)frameForContentsViewIn:(NSView*)container;
77 77
78 // Returns YES if the content view should be resized. 78 // Returns YES if the content view should be resized.
79 - (BOOL)shouldResizeContentView; 79 - (BOOL)shouldResizeContentView;
80 80
81 // Returns YES if the content view is inside a popup. 81 // Returns YES if the content view is inside a popup.
82 - (BOOL)isPopup; 82 - (BOOL)isPopup;
83 83
84 @end 84 @end
85 85
86 // An NSView with special-case handling for when the contents view does not 86 // An NSView with special-case handling for when the contents view does not
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize { 123 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
124 NSView* const contentsView = 124 NSView* const contentsView =
125 [[self subviews] count] > 0 ? [[self subviews] objectAtIndex:0] : nil; 125 [[self subviews] count] > 0 ? [[self subviews] objectAtIndex:0] : nil;
126 if (!contentsView || [contentsView autoresizingMask] == NSViewNotSizable || 126 if (!contentsView || [contentsView autoresizingMask] == NSViewNotSizable ||
127 !delegate_ || 127 !delegate_ ||
128 (![delegate_ shouldResizeContentView] && [delegate_ isPopup])) { 128 (![delegate_ shouldResizeContentView] && [delegate_ isPopup])) {
129 return; 129 return;
130 } 130 }
131 131
132 ScopedCAActionDisabler disabler; 132 ScopedCAActionDisabler disabler;
133 [contentsView setFrame:[delegate_ frameForContentsView]]; 133 [contentsView setFrame:[delegate_ frameForContentsViewIn:self]];
134 } 134 }
135 135
136 // Update the background layer's color whenever the view needs to repaint. 136 // Update the background layer's color whenever the view needs to repaint.
137 - (void)setNeedsDisplayInRect:(NSRect)rect { 137 - (void)setNeedsDisplayInRect:(NSRect)rect {
138 [super setNeedsDisplayInRect:rect]; 138 [super setNeedsDisplayInRect:rect];
139 [self updateBackgroundColor]; 139 [self updateBackgroundColor];
140 } 140 }
141 141
142 - (void)updateBackgroundColor { 142 - (void)updateBackgroundColor {
143 // This view is sometimes flashed into visibility (e.g, when closing 143 // This view is sometimes flashed into visibility (e.g, when closing
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 [super dealloc]; 210 [super dealloc];
211 } 211 }
212 212
213 - (void)loadView { 213 - (void)loadView {
214 base::scoped_nsobject<NSView> view( 214 base::scoped_nsobject<NSView> view(
215 [[TabContentsContainerView alloc] initWithDelegate:self]); 215 [[TabContentsContainerView alloc] initWithDelegate:self]);
216 [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable]; 216 [view setAutoresizingMask:NSViewHeightSizable|NSViewWidthSizable];
217 [self setView:view]; 217 [self setView:view];
218 } 218 }
219 219
220 - (void)ensureContentsSizeDoesNotChange { 220 - (void)addContentsToView:(NSView*)superview {
ccameron 2016/07/12 18:56:58 I'd prefer to avoid having the "nil defaults to so
tapted 2016/07/13 03:33:17 hehe - I actually started with this, but it made i
221 NSView* contentsContainer = [self view];
222 NSArray* subviews = [contentsContainer subviews];
223 if ([subviews count] > 0) {
224 NSView* currentSubview = [subviews objectAtIndex:0];
225 [currentSubview setAutoresizingMask:NSViewNotSizable];
226 }
227 }
228
229 - (void)ensureContentsVisible {
230 if (!contents_) 221 if (!contents_)
231 return; 222 return;
223
232 ScopedCAActionDisabler disabler; 224 ScopedCAActionDisabler disabler;
ccameron 2016/07/12 18:56:58 Would it be useful to have a "ScopedRWHViewActionD
tapted 2016/07/13 03:33:18 I'll keep it at the back of my mind - it does soun
233 NSView* contentsContainer = [self view]; 225 NSView* contentsContainer = [self view];
226
227 // |superview| will be nil when toggling fullscreen or changing tabs via a
228 // notification, which preserves the current superview. Otherwise, [self view]
229 // should have been removed from the view hierarchy to suppress resizes.
230 DCHECK(!superview || ![contentsContainer superview]);
231 if (!superview)
232 superview = [contentsContainer superview];
233 DCHECK(superview);
234
234 NSArray* subviews = [contentsContainer subviews]; 235 NSArray* subviews = [contentsContainer subviews];
235 NSView* contentsNativeView; 236 NSView* contentsNativeView;
236 content::RenderWidgetHostView* const fullscreenView = 237 content::RenderWidgetHostView* const fullscreenView =
237 isEmbeddingFullscreenWidget_ ? 238 isEmbeddingFullscreenWidget_ ?
238 contents_->GetFullscreenRenderWidgetHostView() : NULL; 239 contents_->GetFullscreenRenderWidgetHostView() : NULL;
239 if (fullscreenView) { 240 if (fullscreenView) {
240 contentsNativeView = fullscreenView->GetNativeView(); 241 contentsNativeView = fullscreenView->GetNativeView();
241 } else { 242 } else {
242 isEmbeddingFullscreenWidget_ = NO; 243 isEmbeddingFullscreenWidget_ = NO;
243 contentsNativeView = contents_->GetNativeView(); 244 contentsNativeView = contents_->GetNativeView();
244 } 245 }
245 246
246 if ([self shouldResizeContentView]) 247 if ([self shouldResizeContentView])
247 [contentsNativeView setFrame:[self frameForContentsView]]; 248 [contentsNativeView setFrame:[self frameForContentsViewIn:superview]];
248 249
249 if ([subviews count] == 0) { 250 if ([subviews count] == 0) {
250 [contentsContainer addSubview:contentsNativeView]; 251 [contentsContainer addSubview:contentsNativeView];
251 } else if ([subviews objectAtIndex:0] != contentsNativeView) { 252 } else if ([subviews objectAtIndex:0] != contentsNativeView) {
252 [contentsContainer replaceSubview:[subviews objectAtIndex:0] 253 [contentsContainer replaceSubview:[subviews objectAtIndex:0]
253 with:contentsNativeView]; 254 with:contentsNativeView];
254 } 255 }
256
257 [contentsNativeView setAutoresizingMask:NSViewNotSizable];
258 [contentsContainer setFrame:[superview bounds]];
259 [superview addSubview:contentsContainer];
255 [contentsNativeView setAutoresizingMask:NSViewWidthSizable| 260 [contentsNativeView setAutoresizingMask:NSViewWidthSizable|
256 NSViewHeightSizable]; 261 NSViewHeightSizable];
257 262
258 [contentsContainer setNeedsDisplay:YES]; 263 [contentsContainer setNeedsDisplay:YES];
259 264
260 // Push the background color down to the RenderWidgetHostView, so that if 265 // Push the background color down to the RenderWidgetHostView, so that if
261 // there is a flash between contents appearing, it will be the theme's color, 266 // there is a flash between contents appearing, it will be the theme's color,
262 // not white. 267 // not white.
263 SkColor skBackgroundColor = SK_ColorWHITE; 268 SkColor skBackgroundColor = SK_ColorWHITE;
264 const ThemeProvider* theme = [[[self view] window] themeProvider]; 269 const ThemeProvider* theme = [[[self view] window] themeProvider];
265 if (theme) 270 if (theme)
266 skBackgroundColor = theme->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND); 271 skBackgroundColor = theme->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
267 content::RenderWidgetHostView* rwhv = contents_->GetRenderWidgetHostView(); 272 content::RenderWidgetHostView* rwhv = contents_->GetRenderWidgetHostView();
268 if (rwhv) 273 if (rwhv)
269 rwhv->SetBackgroundColor(skBackgroundColor); 274 rwhv->SetBackgroundColor(skBackgroundColor);
270 } 275 }
271 276
272 - (void)updateFullscreenWidgetFrame { 277 - (void)updateFullscreenWidgetFrame {
273 // This should only apply if a fullscreen widget is embedded. 278 // This should only apply if a fullscreen widget is embedded.
274 if (!isEmbeddingFullscreenWidget_ || blockFullscreenResize_) 279 if (!isEmbeddingFullscreenWidget_ || blockFullscreenResize_)
275 return; 280 return;
276 281
277 content::RenderWidgetHostView* const fullscreenView = 282 content::RenderWidgetHostView* const fullscreenView =
278 contents_->GetFullscreenRenderWidgetHostView(); 283 contents_->GetFullscreenRenderWidgetHostView();
279 if (fullscreenView) 284 if (fullscreenView) {
280 [fullscreenView->GetNativeView() setFrame:[self frameForContentsView]]; 285 [fullscreenView->GetNativeView()
286 setFrame:[self frameForContentsViewIn:[self view]]];
287 }
281 } 288 }
282 289
283 - (void)changeWebContents:(WebContents*)newContents { 290 - (void)changeWebContents:(WebContents*)newContents {
284 contents_ = newContents; 291 contents_ = newContents;
285 fullscreenObserver_->Observe(contents_); 292 fullscreenObserver_->Observe(contents_);
286 isEmbeddingFullscreenWidget_ = 293 isEmbeddingFullscreenWidget_ =
287 contents_ && contents_->GetFullscreenRenderWidgetHostView(); 294 contents_ && contents_->GetFullscreenRenderWidgetHostView();
288 } 295 }
289 296
290 // Returns YES if the tab represented by this controller is the front-most. 297 // Returns YES if the tab represented by this controller is the front-most.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // focus (for example, if the omnibox has focus instead). The WebContents 329 // focus (for example, if the omnibox has focus instead). The WebContents
323 // logic will restore focus to the appropriate view. 330 // logic will restore focus to the appropriate view.
324 } 331 }
325 332
326 - (void)tabDidChange:(WebContents*)updatedContents { 333 - (void)tabDidChange:(WebContents*)updatedContents {
327 // Calling setContentView: here removes any first responder status 334 // Calling setContentView: here removes any first responder status
328 // the view may have, so avoid changing the view hierarchy unless 335 // the view may have, so avoid changing the view hierarchy unless
329 // the view is different. 336 // the view is different.
330 if ([self webContents] != updatedContents) { 337 if ([self webContents] != updatedContents) {
331 [self changeWebContents:updatedContents]; 338 [self changeWebContents:updatedContents];
332 [self ensureContentsVisible]; 339 [self addContentsToView:nil];
ccameron 2016/07/12 18:56:58 [self ensureContentsVisibleWithSuperview:[[self vi
tapted 2016/07/13 03:33:18 Done.
333 } 340 }
334 } 341 }
335 342
336 - (void)toggleFullscreenWidget:(BOOL)enterFullscreen { 343 - (void)toggleFullscreenWidget:(BOOL)enterFullscreen {
337 isEmbeddingFullscreenWidget_ = enterFullscreen && 344 isEmbeddingFullscreenWidget_ = enterFullscreen &&
338 contents_ && contents_->GetFullscreenRenderWidgetHostView(); 345 contents_ && contents_->GetFullscreenRenderWidgetHostView();
339 [self ensureContentsVisible]; 346 [self addContentsToView:nil];
ccameron 2016/07/12 18:56:58 ditto.
tapted 2016/07/13 03:33:18 Done.
340 } 347 }
341 348
342 - (BOOL)contentsInFullscreenCaptureMode { 349 - (BOOL)contentsInFullscreenCaptureMode {
343 // Note: Grab a known-valid WebContents pointer from |fullscreenObserver_|. 350 // Note: Grab a known-valid WebContents pointer from |fullscreenObserver_|.
344 content::WebContents* const wc = fullscreenObserver_->web_contents(); 351 content::WebContents* const wc = fullscreenObserver_->web_contents();
345 if (!wc || 352 if (!wc ||
346 wc->GetCapturerCount() == 0 || 353 wc->GetCapturerCount() == 0 ||
347 wc->GetPreferredSize().IsEmpty() || 354 wc->GetPreferredSize().IsEmpty() ||
348 !(isEmbeddingFullscreenWidget_ || 355 !(isEmbeddingFullscreenWidget_ ||
349 (wc->GetDelegate() && 356 (wc->GetDelegate() &&
350 wc->GetDelegate()->IsFullscreenForTabOrPending(wc)))) { 357 wc->GetDelegate()->IsFullscreenForTabOrPending(wc)))) {
351 return NO; 358 return NO;
352 } 359 }
353 return YES; 360 return YES;
354 } 361 }
355 362
356 - (NSRect)frameForContentsView { 363 - (NSRect)frameForContentsViewIn:(NSView*)container {
357 const NSSize containerSize = [[self view] frame].size; 364 gfx::Rect rect([container bounds]);
358 gfx::Rect rect;
359 rect.set_width(containerSize.width);
360 rect.set_height(containerSize.height);
361 365
362 // In most cases, the contents view is simply sized to fill the container 366 // In most cases, the contents view is simply sized to fill the container
363 // view's bounds. Only WebContentses that are in fullscreen mode and being 367 // view's bounds. Only WebContentses that are in fullscreen mode and being
364 // screen-captured will engage the special layout/sizing behavior. 368 // screen-captured will engage the special layout/sizing behavior.
365 if (![self contentsInFullscreenCaptureMode]) 369 if (![self contentsInFullscreenCaptureMode])
366 return NSRectFromCGRect(rect.ToCGRect()); 370 return NSRectFromCGRect(rect.ToCGRect());
367 371
368 // Size the contents view to the capture video resolution and center it. If 372 // Size the contents view to the capture video resolution and center it. If
369 // the container view is not large enough to fit it at the preferred size, 373 // the container view is not large enough to fit it at the preferred size,
370 // scale down to fit (preserving aspect ratio). 374 // scale down to fit (preserving aspect ratio).
(...skipping 24 matching lines...) Expand all
395 399
396 - (BOOL)shouldResizeContentView { 400 - (BOOL)shouldResizeContentView {
397 return !isEmbeddingFullscreenWidget_ || !blockFullscreenResize_; 401 return !isEmbeddingFullscreenWidget_ || !blockFullscreenResize_;
398 } 402 }
399 403
400 - (BOOL)isPopup { 404 - (BOOL)isPopup {
401 return isPopup_; 405 return isPopup_;
402 } 406 }
403 407
404 @end 408 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h ('k') | chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698