Chromium Code Reviews| Index: chrome/browser/cocoa/browser_window_controller.mm |
| =================================================================== |
| --- chrome/browser/cocoa/browser_window_controller.mm (revision 29973) |
| +++ chrome/browser/cocoa/browser_window_controller.mm (working copy) |
| @@ -60,10 +60,6 @@ |
| // Note: These functions are private, use -[NSObject respondsToSelector:] |
| // before calling them. |
| -- (void)setAutorecalculatesContentBorderThickness:(BOOL)b |
| - forEdge:(NSRectEdge)e; |
| -- (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e; |
| - |
| - (void)setBottomCornerRounded:(BOOL)rounded; |
| - (NSRect)_growBoxRect; |
| @@ -116,18 +112,14 @@ |
| ownsBrowser_ = ownIt; |
| tabObserver_.reset( |
| new TabStripModelObserverBridge(browser->tabstrip_model(), self)); |
| - windowShim_.reset(new BrowserWindowCocoa(browser, self, [self window])); |
| + NSWindow* window = [self window]; |
| + windowShim_.reset(new BrowserWindowCocoa(browser, self, window)); |
| - // The window is now fully realized and |-windowDidLoad:| has been |
| - // called. We shouldn't do much in wDL because |windowShim_| won't yet |
| - // be initialized (as it's called in response to |[self window]| above). |
| - // Retain it per the comment in the header. |
| - window_.reset([[self window] retain]); |
| // Sets the window to not have rounded corners, which prevents |
| // the resize control from being inset slightly and looking ugly. |
| - if ([window_ respondsToSelector:@selector(setBottomCornerRounded:)]) |
| - [window_ setBottomCornerRounded:NO]; |
| + if ([window respondsToSelector:@selector(setBottomCornerRounded:)]) |
| + [window setBottomCornerRounded:NO]; |
| [self setTheme]; |
| @@ -222,7 +214,7 @@ |
| [self layoutSubviews]; |
| // Create the bridge for the status bubble. |
| - statusBubble_.reset(new StatusBubbleMac([self window], self)); |
| + statusBubble_ = new StatusBubbleMac([self window], self); |
| } |
| return self; |
| } |
| @@ -234,10 +226,6 @@ |
| // Under certain testing configurations we may not actually own the browser. |
| if (ownsBrowser_ == NO) |
| browser_.release(); |
| - // Since |window_| outlives our obj-c shutdown sequence, clear out the |
| - // delegate so nothing tries to call us back in the meantime as part of |
| - // window destruction. |
| - [window_ setDelegate:nil]; |
| [super dealloc]; |
| } |
| @@ -251,7 +239,13 @@ |
| [NSApp removeWindowsItem:[self window]]; |
| // We need the window to go away now. |
| - [self autorelease]; |
| + // We can't actually use |-autorelease| here because there's an embedded |
| + // run loop in the |-performClose:| which contains its own autorelease pool. |
| + // Instead we use call it after a zero-length delay, which gets us back |
| + // to the main event loop. |
| + [self performSelector:@selector(autorelease) |
| + withObject:nil |
| + afterDelay:0]; |
| } |
| // Called when the window meets the criteria to be closed (ie, |
| @@ -259,16 +253,14 @@ |
| // semantics of BrowserWindow::Close() and not call the Browser's dtor directly |
| // from this method. |
| - (void)windowWillClose:(NSNotification*)notification { |
| - // Don't update the window any longer. |
| - // TODO(shess,dmaclach): This is a work-around for some cases where |
| - // the window's views were living longer than this controller, and |
| - // were then being re-displayed. Better would be to have it live |
| - // the appropriate amount of time, at which point we can remove |
| - // this. [And perhaps the funky -autorelease below can be fixed.] |
| - [window_ setAutodisplay:NO]; |
| - |
| + DCHECK_EQ([notification object], [self window]); |
| DCHECK(!browser_->tabstrip_model()->count()); |
| - |
| + [savedRegularWindow_ close]; |
| + [bookmarkBubbleController_ close]; |
| + // We delete statusBubble here because we need to kill off the dependency |
| + // that its window has on our window before our window goes away. |
| + delete statusBubble_; |
| + statusBubble_ = NULL; |
| // We can't actually use |-autorelease| here because there's an embedded |
| // run loop in the |-performClose:| which contains its own autorelease pool. |
| // Instead we use call it after a zero-length delay, which gets us back |
| @@ -350,8 +342,7 @@ |
| // message, since it just means that a menu extra (on the "system status bar") |
| // was activated; we'll get another |-windowDidResignKey| if we ever really |
| // lose key window status. |
| - if ([NSApp isActive] && |
| - ([NSApp keyWindow] == static_cast<NSWindow*>(window_))) |
| + if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) |
| return; |
| // We need to deactivate the controls (in the "WebView"). To do this, get the |
| @@ -424,6 +415,10 @@ |
| return frame; |
| } |
| +- (void)activate { |
| + [[self window] makeKeyAndOrderFront:self]; |
| +} |
| + |
| // Determine whether we should let a window zoom/unzoom to the given |newFrame|. |
| // We avoid letting unzoom move windows between screens, because it's really |
| // strange and unintuitive. |
| @@ -637,7 +632,7 @@ |
| } |
| - (StatusBubbleMac*)statusBubble { |
| - return statusBubble_.get(); |
| + return statusBubble_; |
| } |
| - (void)updateToolbarWithContents:(TabContents*)tab |
| @@ -654,13 +649,14 @@ |
| // in the coordinate system of the content area of the currently selected tab. |
| // |windowGrowBox| needs to be in the window's coordinate system. |
| - (NSRect)selectedTabGrowBoxRect { |
| - if (![window_ respondsToSelector:@selector(_growBoxRect)]) |
| + NSWindow* window = [self window]; |
| + if (![window respondsToSelector:@selector(_growBoxRect)]) |
| return NSZeroRect; |
| // Before we return a rect, we need to convert it from window coordinates |
| // to tab content area coordinates and flip the coordinate system. |
| NSRect growBoxRect = |
| - [[self tabContentArea] convertRect:[window_ _growBoxRect] fromView:nil]; |
| + [[self tabContentArea] convertRect:[window _growBoxRect] fromView:nil]; |
| growBoxRect.origin.y = |
| [[self tabContentArea] frame].size.height - growBoxRect.size.height - |
| growBoxRect.origin.y; |
| @@ -763,17 +759,6 @@ |
| [toolbarController_ setIsLoading:isLoading]; |
| } |
| -- (void)activate { |
| - // TODO(rohitrao): Figure out the proper activation behavior for fullscreen |
| - // windows. When there is only one window open, this code makes sense, but |
| - // what should we do if we need to activate a non-fullscreen background window |
| - // while a fullscreen window has focus? http://crbug.com/24893 |
| - if (fullscreen_) |
| - [fullscreen_window_ makeKeyAndOrderFront:self]; |
| - else |
| - [window_ makeKeyAndOrderFront:self]; |
| -} |
| - |
| // Make the location bar the first responder, if possible. |
| - (void)focusLocationBar { |
| [toolbarController_ focusLocationBar]; |
| @@ -928,64 +913,48 @@ |
| if (![self supportsFullscreen]) |
| return; |
| - fullscreen_ = fullscreen; |
| - if (fullscreen) { |
| - // Move content to a new fullscreen window |
| - NSView* content = [[self window] contentView]; |
| - // Disable autoresizing of subviews while we move views around. This |
| - // prevents spurious renderer resizes. |
| - [content setAutoresizesSubviews:NO]; |
| - fullscreen_window_.reset([[self fullscreenWindow] retain]); |
| - [content removeFromSuperview]; |
| - [fullscreen_window_ setContentView:content]; |
| - [self setWindow:fullscreen_window_.get()]; |
| - [window_ setWindowController:nil]; |
| - [window_ setDelegate:nil]; |
| - // Required for proper event dispatch. |
| - [fullscreen_window_ setWindowController:self]; |
| - [fullscreen_window_ setDelegate:self]; |
| + NSWindow* window = [self window]; |
| - // Minimize our UI. This call triggers a relayout, so it needs to come |
| - // after we move the contentview to the new window. |
| - [self adjustUIForFullscreen:fullscreen]; |
| - // Show one window, hide the other. |
| - [fullscreen_window_ makeKeyAndOrderFront:self]; |
| - [content setAutoresizesSubviews:YES]; |
| - [content setNeedsDisplay:YES]; |
| - [window_ orderOut:self]; |
| - } else { |
| - NSView* content = [fullscreen_window_ contentView]; |
| - // Disable autoresizing of subviews while we move views around. This |
| - // prevents spurious renderer resizes. |
| - [content setAutoresizesSubviews:NO]; |
| - [content removeFromSuperview]; |
| - [window_ setContentView:content]; |
| - [fullscreen_window_ setDelegate:nil]; |
| - [fullscreen_window_ setWindowController:nil]; |
| - [window_ setWindowController:self]; |
| - [window_ setDelegate:self]; |
| - [self setWindow:window_.get()]; |
| - // This call triggers a relayout, so it needs to come after we move the |
| - // contentview to the new window. |
| - [self adjustUIForFullscreen:fullscreen]; |
| - [content setAutoresizesSubviews:YES]; |
| - [content setNeedsDisplay:YES]; |
| + // Retain the contentView while we remove it from its superview. |
| + scoped_nsobject<NSView> content([[window contentView] retain]); |
| - // With this call, valgrind yells at me about "Conditional jump or |
| - // move depends on uninitialised value(s)". The error happens in |
| - // -[NSThemeFrame drawOverlayRect:]. I'm pretty convinced this is |
| - // an Apple bug, but there is no visual impact. I have been |
| - // unable to tickle it away with other window or view manipulation |
| - // Cocoa calls. Stack added to suppressions_mac.txt. |
| - [window_ makeKeyAndOrderFront:self]; |
| + // Disable autoresizing of subviews while we move views around. This |
| + // prevents spurious renderer resizes. |
| + [content setAutoresizesSubviews:NO]; |
| + [content removeFromSuperview]; |
| - [fullscreen_window_ close]; |
| - fullscreen_window_.reset(nil); |
| + NSWindow* dstWindow = nil; |
| + if (fullscreen) { |
| + DCHECK(!savedRegularWindow_); |
| + savedRegularWindow_ = [window retain]; |
| + dstWindow = [self fullscreenWindow]; |
| + } else { |
| + DCHECK(savedRegularWindow_); |
| + dstWindow = [savedRegularWindow_ autorelease]; |
| + savedRegularWindow_ = nil; |
| } |
| + |
| + // With this call, valgrind yells at me about "Conditional jump or |
| + // move depends on uninitialised value(s)". The error happens in |
| + // -[NSThemeFrame drawOverlayRect:]. I'm pretty convinced this is |
| + // an Apple bug, but there is no visual impact. I have been |
| + // unable to tickle it away with other window or view manipulation |
| + // Cocoa calls. Stack added to suppressions_mac.txt. |
|
Scott Hess - ex-Googler
2009/10/26 19:45:21
Just checking - does this comment now apply to -se
|
| + [content setAutoresizesSubviews:YES]; |
|
Scott Hess - ex-Googler
2009/10/26 19:45:21
Previously this line was way down the list. The c
|
| + [dstWindow setContentView:content]; |
| + [window setWindowController:nil]; |
| + [window setDelegate:nil]; |
| + [self setWindow:dstWindow]; |
| + [dstWindow setWindowController:self]; |
| + [dstWindow setDelegate:self]; |
| + [self adjustUIForFullscreen:fullscreen]; |
| + [dstWindow makeKeyAndOrderFront:self]; |
| + |
| + [window orderOut:self]; |
| } |
| - (BOOL)isFullscreen { |
| - return fullscreen_; |
| + return savedRegularWindow_ != nil; |
| } |
| // Called by the bookmark bar to open a URL. |
| @@ -1088,25 +1057,37 @@ |
| // Show the bookmark bubble (e.g. user just clicked on the STAR). |
| - (void)showBookmarkBubbleForURL:(const GURL&)url |
| alreadyBookmarked:(BOOL)alreadyBookmarked { |
| - BookmarkModel* model = browser_->profile()->GetBookmarkModel(); |
| - const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url); |
| - |
| - // Bring up the bubble. But clicking on STAR while the bubble is |
| - // open should make it go away. |
| - if (bookmarkBubbleController_.get()) { |
| - [self doneWithBubbleController:bookmarkBubbleController_.get()]; |
| - } else { |
| - bookmarkBubbleController_.reset([[BookmarkBubbleController alloc] |
| - initWithDelegate:self |
| - parentWindow:[self window] |
| - topLeftForBubble:[self topLeftForBubble] |
| - model:model |
| - node:node |
| - alreadyBookmarked:alreadyBookmarked]); |
| - [bookmarkBubbleController_ showWindow]; |
| + if (!bookmarkBubbleController_) { |
| + BookmarkModel* model = browser_->profile()->GetBookmarkModel(); |
| + const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(url); |
| + NSPoint topLeft = [self topLeftForBubble]; |
| + bookmarkBubbleController_ = |
| + [[BookmarkBubbleController alloc] initWithDelegate:self |
| + parentWindow:[self window] |
| + topLeftForBubble:topLeft |
| + model:model |
| + node:node |
| + alreadyBookmarked:alreadyBookmarked]; |
| + NSWindow* bookmarkBubbleWindow = [bookmarkBubbleController_ window]; |
| + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| + [nc addObserver:self |
| + selector:@selector(bubbleWindowWillClose:) |
| + name:NSWindowWillCloseNotification |
| + object:bookmarkBubbleWindow]; |
| + [bookmarkBubbleController_ showWindow:self]; |
| } |
| } |
| +// Notification sent when our bubble window is closed. |
| +- (void)bubbleWindowWillClose:(NSNotification*)notification { |
| + DCHECK([[notification object] windowController] == bookmarkBubbleController_); |
| + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| + [nc removeObserver:self |
| + name:NSWindowWillCloseNotification |
| + object:[bookmarkBubbleController_ window]]; |
| + bookmarkBubbleController_ = nil; |
| +} |
| + |
| // Implement BookmarkBubbleControllerDelegate |
| - (void)editBookmarkNode:(const BookmarkNode*)node { |
| // A BookmarkEditorController is a sheet that owns itself, and |
| @@ -1121,17 +1102,14 @@ |
| runAsModalSheet]; |
| } |
| -// Implement BookmarkBubbleControllerDelegate |
| -- (void)doneWithBubbleController:(BookmarkBubbleController*)controller { |
| - bookmarkBubbleController_.reset(nil); |
| -} |
| // Delegate method called when window is resized. |
| - (void)windowDidResize:(NSNotification*)notification { |
| // Resize (and possibly move) the status bubble. Note that we may get called |
| // when the status bubble does not exist. |
| - if (statusBubble_.get()) |
| + if (statusBubble_) { |
| statusBubble_->UpdateSizeAndPosition(); |
| + } |
| } |
| @end |
| @@ -1276,25 +1254,27 @@ |
| // the entire content area. Otherwise, this method places the topmost view |
| // directly beneath the tabstrip. |
| - (void)layoutSubviews { |
| - NSView* contentView = fullscreen_ ? [fullscreen_window_ contentView] |
| - : [[self window] contentView]; |
| + NSWindow* window = [self window]; |
| + NSView* contentView = [window contentView]; |
| NSRect contentFrame = [contentView frame]; |
| int maxY = NSMaxY(contentFrame); |
| int minY = NSMinY(contentFrame); |
| - if (!fullscreen_ && [self isNormalWindow]) { |
| + if (![self isFullscreen] && [self isNormalWindow]) { |
| maxY = NSMinY([[self tabStripView] frame]); |
| } |
| DCHECK_GE(maxY, minY); |
| // Suppress title drawing for normal windows (popups use normal |
| // window title bars). |
| - [window_ setShouldHideTitle:[self isNormalWindow]]; |
| + if ([window respondsToSelector:@selector(setShouldHideTitle:)]) { |
| + [(id)window setShouldHideTitle:[self isNormalWindow]]; |
| + } |
| // Place the toolbar at the top of the reserved area, but only if we're not in |
| // fullscreen mode. |
| NSView* toolbarView = [toolbarController_ view]; |
| NSRect toolbarFrame = [toolbarView frame]; |
| - if (!fullscreen_) { |
| + if (![self isFullscreen]) { |
| // The toolbar is present in the window, so we make room for it. |
| toolbarFrame.origin.x = 0; |
| toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame); |