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 |