Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h" |
| 6 | 6 |
| 7 #include "apps/app_shim/extension_app_shim_handler_mac.h" | 7 #include "apps/app_shim/extension_app_shim_handler_mac.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 [window setCollectionBehavior:behavior]; | 80 [window setCollectionBehavior:behavior]; |
| 81 } | 81 } |
| 82 | 82 |
| 83 // Returns the level for windows that are configured to be always on top. | 83 // Returns the level for windows that are configured to be always on top. |
| 84 // This is not a constant because NSFloatingWindowLevel is a macro defined | 84 // This is not a constant because NSFloatingWindowLevel is a macro defined |
| 85 // as a function call. | 85 // as a function call. |
| 86 NSInteger AlwaysOnTopWindowLevel() { | 86 NSInteger AlwaysOnTopWindowLevel() { |
| 87 return NSFloatingWindowLevel; | 87 return NSFloatingWindowLevel; |
| 88 } | 88 } |
| 89 | 89 |
| 90 NSRect GfxToCocoaBounds(const gfx::Rect& bounds, | |
| 91 bool ensure_position_initialized) { | |
|
benwells
2014/03/05 02:33:30
Nit: indenting.
tapted
2014/03/05 03:14:03
nit: indenting. But also this is always called wit
| |
| 92 typedef apps::AppWindow::BoundsSpecification BoundsSpecification; | |
| 93 | |
| 94 // Flip coordinates based on the primary screen. | |
| 95 NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; | |
| 96 NSRect cocoa_bounds = NSMakeRect( | |
| 97 bounds.x(), | |
| 98 NSHeight(main_screen_rect) - bounds.y() - bounds.height(), | |
|
tapted
2014/03/05 03:14:03
nit (a bit nicer):
`NSHeight(main_screen_rect) - b
| |
| 99 bounds.width(), | |
| 100 bounds.height()); | |
| 101 | |
| 102 // If coordinates are < 0, center window on primary screen. | |
|
tapted
2014/03/05 03:14:03
This comment doesn't really match (-ve coordinates
| |
| 103 if (ensure_position_initialized && | |
| 104 bounds.x() == BoundsSpecification::kUnspecifiedPosition) { | |
| 105 cocoa_bounds.origin.x = | |
| 106 floor((NSWidth(main_screen_rect) - NSWidth(cocoa_bounds)) / 2); | |
| 107 } | |
| 108 if (ensure_position_initialized && | |
| 109 bounds.y() == BoundsSpecification::kUnspecifiedPosition) { | |
| 110 cocoa_bounds.origin.y = | |
| 111 floor((NSHeight(main_screen_rect) - NSHeight(cocoa_bounds)) / 2); | |
| 112 } | |
| 113 | |
| 114 return cocoa_bounds; | |
| 115 } | |
| 116 | |
| 90 } // namespace | 117 } // namespace |
| 91 | 118 |
| 92 @implementation NativeAppWindowController | 119 @implementation NativeAppWindowController |
| 93 | 120 |
| 94 @synthesize appWindow = appWindow_; | 121 @synthesize appWindow = appWindow_; |
| 95 | 122 |
| 96 - (void)windowWillClose:(NSNotification*)notification { | 123 - (void)windowWillClose:(NSNotification*)notification { |
| 97 if (appWindow_) | 124 if (appWindow_) |
| 98 appWindow_->WindowWillClose(); | 125 appWindow_->WindowWillClose(); |
| 99 } | 126 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 | 304 |
| 278 NativeAppWindowCocoa::NativeAppWindowCocoa( | 305 NativeAppWindowCocoa::NativeAppWindowCocoa( |
| 279 AppWindow* app_window, | 306 AppWindow* app_window, |
| 280 const AppWindow::CreateParams& params) | 307 const AppWindow::CreateParams& params) |
| 281 : app_window_(app_window), | 308 : app_window_(app_window), |
| 282 has_frame_(params.frame == AppWindow::FRAME_CHROME), | 309 has_frame_(params.frame == AppWindow::FRAME_CHROME), |
| 283 is_hidden_(false), | 310 is_hidden_(false), |
| 284 is_hidden_with_app_(false), | 311 is_hidden_with_app_(false), |
| 285 is_maximized_(false), | 312 is_maximized_(false), |
| 286 is_fullscreen_(false), | 313 is_fullscreen_(false), |
| 314 is_resizable_(params.resizable), | |
| 315 shows_resize_controls_(true), | |
| 316 shows_fullscreen_controls_(true), | |
| 287 attention_request_id_(0), | 317 attention_request_id_(0), |
| 288 use_system_drag_(true) { | 318 use_system_drag_(true) { |
| 289 Observe(web_contents()); | 319 Observe(web_contents()); |
| 290 | 320 |
| 291 // Flip coordinates based on the primary screen. | |
| 292 NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; | |
| 293 NSRect cocoa_bounds = NSMakeRect(params.bounds.x(), | |
| 294 NSHeight(main_screen_rect) - params.bounds.y() - params.bounds.height(), | |
| 295 params.bounds.width(), params.bounds.height()); | |
| 296 | |
| 297 // If coordinates are < 0, center window on primary screen. | |
| 298 if (params.bounds.x() == INT_MIN) { | |
| 299 cocoa_bounds.origin.x = | |
| 300 floor((NSWidth(main_screen_rect) - NSWidth(cocoa_bounds)) / 2); | |
| 301 } | |
| 302 if (params.bounds.y() == INT_MIN) { | |
| 303 cocoa_bounds.origin.y = | |
| 304 floor((NSHeight(main_screen_rect) - NSHeight(cocoa_bounds)) / 2); | |
| 305 } | |
| 306 | |
| 307 // Initialize |restored_bounds_| after |cocoa_bounds| have been sanitized. | |
| 308 restored_bounds_ = cocoa_bounds; | |
| 309 | |
| 310 base::scoped_nsobject<NSWindow> window; | 321 base::scoped_nsobject<NSWindow> window; |
| 311 Class window_class; | 322 Class window_class; |
| 312 if (has_frame_) { | 323 if (has_frame_) { |
| 313 bool should_use_native_frame = | 324 bool should_use_native_frame = |
| 314 CommandLine::ForCurrentProcess()->HasSwitch( | 325 CommandLine::ForCurrentProcess()->HasSwitch( |
| 315 switches::kAppsUseNativeFrame); | 326 switches::kAppsUseNativeFrame); |
| 316 window_class = should_use_native_frame ? | 327 window_class = should_use_native_frame ? |
| 317 [ShellNSWindow class] : [ShellCustomFrameNSWindow class]; | 328 [ShellNSWindow class] : [ShellCustomFrameNSWindow class]; |
| 318 } else { | 329 } else { |
| 319 window_class = [ShellFramelessNSWindow class]; | 330 window_class = [ShellFramelessNSWindow class]; |
| 320 } | 331 } |
| 321 | 332 |
| 322 size_constraints_.set_minimum_size(params.minimum_size); | 333 // Estimate the initial bounds of the window. Once the frame insets are known, |
| 323 size_constraints_.set_maximum_size(params.maximum_size); | 334 // the window bounds and constraints can be set precisely. |
| 324 shows_resize_controls_ = | 335 NSRect cocoa_bounds = GfxToCocoaBounds( |
| 325 params.resizable && !size_constraints_.HasFixedSize(); | 336 params.GetInitialWindowBounds(gfx::Insets()), true); |
| 326 shows_fullscreen_controls_ = | |
| 327 params.resizable && !size_constraints_.HasMaximumSize(); | |
| 328 window.reset([[window_class alloc] | 337 window.reset([[window_class alloc] |
| 329 initWithContentRect:cocoa_bounds | 338 initWithContentRect:cocoa_bounds |
| 330 styleMask:GetWindowStyleMask() | 339 styleMask:GetWindowStyleMask() |
| 331 backing:NSBackingStoreBuffered | 340 backing:NSBackingStoreBuffered |
| 332 defer:NO]); | 341 defer:NO]); |
| 333 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; | 342 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; |
| 334 | 343 |
| 335 if (base::mac::IsOSSnowLeopard() && | 344 if (base::mac::IsOSSnowLeopard() && |
| 336 [window respondsToSelector:@selector(setBottomCornerRounded:)]) | 345 [window respondsToSelector:@selector(setBottomCornerRounded:)]) |
| 337 [window setBottomCornerRounded:NO]; | 346 [window setBottomCornerRounded:NO]; |
| 338 | 347 |
| 339 if (params.always_on_top) | 348 if (params.always_on_top) |
| 340 [window setLevel:AlwaysOnTopWindowLevel()]; | 349 [window setLevel:AlwaysOnTopWindowLevel()]; |
| 341 InitCollectionBehavior(window); | 350 InitCollectionBehavior(window); |
| 342 | 351 |
| 343 // Set the window to participate in Lion Fullscreen mode. Setting this flag | |
| 344 // has no effect on Snow Leopard or earlier. UI controls for fullscreen are | |
| 345 // only shown for apps that have unbounded size. | |
| 346 if (shows_fullscreen_controls_) | |
| 347 SetFullScreenCollectionBehavior(window, true); | |
| 348 | |
| 349 window_controller_.reset( | 352 window_controller_.reset( |
| 350 [[NativeAppWindowController alloc] initWithWindow:window.release()]); | 353 [[NativeAppWindowController alloc] initWithWindow:window.release()]); |
| 351 | 354 |
| 352 NSView* view = web_contents()->GetView()->GetNativeView(); | 355 NSView* view = web_contents()->GetView()->GetNativeView(); |
| 353 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; | 356 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
| 354 | 357 |
| 355 // By default, the whole frameless window is not draggable. | 358 // By default, the whole frameless window is not draggable. |
| 356 if (!has_frame_) { | 359 if (!has_frame_) { |
| 357 gfx::Rect window_bounds( | 360 gfx::Rect window_bounds( |
| 358 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); | 361 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); |
| 359 system_drag_exclude_areas_.push_back(window_bounds); | 362 system_drag_exclude_areas_.push_back(window_bounds); |
| 360 } | 363 } |
| 361 | 364 |
| 362 InstallView(); | 365 InstallView(); |
| 363 | 366 |
| 364 [[window_controller_ window] setDelegate:window_controller_]; | 367 [[window_controller_ window] setDelegate:window_controller_]; |
| 365 [window_controller_ setAppWindow:this]; | 368 [window_controller_ setAppWindow:this]; |
| 366 | 369 |
| 367 // Update the size constraints of the NSWindow. | 370 // We can now compute the precise window bounds and constraints. |
| 368 SetMinimumSize(params.minimum_size); | 371 gfx::Insets insets = GetFrameInsets(); |
| 369 SetMaximumSize(params.maximum_size); | 372 SetBounds(params.GetInitialWindowBounds(insets)); |
| 373 SetContentSizeConstraints(params.GetContentMinimumSize(insets), | |
| 374 params.GetContentMaximumSize(insets)); | |
| 375 | |
| 376 // Initialize |restored_bounds_|. | |
| 377 restored_bounds_ = [this->window() frame]; | |
| 370 | 378 |
| 371 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( | 379 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( |
| 372 Profile::FromBrowserContext(app_window_->browser_context()), | 380 Profile::FromBrowserContext(app_window_->browser_context()), |
| 373 window, | 381 window, |
| 374 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, | 382 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, |
| 375 app_window)); | 383 app_window)); |
| 376 } | 384 } |
| 377 | 385 |
| 378 NSUInteger NativeAppWindowCocoa::GetWindowStyleMask() const { | 386 NSUInteger NativeAppWindowCocoa::GetWindowStyleMask() const { |
| 379 NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | | 387 NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 if (bounds.width() < min_size.width) | 614 if (bounds.width() < min_size.width) |
| 607 checked_bounds.set_width(min_size.width); | 615 checked_bounds.set_width(min_size.width); |
| 608 if (bounds.height() < min_size.height) | 616 if (bounds.height() < min_size.height) |
| 609 checked_bounds.set_height(min_size.height); | 617 checked_bounds.set_height(min_size.height); |
| 610 NSSize max_size = [window() maxSize]; | 618 NSSize max_size = [window() maxSize]; |
| 611 if (checked_bounds.width() > max_size.width) | 619 if (checked_bounds.width() > max_size.width) |
| 612 checked_bounds.set_width(max_size.width); | 620 checked_bounds.set_width(max_size.width); |
| 613 if (checked_bounds.height() > max_size.height) | 621 if (checked_bounds.height() > max_size.height) |
| 614 checked_bounds.set_height(max_size.height); | 622 checked_bounds.set_height(max_size.height); |
| 615 | 623 |
| 616 NSRect cocoa_bounds = NSMakeRect(checked_bounds.x(), 0, | 624 NSRect cocoa_bounds = GfxToCocoaBounds(checked_bounds, true); |
| 617 checked_bounds.width(), | |
| 618 checked_bounds.height()); | |
| 619 // Flip coordinates based on the primary screen. | |
| 620 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; | |
| 621 cocoa_bounds.origin.y = NSHeight([screen frame]) - checked_bounds.bottom(); | |
| 622 | |
| 623 [window() setFrame:cocoa_bounds display:YES]; | 625 [window() setFrame:cocoa_bounds display:YES]; |
| 624 // setFrame: without animate: does not trigger a windowDidEndLiveResize: so | 626 // setFrame: without animate: does not trigger a windowDidEndLiveResize: so |
| 625 // call it here. | 627 // call it here. |
| 626 WindowDidFinishResize(); | 628 WindowDidFinishResize(); |
| 627 } | 629 } |
| 628 | 630 |
| 629 void NativeAppWindowCocoa::UpdateWindowIcon() { | 631 void NativeAppWindowCocoa::UpdateWindowIcon() { |
| 630 // TODO(junmin): implement. | 632 // TODO(junmin): implement. |
| 631 } | 633 } |
| 632 | 634 |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1030 NSWindow* window = [window_controller_ window]; | 1032 NSWindow* window = [window_controller_ window]; |
| 1031 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); | 1033 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); |
| 1032 return static_cast<ShellNSWindow*>(window); | 1034 return static_cast<ShellNSWindow*>(window); |
| 1033 } | 1035 } |
| 1034 | 1036 |
| 1035 void NativeAppWindowCocoa::UpdateRestoredBounds() { | 1037 void NativeAppWindowCocoa::UpdateRestoredBounds() { |
| 1036 if (IsRestored(*this)) | 1038 if (IsRestored(*this)) |
| 1037 restored_bounds_ = [window() frame]; | 1039 restored_bounds_ = [window() frame]; |
| 1038 } | 1040 } |
| 1039 | 1041 |
| 1040 void NativeAppWindowCocoa::UpdateShelfMenu() { | 1042 void NativeAppWindowCocoa::SetContentSizeConstraints( |
| 1041 // TODO(tmdiep): To be implemented for Mac. | 1043 const gfx::Size& minimum_size, const gfx::Size& maximum_size) { |
| 1042 NOTIMPLEMENTED(); | 1044 // Update the size constraints. |
| 1043 } | 1045 size_constraints_.set_minimum_size(minimum_size); |
| 1044 | 1046 size_constraints_.set_maximum_size(maximum_size); |
| 1045 gfx::Size NativeAppWindowCocoa::GetMinimumSize() const { | |
| 1046 return size_constraints_.GetMinimumSize(); | |
| 1047 } | |
| 1048 | |
| 1049 void NativeAppWindowCocoa::SetMinimumSize(const gfx::Size& size) { | |
| 1050 size_constraints_.set_minimum_size(size); | |
| 1051 | 1047 |
| 1052 gfx::Size min_size = size_constraints_.GetMinimumSize(); | 1048 gfx::Size min_size = size_constraints_.GetMinimumSize(); |
| 1053 [window() setContentMinSize:NSMakeSize(min_size.width(), min_size.height())]; | 1049 [window() setContentMinSize:NSMakeSize(min_size.width(), min_size.height())]; |
| 1054 } | |
| 1055 | |
| 1056 gfx::Size NativeAppWindowCocoa::GetMaximumSize() const { | |
| 1057 return size_constraints_.GetMaximumSize(); | |
| 1058 } | |
| 1059 | |
| 1060 void NativeAppWindowCocoa::SetMaximumSize(const gfx::Size& size) { | |
| 1061 size_constraints_.set_maximum_size(size); | |
| 1062 | 1050 |
| 1063 gfx::Size max_size = size_constraints_.GetMaximumSize(); | 1051 gfx::Size max_size = size_constraints_.GetMaximumSize(); |
| 1064 const int kUnboundedSize = apps::SizeConstraints::kUnboundedSize; | 1052 const int kUnboundedSize = apps::SizeConstraints::kUnboundedSize; |
| 1065 CGFloat max_width = max_size.width() == kUnboundedSize ? | 1053 CGFloat max_width = max_size.width() == kUnboundedSize ? |
| 1066 CGFLOAT_MAX : max_size.width(); | 1054 CGFLOAT_MAX : max_size.width(); |
| 1067 CGFloat max_height = max_size.height() == kUnboundedSize ? | 1055 CGFloat max_height = max_size.height() == kUnboundedSize ? |
| 1068 CGFLOAT_MAX : max_size.height(); | 1056 CGFLOAT_MAX : max_size.height(); |
| 1069 [window() setContentMaxSize:NSMakeSize(max_width, max_height)]; | 1057 [window() setContentMaxSize:NSMakeSize(max_width, max_height)]; |
| 1058 | |
| 1059 // Update the window controls. | |
| 1060 shows_resize_controls_ = | |
| 1061 is_resizable_ && !size_constraints_.HasFixedSize(); | |
| 1062 shows_fullscreen_controls_ = | |
| 1063 is_resizable_ && !size_constraints_.HasMaximumSize(); | |
| 1064 | |
| 1065 if (!is_fullscreen_) { | |
| 1066 [window() setStyleMask:GetWindowStyleMask()]; | |
| 1067 | |
| 1068 // Set the window to participate in Lion Fullscreen mode. Setting this flag | |
| 1069 // has no effect on Snow Leopard or earlier. UI controls for fullscreen are | |
| 1070 // only shown for apps that have unbounded size. | |
| 1071 SetFullScreenCollectionBehavior(window(), shows_fullscreen_controls_); | |
| 1072 } | |
| 1070 } | 1073 } |
| 1074 | |
| 1075 void NativeAppWindowCocoa::UpdateShelfMenu() { | |
| 1076 // TODO(tmdiep): To be implemented for Mac. | |
| 1077 NOTIMPLEMENTED(); | |
| 1078 } | |
| 1079 | |
| 1080 gfx::Size NativeAppWindowCocoa::GetContentMinimumSize() const { | |
| 1081 return size_constraints_.GetMinimumSize(); | |
| 1082 } | |
| 1083 | |
| 1084 void NativeAppWindowCocoa::SetContentMinimumSize(const gfx::Size& size) { | |
| 1085 SetContentSizeConstraints(size, size_constraints_.GetMaximumSize()); | |
|
tmdiep
2014/03/04 03:13:14
Fixed bug - when the constraints were changed afte
| |
| 1086 } | |
| 1087 | |
| 1088 gfx::Size NativeAppWindowCocoa::GetContentMaximumSize() const { | |
| 1089 return size_constraints_.GetMaximumSize(); | |
| 1090 } | |
| 1091 | |
| 1092 void NativeAppWindowCocoa::SetContentMaximumSize(const gfx::Size& size) { | |
| 1093 SetContentSizeConstraints(size_constraints_.GetMinimumSize(), size); | |
| 1094 } | |
| OLD | NEW |