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(gfx::Rect bounds) { |
| 91 typedef apps::AppWindow::BoundsSpecification BoundsSpecification; |
| 92 |
| 93 NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; |
| 94 |
| 95 // If coordinates are unspecified, center window on primary screen. |
| 96 if (bounds.x() == BoundsSpecification::kUnspecifiedPosition) |
| 97 bounds.set_x(floor((NSWidth(main_screen_rect) - bounds.width()) / 2)); |
| 98 if (bounds.y() == BoundsSpecification::kUnspecifiedPosition) |
| 99 bounds.set_y(floor((NSHeight(main_screen_rect) - bounds.height()) / 2)); |
| 100 |
| 101 // Convert to Mac coordinates. |
| 102 NSRect cocoa_bounds = NSRectFromCGRect(bounds.ToCGRect()); |
| 103 cocoa_bounds.origin.y = NSHeight(main_screen_rect) - NSMaxY(cocoa_bounds); |
| 104 return cocoa_bounds; |
| 105 } |
| 106 |
90 } // namespace | 107 } // namespace |
91 | 108 |
92 @implementation NativeAppWindowController | 109 @implementation NativeAppWindowController |
93 | 110 |
94 @synthesize appWindow = appWindow_; | 111 @synthesize appWindow = appWindow_; |
95 | 112 |
96 - (void)windowWillClose:(NSNotification*)notification { | 113 - (void)windowWillClose:(NSNotification*)notification { |
97 if (appWindow_) | 114 if (appWindow_) |
98 appWindow_->WindowWillClose(); | 115 appWindow_->WindowWillClose(); |
99 } | 116 } |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 | 294 |
278 NativeAppWindowCocoa::NativeAppWindowCocoa( | 295 NativeAppWindowCocoa::NativeAppWindowCocoa( |
279 AppWindow* app_window, | 296 AppWindow* app_window, |
280 const AppWindow::CreateParams& params) | 297 const AppWindow::CreateParams& params) |
281 : app_window_(app_window), | 298 : app_window_(app_window), |
282 has_frame_(params.frame == AppWindow::FRAME_CHROME), | 299 has_frame_(params.frame == AppWindow::FRAME_CHROME), |
283 is_hidden_(false), | 300 is_hidden_(false), |
284 is_hidden_with_app_(false), | 301 is_hidden_with_app_(false), |
285 is_maximized_(false), | 302 is_maximized_(false), |
286 is_fullscreen_(false), | 303 is_fullscreen_(false), |
| 304 is_resizable_(params.resizable), |
| 305 shows_resize_controls_(true), |
| 306 shows_fullscreen_controls_(true), |
287 attention_request_id_(0), | 307 attention_request_id_(0), |
288 use_system_drag_(true) { | 308 use_system_drag_(true) { |
289 Observe(web_contents()); | 309 Observe(web_contents()); |
290 | 310 |
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; | 311 base::scoped_nsobject<NSWindow> window; |
311 Class window_class; | 312 Class window_class; |
312 if (has_frame_) { | 313 if (has_frame_) { |
313 bool should_use_native_frame = | 314 bool should_use_native_frame = |
314 CommandLine::ForCurrentProcess()->HasSwitch( | 315 CommandLine::ForCurrentProcess()->HasSwitch( |
315 switches::kAppsUseNativeFrame); | 316 switches::kAppsUseNativeFrame); |
316 window_class = should_use_native_frame ? | 317 window_class = should_use_native_frame ? |
317 [ShellNSWindow class] : [ShellCustomFrameNSWindow class]; | 318 [ShellNSWindow class] : [ShellCustomFrameNSWindow class]; |
318 } else { | 319 } else { |
319 window_class = [ShellFramelessNSWindow class]; | 320 window_class = [ShellFramelessNSWindow class]; |
320 } | 321 } |
321 | 322 |
322 size_constraints_.set_minimum_size(params.minimum_size); | 323 // Estimate the initial bounds of the window. Once the frame insets are known, |
323 size_constraints_.set_maximum_size(params.maximum_size); | 324 // the window bounds and constraints can be set precisely. |
324 shows_resize_controls_ = | 325 NSRect cocoa_bounds = GfxToCocoaBounds( |
325 params.resizable && !size_constraints_.HasFixedSize(); | 326 params.GetInitialWindowBounds(gfx::Insets())); |
326 shows_fullscreen_controls_ = | |
327 params.resizable && !size_constraints_.HasMaximumSize(); | |
328 window.reset([[window_class alloc] | 327 window.reset([[window_class alloc] |
329 initWithContentRect:cocoa_bounds | 328 initWithContentRect:cocoa_bounds |
330 styleMask:GetWindowStyleMask() | 329 styleMask:GetWindowStyleMask() |
331 backing:NSBackingStoreBuffered | 330 backing:NSBackingStoreBuffered |
332 defer:NO]); | 331 defer:NO]); |
333 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; | 332 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; |
334 | 333 |
335 if (base::mac::IsOSSnowLeopard() && | 334 if (base::mac::IsOSSnowLeopard() && |
336 [window respondsToSelector:@selector(setBottomCornerRounded:)]) | 335 [window respondsToSelector:@selector(setBottomCornerRounded:)]) |
337 [window setBottomCornerRounded:NO]; | 336 [window setBottomCornerRounded:NO]; |
338 | 337 |
339 if (params.always_on_top) | 338 if (params.always_on_top) |
340 [window setLevel:AlwaysOnTopWindowLevel()]; | 339 [window setLevel:AlwaysOnTopWindowLevel()]; |
341 InitCollectionBehavior(window); | 340 InitCollectionBehavior(window); |
342 | 341 |
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( | 342 window_controller_.reset( |
350 [[NativeAppWindowController alloc] initWithWindow:window.release()]); | 343 [[NativeAppWindowController alloc] initWithWindow:window.release()]); |
351 | 344 |
352 NSView* view = web_contents()->GetView()->GetNativeView(); | 345 NSView* view = web_contents()->GetView()->GetNativeView(); |
353 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; | 346 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
354 | 347 |
355 // By default, the whole frameless window is not draggable. | 348 // By default, the whole frameless window is not draggable. |
356 if (!has_frame_) { | 349 if (!has_frame_) { |
357 gfx::Rect window_bounds( | 350 gfx::Rect window_bounds( |
358 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); | 351 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); |
359 system_drag_exclude_areas_.push_back(window_bounds); | 352 system_drag_exclude_areas_.push_back(window_bounds); |
360 } | 353 } |
361 | 354 |
362 InstallView(); | 355 InstallView(); |
363 | 356 |
364 [[window_controller_ window] setDelegate:window_controller_]; | 357 [[window_controller_ window] setDelegate:window_controller_]; |
365 [window_controller_ setAppWindow:this]; | 358 [window_controller_ setAppWindow:this]; |
366 | 359 |
367 // Update the size constraints of the NSWindow. | 360 // We can now compute the precise window bounds and constraints. |
368 SetMinimumSize(params.minimum_size); | 361 gfx::Insets insets = GetFrameInsets(); |
369 SetMaximumSize(params.maximum_size); | 362 SetBounds(params.GetInitialWindowBounds(insets)); |
| 363 SetContentSizeConstraints(params.GetContentMinimumSize(insets), |
| 364 params.GetContentMaximumSize(insets)); |
| 365 |
| 366 // Initialize |restored_bounds_|. |
| 367 restored_bounds_ = [this->window() frame]; |
370 | 368 |
371 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( | 369 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( |
372 Profile::FromBrowserContext(app_window_->browser_context()), | 370 Profile::FromBrowserContext(app_window_->browser_context()), |
373 window, | 371 window, |
374 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, | 372 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, |
375 NULL)); | 373 NULL)); |
376 } | 374 } |
377 | 375 |
378 NSUInteger NativeAppWindowCocoa::GetWindowStyleMask() const { | 376 NSUInteger NativeAppWindowCocoa::GetWindowStyleMask() const { |
379 NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | | 377 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) | 604 if (bounds.width() < min_size.width) |
607 checked_bounds.set_width(min_size.width); | 605 checked_bounds.set_width(min_size.width); |
608 if (bounds.height() < min_size.height) | 606 if (bounds.height() < min_size.height) |
609 checked_bounds.set_height(min_size.height); | 607 checked_bounds.set_height(min_size.height); |
610 NSSize max_size = [window() maxSize]; | 608 NSSize max_size = [window() maxSize]; |
611 if (checked_bounds.width() > max_size.width) | 609 if (checked_bounds.width() > max_size.width) |
612 checked_bounds.set_width(max_size.width); | 610 checked_bounds.set_width(max_size.width); |
613 if (checked_bounds.height() > max_size.height) | 611 if (checked_bounds.height() > max_size.height) |
614 checked_bounds.set_height(max_size.height); | 612 checked_bounds.set_height(max_size.height); |
615 | 613 |
616 NSRect cocoa_bounds = NSMakeRect(checked_bounds.x(), 0, | 614 NSRect cocoa_bounds = GfxToCocoaBounds(checked_bounds); |
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]; | 615 [window() setFrame:cocoa_bounds display:YES]; |
624 // setFrame: without animate: does not trigger a windowDidEndLiveResize: so | 616 // setFrame: without animate: does not trigger a windowDidEndLiveResize: so |
625 // call it here. | 617 // call it here. |
626 WindowDidFinishResize(); | 618 WindowDidFinishResize(); |
627 } | 619 } |
628 | 620 |
629 void NativeAppWindowCocoa::UpdateWindowIcon() { | 621 void NativeAppWindowCocoa::UpdateWindowIcon() { |
630 // TODO(junmin): implement. | 622 // TODO(junmin): implement. |
631 } | 623 } |
632 | 624 |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 NSWindow* window = [window_controller_ window]; | 1022 NSWindow* window = [window_controller_ window]; |
1031 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); | 1023 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); |
1032 return static_cast<ShellNSWindow*>(window); | 1024 return static_cast<ShellNSWindow*>(window); |
1033 } | 1025 } |
1034 | 1026 |
1035 void NativeAppWindowCocoa::UpdateRestoredBounds() { | 1027 void NativeAppWindowCocoa::UpdateRestoredBounds() { |
1036 if (IsRestored(*this)) | 1028 if (IsRestored(*this)) |
1037 restored_bounds_ = [window() frame]; | 1029 restored_bounds_ = [window() frame]; |
1038 } | 1030 } |
1039 | 1031 |
1040 void NativeAppWindowCocoa::UpdateShelfMenu() { | 1032 void NativeAppWindowCocoa::SetContentSizeConstraints( |
1041 // TODO(tmdiep): To be implemented for Mac. | 1033 const gfx::Size& minimum_size, const gfx::Size& maximum_size) { |
1042 NOTIMPLEMENTED(); | 1034 // Update the size constraints. |
1043 } | 1035 size_constraints_.set_minimum_size(minimum_size); |
1044 | 1036 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 | 1037 |
1052 gfx::Size min_size = size_constraints_.GetMinimumSize(); | 1038 gfx::Size min_size = size_constraints_.GetMinimumSize(); |
1053 [window() setContentMinSize:NSMakeSize(min_size.width(), min_size.height())]; | 1039 [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 | 1040 |
1063 gfx::Size max_size = size_constraints_.GetMaximumSize(); | 1041 gfx::Size max_size = size_constraints_.GetMaximumSize(); |
1064 const int kUnboundedSize = apps::SizeConstraints::kUnboundedSize; | 1042 const int kUnboundedSize = apps::SizeConstraints::kUnboundedSize; |
1065 CGFloat max_width = max_size.width() == kUnboundedSize ? | 1043 CGFloat max_width = max_size.width() == kUnboundedSize ? |
1066 CGFLOAT_MAX : max_size.width(); | 1044 CGFLOAT_MAX : max_size.width(); |
1067 CGFloat max_height = max_size.height() == kUnboundedSize ? | 1045 CGFloat max_height = max_size.height() == kUnboundedSize ? |
1068 CGFLOAT_MAX : max_size.height(); | 1046 CGFLOAT_MAX : max_size.height(); |
1069 [window() setContentMaxSize:NSMakeSize(max_width, max_height)]; | 1047 [window() setContentMaxSize:NSMakeSize(max_width, max_height)]; |
| 1048 |
| 1049 // Update the window controls. |
| 1050 shows_resize_controls_ = |
| 1051 is_resizable_ && !size_constraints_.HasFixedSize(); |
| 1052 shows_fullscreen_controls_ = |
| 1053 is_resizable_ && !size_constraints_.HasMaximumSize(); |
| 1054 |
| 1055 if (!is_fullscreen_) { |
| 1056 [window() setStyleMask:GetWindowStyleMask()]; |
| 1057 |
| 1058 // Set the window to participate in Lion Fullscreen mode. Setting this flag |
| 1059 // has no effect on Snow Leopard or earlier. UI controls for fullscreen are |
| 1060 // only shown for apps that have unbounded size. |
| 1061 SetFullScreenCollectionBehavior(window(), shows_fullscreen_controls_); |
| 1062 } |
1070 } | 1063 } |
| 1064 |
| 1065 void NativeAppWindowCocoa::UpdateShelfMenu() { |
| 1066 // TODO(tmdiep): To be implemented for Mac. |
| 1067 NOTIMPLEMENTED(); |
| 1068 } |
| 1069 |
| 1070 gfx::Size NativeAppWindowCocoa::GetContentMinimumSize() const { |
| 1071 return size_constraints_.GetMinimumSize(); |
| 1072 } |
| 1073 |
| 1074 void NativeAppWindowCocoa::SetContentMinimumSize(const gfx::Size& size) { |
| 1075 SetContentSizeConstraints(size, size_constraints_.GetMaximumSize()); |
| 1076 } |
| 1077 |
| 1078 gfx::Size NativeAppWindowCocoa::GetContentMaximumSize() const { |
| 1079 return size_constraints_.GetMaximumSize(); |
| 1080 } |
| 1081 |
| 1082 void NativeAppWindowCocoa::SetContentMaximumSize(const gfx::Size& size) { |
| 1083 SetContentSizeConstraints(size_constraints_.GetMinimumSize(), size); |
| 1084 } |
OLD | NEW |