| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #include <Carbon/Carbon.h> | 5 #include <Carbon/Carbon.h> |
| 6 | 6 |
| 7 #include "base/mac_util.h" | 7 #include "base/mac_util.h" |
| 8 #include "base/scoped_nsdisable_screen_updates.h" | 8 #include "base/scoped_nsdisable_screen_updates.h" |
| 9 #import "base/scoped_nsobject.h" | 9 #import "base/scoped_nsobject.h" |
| 10 #include "base/sys_string_conversions.h" | 10 #include "base/sys_string_conversions.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 // Note: These functions are private, use -[NSObject respondsToSelector:] | 55 // Note: These functions are private, use -[NSObject respondsToSelector:] |
| 56 // before calling them. | 56 // before calling them. |
| 57 | 57 |
| 58 - (void)setAutorecalculatesContentBorderThickness:(BOOL)b | 58 - (void)setAutorecalculatesContentBorderThickness:(BOOL)b |
| 59 forEdge:(NSRectEdge)e; | 59 forEdge:(NSRectEdge)e; |
| 60 - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e; | 60 - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e; |
| 61 | 61 |
| 62 - (void)setBottomCornerRounded:(BOOL)rounded; | 62 - (void)setBottomCornerRounded:(BOOL)rounded; |
| 63 | 63 |
| 64 - (NSRect)_growBoxRect; | 64 - (NSRect)_growBoxRect; |
| 65 |
| 65 @end | 66 @end |
| 66 | 67 |
| 67 | 68 |
| 68 @interface BrowserWindowController(Private) | 69 @interface BrowserWindowController(Private) |
| 69 | 70 |
| 70 // Leopard's gradient heuristic gets confused by our tabs and makes the title | 71 // Leopard's gradient heuristic gets confused by our tabs and makes the title |
| 71 // gradient jump when creating a tab that is less than a tab width from the | 72 // gradient jump when creating a tab that is less than a tab width from the |
| 72 // right side of the screen. This function disables Leopard's gradient | 73 // right side of the screen. This function disables Leopard's gradient |
| 73 // heuristic. | 74 // heuristic. |
| 74 - (void)fixWindowGradient; | 75 - (void)fixWindowGradient; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 } | 232 } |
| 232 | 233 |
| 233 - (void)destroyBrowser { | 234 - (void)destroyBrowser { |
| 234 [NSApp removeWindowsItem:[self window]]; | 235 [NSApp removeWindowsItem:[self window]]; |
| 235 | 236 |
| 236 // We need the window to go away now. | 237 // We need the window to go away now. |
| 237 [self autorelease]; | 238 [self autorelease]; |
| 238 } | 239 } |
| 239 | 240 |
| 240 // Called when the window meets the criteria to be closed (ie, | 241 // Called when the window meets the criteria to be closed (ie, |
| 241 // |-windowShoudlClose:| returns YES). We must be careful to preserve the | 242 // |-windowShouldClose:| returns YES). We must be careful to preserve the |
| 242 // semantics of BrowserWindow::Close() and not call the Browser's dtor directly | 243 // semantics of BrowserWindow::Close() and not call the Browser's dtor directly |
| 243 // from this method. | 244 // from this method. |
| 244 - (void)windowWillClose:(NSNotification*)notification { | 245 - (void)windowWillClose:(NSNotification*)notification { |
| 245 DCHECK(!browser_->tabstrip_model()->count()); | 246 DCHECK(!browser_->tabstrip_model()->count()); |
| 246 | 247 |
| 247 // We can't actually use |-autorelease| here because there's an embedded | 248 // We can't actually use |-autorelease| here because there's an embedded |
| 248 // run loop in the |-performClose:| which contains its own autorelease pool. | 249 // run loop in the |-performClose:| which contains its own autorelease pool. |
| 249 // Instead we use call it after a zero-length delay, which gets us back | 250 // Instead we use call it after a zero-length delay, which gets us back |
| 250 // to the main event loop. | 251 // to the main event loop. |
| 251 [self performSelector:@selector(autorelease) | 252 [self performSelector:@selector(autorelease) |
| 252 withObject:nil | 253 withObject:nil |
| 253 afterDelay:0]; | 254 afterDelay:0]; |
| 254 } | 255 } |
| 255 | 256 |
| 257 // Checks if there are any tabs with sheets open, and if so, raises one of |
| 258 // the tabs with a sheet and returns NO. |
| 259 - (BOOL)shouldCloseWithOpenPerTabSheets { |
| 260 // This is O(n_open_sheets * n_tabs), i.e. O(n**2). Since people probably |
| 261 // won't have 100 tabs open, and not every tab will have a sheet, this is ok. |
| 262 for (NSView* view in |
| 263 [[tabStripController_ sheetController] viewsWithAttachedSheets]) { |
| 264 [tabStripController_ gtm_systemRequestsVisibilityForView:view]; |
| 265 return NO; |
| 266 } |
| 267 |
| 268 return YES; |
| 269 } |
| 270 |
| 271 - (void)attachConstrainedWindow:(ConstrainedWindowMac*)window { |
| 272 [tabStripController_ attachConstrainedWindow:window]; |
| 273 } |
| 274 |
| 275 - (void)removeConstrainedWindow:(ConstrainedWindowMac*)window { |
| 276 [tabStripController_ removeConstrainedWindow:window]; |
| 277 } |
| 278 |
| 256 // Called when the user wants to close a window or from the shutdown process. | 279 // Called when the user wants to close a window or from the shutdown process. |
| 257 // The Browser object is in control of whether or not we're allowed to close. It | 280 // The Browser object is in control of whether or not we're allowed to close. It |
| 258 // may defer closing due to several states, such as onUnload handlers needing to | 281 // may defer closing due to several states, such as onUnload handlers needing to |
| 259 // be fired. If closing is deferred, the Browser will handle the processing | 282 // be fired. If closing is deferred, the Browser will handle the processing |
| 260 // required to get us to the closing state and (by watching for all the tabs | 283 // required to get us to the closing state and (by watching for all the tabs |
| 261 // going away) will again call to close the window when it's finally ready. | 284 // going away) will again call to close the window when it's finally ready. |
| 262 - (BOOL)windowShouldClose:(id)sender { | 285 - (BOOL)windowShouldClose:(id)sender { |
| 286 // Do not close a window with open sheets, as required by |
| 287 // GTMWindowSheetController. |
| 288 if (![self shouldCloseWithOpenPerTabSheets]) |
| 289 return NO; |
| 290 |
| 263 // Disable updates while closing all tabs to avoid flickering. | 291 // Disable updates while closing all tabs to avoid flickering. |
| 264 base::ScopedNSDisableScreenUpdates disabler; | 292 base::ScopedNSDisableScreenUpdates disabler; |
| 265 // Give beforeunload handlers the chance to cancel the close before we hide | 293 // Give beforeunload handlers the chance to cancel the close before we hide |
| 266 // the window below. | 294 // the window below. |
| 267 if (!browser_->ShouldCloseWindow()) | 295 if (!browser_->ShouldCloseWindow()) |
| 268 return NO; | 296 return NO; |
| 269 | 297 |
| 270 // saveWindowPositionIfNeeded: only works if we are the last active | 298 // saveWindowPositionIfNeeded: only works if we are the last active |
| 271 // window, but orderOut: ends up activating another window, so we | 299 // window, but orderOut: ends up activating another window, so we |
| 272 // have to save the window position before we call orderOut:. | 300 // have to save the window position before we call orderOut:. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 return; | 441 return; |
| 414 } | 442 } |
| 415 const std::wstring encoding = current_tab->encoding(); | 443 const std::wstring encoding = current_tab->encoding(); |
| 416 | 444 |
| 417 bool toggled = encoding_controller.IsItemChecked(profile, encoding, tag); | 445 bool toggled = encoding_controller.IsItemChecked(profile, encoding, tag); |
| 418 NSInteger oldState = [item state]; | 446 NSInteger oldState = [item state]; |
| 419 NSInteger newState = toggled ? NSOnState : NSOffState; | 447 NSInteger newState = toggled ? NSOnState : NSOffState; |
| 420 if (oldState != newState) | 448 if (oldState != newState) |
| 421 [item setState:newState]; | 449 [item setState:newState]; |
| 422 } | 450 } |
| 451 } |
| 423 | 452 |
| 453 - (BOOL)supportsFullscreen { |
| 454 // TODO(avi, thakis): GTMWindowSheetController has no api to move |
| 455 // tabsheets between windows. Until then, we have to prevent having to |
| 456 // move a tabsheet between windows, e.g. no fullscreen toggling |
| 457 NSArray* a = [[tabStripController_ sheetController] viewsWithAttachedSheets]; |
| 458 return [a count] == 0; |
| 424 } | 459 } |
| 425 | 460 |
| 426 // Called to validate menu and toolbar items when this window is key. All the | 461 // Called to validate menu and toolbar items when this window is key. All the |
| 427 // items we care about have been set with the |commandDispatch:| action and | 462 // items we care about have been set with the |commandDispatch:| action and |
| 428 // a target of FirstResponder in IB. If it's not one of those, let it | 463 // a target of FirstResponder in IB. If it's not one of those, let it |
| 429 // continue up the responder chain to be handled elsewhere. We pull out the | 464 // continue up the responder chain to be handled elsewhere. We pull out the |
| 430 // tag as the cross-platform constant to differentiate and dispatch the | 465 // tag as the cross-platform constant to differentiate and dispatch the |
| 431 // various commands. | 466 // various commands. |
| 432 // NOTE: we might have to handle state for app-wide menu items, | 467 // NOTE: we might have to handle state for app-wide menu items, |
| 433 // although we could cheat and directly ask the app controller if our | 468 // although we could cheat and directly ask the app controller if our |
| (...skipping 11 matching lines...) Expand all Loading... |
| 445 case IDC_CLOSE_TAB: | 480 case IDC_CLOSE_TAB: |
| 446 // Disable "close tab" if we're not the key window or if there's only | 481 // Disable "close tab" if we're not the key window or if there's only |
| 447 // one tab. | 482 // one tab. |
| 448 enable &= [self numberOfTabs] > 1 && [[self window] isKeyWindow]; | 483 enable &= [self numberOfTabs] > 1 && [[self window] isKeyWindow]; |
| 449 break; | 484 break; |
| 450 case IDC_RESTORE_TAB: | 485 case IDC_RESTORE_TAB: |
| 451 // We have to ask the Browser manually if we can restore. The | 486 // We have to ask the Browser manually if we can restore. The |
| 452 // command updater doesn't know. | 487 // command updater doesn't know. |
| 453 enable &= browser_->CanRestoreTab(); | 488 enable &= browser_->CanRestoreTab(); |
| 454 break; | 489 break; |
| 490 case IDC_FULLSCREEN: |
| 491 enable &= [self supportsFullscreen]; |
| 492 break; |
| 455 } | 493 } |
| 456 | 494 |
| 457 // If the item is toggleable, find its toggle state and | 495 // If the item is toggleable, find its toggle state and |
| 458 // try to update it. This is a little awkward, but the alternative is | 496 // try to update it. This is a little awkward, but the alternative is |
| 459 // to check after a commandDispatch, which seems worse. | 497 // to check after a commandDispatch, which seems worse. |
| 460 [self updateToggleStateWithTag:tag forItem:item]; | 498 [self updateToggleStateWithTag:tag forItem:item]; |
| 461 } | 499 } |
| 462 } | 500 } |
| 463 return enable; | 501 return enable; |
| 464 } | 502 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 - (float)verticalOffsetForStatusBubble { | 538 - (float)verticalOffsetForStatusBubble { |
| 501 float offset = 0.0; | 539 float offset = 0.0; |
| 502 | 540 |
| 503 // Don't create a download shelf if there isn't one. | 541 // Don't create a download shelf if there isn't one. |
| 504 if (downloadShelfController_.get() && [[self downloadShelf] isVisible]) | 542 if (downloadShelfController_.get() && [[self downloadShelf] isVisible]) |
| 505 offset += [[self downloadShelf] height]; | 543 offset += [[self downloadShelf] height]; |
| 506 | 544 |
| 507 return offset; | 545 return offset; |
| 508 } | 546 } |
| 509 | 547 |
| 548 - (GTMWindowSheetController*)sheetController { |
| 549 return [tabStripController_ sheetController]; |
| 550 } |
| 551 |
| 510 - (LocationBar*)locationBar { | 552 - (LocationBar*)locationBar { |
| 511 return [toolbarController_ locationBar]; | 553 return [toolbarController_ locationBar]; |
| 512 } | 554 } |
| 513 | 555 |
| 514 - (StatusBubble*)statusBubble { | 556 - (StatusBubble*)statusBubble { |
| 515 return statusBubble_.get(); | 557 return statusBubble_.get(); |
| 516 } | 558 } |
| 517 | 559 |
| 518 - (void)updateToolbarWithContents:(TabContents*)tab | 560 - (void)updateToolbarWithContents:(TabContents*)tab |
| 519 shouldRestoreState:(BOOL)shouldRestore { | 561 shouldRestoreState:(BOOL)shouldRestore { |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 // Force a relayout. | 819 // Force a relayout. |
| 778 [self layoutSubviews]; | 820 [self layoutSubviews]; |
| 779 } | 821 } |
| 780 | 822 |
| 781 - (NSWindow*)fullscreenWindow { | 823 - (NSWindow*)fullscreenWindow { |
| 782 return [[[FullscreenWindow alloc] initForScreen:[[self window] screen]] | 824 return [[[FullscreenWindow alloc] initForScreen:[[self window] screen]] |
| 783 autorelease]; | 825 autorelease]; |
| 784 } | 826 } |
| 785 | 827 |
| 786 - (void)setFullscreen:(BOOL)fullscreen { | 828 - (void)setFullscreen:(BOOL)fullscreen { |
| 829 if (![self supportsFullscreen]) |
| 830 return; |
| 831 |
| 787 fullscreen_ = fullscreen; | 832 fullscreen_ = fullscreen; |
| 788 if (fullscreen) { | 833 if (fullscreen) { |
| 789 // Move content to a new fullscreen window | 834 // Move content to a new fullscreen window |
| 790 NSView* content = [[self window] contentView]; | 835 NSView* content = [[self window] contentView]; |
| 791 fullscreen_window_.reset([[self fullscreenWindow] retain]); | 836 fullscreen_window_.reset([[self fullscreenWindow] retain]); |
| 792 [content removeFromSuperview]; | 837 [content removeFromSuperview]; |
| 793 [fullscreen_window_ setContentView:content]; | 838 [fullscreen_window_ setContentView:content]; |
| 794 [self setWindow:fullscreen_window_.get()]; | 839 [self setWindow:fullscreen_window_.get()]; |
| 795 // Minimize our UI. This call triggers a relayout, so it needs to come | 840 // Minimize our UI. This call triggers a relayout, so it needs to come |
| 796 // after we move the contentview to the new window. | 841 // after we move the contentview to the new window. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 - (void)selectTabWithContents:(TabContents*)newContents | 899 - (void)selectTabWithContents:(TabContents*)newContents |
| 855 previousContents:(TabContents*)oldContents | 900 previousContents:(TabContents*)oldContents |
| 856 atIndex:(NSInteger)index | 901 atIndex:(NSInteger)index |
| 857 userGesture:(bool)wasUserGesture { | 902 userGesture:(bool)wasUserGesture { |
| 858 DCHECK(oldContents != newContents); | 903 DCHECK(oldContents != newContents); |
| 859 | 904 |
| 860 // Update various elements that are interested in knowing the current | 905 // Update various elements that are interested in knowing the current |
| 861 // TabContents. | 906 // TabContents. |
| 862 #if 0 | 907 #if 0 |
| 863 // TODO(pinkerton):Update as more things become window-specific | 908 // TODO(pinkerton):Update as more things become window-specific |
| 864 contents_container_->SetTabContents(new_contents); | 909 contents_container_->SetTabContents(newContents); |
| 865 #endif | 910 #endif |
| 866 | 911 |
| 867 // Update all the UI bits. | 912 // Update all the UI bits. |
| 868 windowShim_->UpdateTitleBar(); | 913 windowShim_->UpdateTitleBar(); |
| 869 #if 0 | 914 #if 0 |
| 870 // TODO(pinkerton):Update as more things become window-specific | 915 // TODO(pinkerton):Update as more things become window-specific |
| 871 toolbar_->SetProfile(new_contents->profile()); | 916 toolbar_->SetProfile(newContents->profile()); |
| 872 UpdateToolbar(new_contents, true); | 917 UpdateToolbar(newContents, true); |
| 873 UpdateUIForContents(new_contents); | 918 UpdateUIForContents(newContents); |
| 874 #endif | 919 #endif |
| 875 } | 920 } |
| 876 | 921 |
| 877 - (void)tabChangedWithContents:(TabContents*)contents | 922 - (void)tabChangedWithContents:(TabContents*)contents |
| 878 atIndex:(NSInteger)index | 923 atIndex:(NSInteger)index |
| 879 loadingOnly:(BOOL)loading { | 924 loadingOnly:(BOOL)loading { |
| 880 // Update titles if this is the currently selected tab. | 925 if (index == browser_->tabstrip_model()->selected_index()) { |
| 881 if (index == browser_->tabstrip_model()->selected_index()) | 926 // Update titles if this is the currently selected tab. |
| 882 windowShim_->UpdateTitleBar(); | 927 windowShim_->UpdateTitleBar(); |
| 928 } |
| 883 } | 929 } |
| 884 | 930 |
| 885 - (void)userChangedTheme { | 931 - (void)userChangedTheme { |
| 886 [self setTheme]; | 932 [self setTheme]; |
| 887 [self applyTheme]; | 933 [self applyTheme]; |
| 888 | 934 |
| 889 [tabStripController_ userChangedTheme]; | 935 [tabStripController_ userChangedTheme]; |
| 890 } | 936 } |
| 891 | 937 |
| 892 - (GTMTheme *)gtm_themeForWindow:(NSWindow*)window { | 938 - (GTMTheme *)gtm_themeForWindow:(NSWindow*)window { |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 NSColor* toolbarButtonBorderColor = toolbarButtonIconColor; | 1237 NSColor* toolbarButtonBorderColor = toolbarButtonIconColor; |
| 1192 [theme setValue:toolbarButtonBorderColor | 1238 [theme setValue:toolbarButtonBorderColor |
| 1193 forAttribute:@"borderColor" | 1239 forAttribute:@"borderColor" |
| 1194 style:GTMThemeStyleToolBar | 1240 style:GTMThemeStyleToolBar |
| 1195 state:YES]; | 1241 state:YES]; |
| 1196 | 1242 |
| 1197 return theme; | 1243 return theme; |
| 1198 } | 1244 } |
| 1199 @end | 1245 @end |
| 1200 | 1246 |
| OLD | NEW |