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 "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/mac/foundation_util.h" | 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
| 10 #include "base/mac/sdk_forward_declarations.h" | 10 #include "base/mac/sdk_forward_declarations.h" |
| 11 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
| 12 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" | 12 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" |
| 13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/browser/ui/cocoa/browser_window_utils.h" | 14 #include "chrome/browser/ui/cocoa/browser_window_utils.h" |
| 15 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" | 15 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" |
| 16 #import "chrome/browser/ui/cocoa/custom_frame_view.h" | |
| 17 #include "chrome/browser/ui/cocoa/extensions/extension_keybinding_registry_cocoa .h" | 16 #include "chrome/browser/ui/cocoa/extensions/extension_keybinding_registry_cocoa .h" |
| 18 #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h" | 17 #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h" |
| 19 #include "chrome/common/chrome_switches.h" | 18 #include "chrome/common/chrome_switches.h" |
| 20 #include "content/public/browser/native_web_keyboard_event.h" | 19 #include "content/public/browser/native_web_keyboard_event.h" |
| 21 #include "content/public/browser/render_widget_host_view.h" | 20 #include "content/public/browser/render_widget_host_view.h" |
| 22 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 23 #include "extensions/common/extension.h" | 22 #include "extensions/common/extension.h" |
| 24 #include "skia/ext/skia_utils_mac.h" | 23 #include "skia/ext/skia_utils_mac.h" |
| 25 #include "third_party/skia/include/core/SkRegion.h" | 24 #include "third_party/skia/include/core/SkRegion.h" |
| 26 #include "ui/gfx/skia_util.h" | 25 #include "ui/gfx/skia_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 44 | 43 |
| 45 using extensions::AppWindow; | 44 using extensions::AppWindow; |
| 46 | 45 |
| 47 @interface NSWindow (NSPrivateApis) | 46 @interface NSWindow (NSPrivateApis) |
| 48 - (void)setBottomCornerRounded:(BOOL)rounded; | 47 - (void)setBottomCornerRounded:(BOOL)rounded; |
| 49 - (BOOL)_isTitleHidden; | 48 - (BOOL)_isTitleHidden; |
| 50 @end | 49 @end |
| 51 | 50 |
| 52 namespace { | 51 namespace { |
| 53 | 52 |
| 53 const CGFloat kTitlebarBackgroundViewPaintHeight = 60.0; | |
|
tapted
2015/02/19 03:11:02
nit: comment for this (i.e. why 60 -- does it just
jackhou1
2015/02/19 04:28:58
Done.
| |
| 54 | |
| 54 void SetFullScreenCollectionBehavior(NSWindow* window, bool allow_fullscreen) { | 55 void SetFullScreenCollectionBehavior(NSWindow* window, bool allow_fullscreen) { |
| 55 NSWindowCollectionBehavior behavior = [window collectionBehavior]; | 56 NSWindowCollectionBehavior behavior = [window collectionBehavior]; |
| 56 if (allow_fullscreen) | 57 if (allow_fullscreen) |
| 57 behavior |= NSWindowCollectionBehaviorFullScreenPrimary; | 58 behavior |= NSWindowCollectionBehaviorFullScreenPrimary; |
| 58 else | 59 else |
| 59 behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; | 60 behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; |
| 60 [window setCollectionBehavior:behavior]; | 61 [window setCollectionBehavior:behavior]; |
| 61 } | 62 } |
| 62 | 63 |
| 63 void SetWorkspacesCollectionBehavior(NSWindow* window, bool always_visible) { | 64 void SetWorkspacesCollectionBehavior(NSWindow* window, bool always_visible) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 | 202 |
| 202 - (BOOL)handledByExtensionCommand:(NSEvent*)event | 203 - (BOOL)handledByExtensionCommand:(NSEvent*)event |
| 203 priority:(ui::AcceleratorManager::HandlerPriority)priority { | 204 priority:(ui::AcceleratorManager::HandlerPriority)priority { |
| 204 if (appWindow_) | 205 if (appWindow_) |
| 205 return appWindow_->HandledByExtensionCommand(event, priority); | 206 return appWindow_->HandledByExtensionCommand(event, priority); |
| 206 return NO; | 207 return NO; |
| 207 } | 208 } |
| 208 | 209 |
| 209 @end | 210 @end |
| 210 | 211 |
| 211 // This is really a method on NSGrayFrame, so it should only be called on the | 212 @implementation TitlebarBackgroundView |
| 212 // view passed into -[NSWindow drawCustomFrameRect:forView:]. | |
| 213 @interface NSView (PrivateMethods) | |
| 214 - (CGFloat)roundedCornerRadius; | |
| 215 @end | |
| 216 | 213 |
| 217 // TODO(jamescook): Should these be AppNSWindow to match AppWindow? | 214 - (void)drawRect:(NSRect)rect { |
| 218 // http://crbug.com/344082 | 215 // Only the top corners are rounded. For simplicity, round all 4 corners but |
| 219 @interface ShellNSWindow : ChromeEventProcessingWindow | 216 // draw the bottom corners outside of the visible bounds. |
| 220 @end | |
| 221 @implementation ShellNSWindow | |
| 222 | |
| 223 // Similar to ChromeBrowserWindow, don't draw the title, but allow it to be seen | |
| 224 // in menus, Expose, etc. | |
| 225 - (BOOL)_isTitleHidden { | |
| 226 return YES; | |
| 227 } | |
| 228 | |
| 229 - (void)drawCustomFrameRect:(NSRect)frameRect forView:(NSView*)view { | |
| 230 // Make the background color of the content area white. We can't just call | |
| 231 // -setBackgroundColor as that causes the title bar to be drawn in a solid | |
| 232 // color. | |
| 233 NSRect rect = [self contentRectForFrameRect:frameRect]; | |
| 234 [[NSColor whiteColor] set]; | |
| 235 NSRectFill(rect); | |
| 236 | |
| 237 // Draw the native title bar. We remove the content area since the native | |
| 238 // implementation draws a gray background. | |
| 239 rect.origin.y = NSMaxY(rect); | |
| 240 rect.size.height = CGFLOAT_MAX; | |
| 241 rect = NSIntersectionRect(rect, frameRect); | |
| 242 | |
| 243 [NSBezierPath clipRect:rect]; | |
| 244 [super drawCustomFrameRect:frameRect | |
| 245 forView:view]; | |
| 246 } | |
| 247 | |
| 248 @end | |
| 249 | |
| 250 @interface ShellCustomFrameNSWindow : ShellNSWindow { | |
| 251 @private | |
| 252 base::scoped_nsobject<NSColor> color_; | |
| 253 base::scoped_nsobject<NSColor> inactiveColor_; | |
| 254 } | |
| 255 | |
| 256 - (void)setColor:(NSColor*)color | |
| 257 inactiveColor:(NSColor*)inactiveColor; | |
| 258 | |
| 259 @end | |
| 260 | |
| 261 @implementation ShellCustomFrameNSWindow | |
| 262 | |
| 263 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view { | |
| 264 [[NSBezierPath bezierPathWithRect:rect] addClip]; | |
| 265 [[NSColor clearColor] set]; | |
| 266 NSRectFill(rect); | |
| 267 | |
| 268 // Set up our clip. | |
| 269 CGFloat cornerRadius = 4.0; | 217 CGFloat cornerRadius = 4.0; |
| 270 if ([view respondsToSelector:@selector(roundedCornerRadius)]) | 218 NSRect roundedRect = [self bounds]; |
| 271 cornerRadius = [view roundedCornerRadius]; | 219 roundedRect.origin.y -= cornerRadius; |
| 272 [[NSBezierPath bezierPathWithRoundedRect:[view bounds] | 220 roundedRect.size.height += cornerRadius; |
| 221 [[NSBezierPath bezierPathWithRoundedRect:roundedRect | |
| 273 xRadius:cornerRadius | 222 xRadius:cornerRadius |
| 274 yRadius:cornerRadius] addClip]; | 223 yRadius:cornerRadius] addClip]; |
| 275 if ([self isMainWindow] || [self isKeyWindow]) | 224 if ([[self window] isMainWindow] || [[self window] isKeyWindow]) |
| 276 [color_ set]; | 225 [color_ set]; |
| 277 else | 226 else |
| 278 [inactiveColor_ set]; | 227 [inactiveColor_ set]; |
| 279 NSRectFill(rect); | 228 NSRectFill(rect); |
| 280 } | 229 } |
| 281 | 230 |
| 282 - (void)setColor:(NSColor*)color | 231 - (void)setColor:(NSColor*)color |
| 283 inactiveColor:(NSColor*)inactiveColor { | 232 inactiveColor:(NSColor*)inactiveColor { |
| 284 color_.reset([color retain]); | 233 color_.reset([color retain]); |
| 285 inactiveColor_.reset([inactiveColor retain]); | 234 inactiveColor_.reset([inactiveColor retain]); |
| 286 } | 235 } |
| 287 | 236 |
| 288 @end | 237 @end |
| 289 | 238 |
| 239 // TODO(jamescook): Should these be AppNSWindow to match AppWindow? | |
| 240 // http://crbug.com/344082 | |
| 241 @interface ShellNSWindow : ChromeEventProcessingWindow | |
| 242 @end | |
| 243 | |
| 244 @implementation ShellNSWindow | |
| 245 | |
| 246 // Similar to ChromeBrowserWindow, don't draw the title, but allow it to be seen | |
| 247 // in menus, Expose, etc. | |
| 248 - (BOOL)_isTitleHidden { | |
| 249 return YES; | |
| 250 } | |
| 251 | |
| 252 @end | |
| 253 | |
| 290 @interface ShellFramelessNSWindow : ShellNSWindow | 254 @interface ShellFramelessNSWindow : ShellNSWindow |
| 291 @end | 255 @end |
| 292 | 256 |
| 293 @implementation ShellFramelessNSWindow | 257 @implementation ShellFramelessNSWindow |
| 294 | 258 |
| 295 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view {} | |
| 296 | |
| 297 + (NSRect)frameRectForContentRect:(NSRect)contentRect | 259 + (NSRect)frameRectForContentRect:(NSRect)contentRect |
| 298 styleMask:(NSUInteger)mask { | 260 styleMask:(NSUInteger)mask { |
| 299 return contentRect; | 261 return contentRect; |
| 300 } | 262 } |
| 301 | 263 |
| 302 + (NSRect)contentRectForFrameRect:(NSRect)frameRect | 264 + (NSRect)contentRectForFrameRect:(NSRect)frameRect |
| 303 styleMask:(NSUInteger)mask { | 265 styleMask:(NSUInteger)mask { |
| 304 return frameRect; | 266 return frameRect; |
| 305 } | 267 } |
| 306 | 268 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 is_fullscreen_(false), | 305 is_fullscreen_(false), |
| 344 is_resizable_(params.resizable), | 306 is_resizable_(params.resizable), |
| 345 shows_resize_controls_(true), | 307 shows_resize_controls_(true), |
| 346 shows_fullscreen_controls_(true), | 308 shows_fullscreen_controls_(true), |
| 347 has_frame_color_(params.has_frame_color), | 309 has_frame_color_(params.has_frame_color), |
| 348 active_frame_color_(params.active_frame_color), | 310 active_frame_color_(params.active_frame_color), |
| 349 inactive_frame_color_(params.inactive_frame_color) { | 311 inactive_frame_color_(params.inactive_frame_color) { |
| 350 Observe(WebContents()); | 312 Observe(WebContents()); |
| 351 | 313 |
| 352 base::scoped_nsobject<NSWindow> window; | 314 base::scoped_nsobject<NSWindow> window; |
| 353 Class window_class; | 315 Class window_class = has_frame_ ? |
| 354 if (has_frame_) { | 316 [ShellNSWindow class] : [ShellFramelessNSWindow class]; |
| 355 window_class = has_frame_color_ ? | |
| 356 [ShellCustomFrameNSWindow class] : [ShellNSWindow class]; | |
| 357 } else { | |
| 358 window_class = [ShellFramelessNSWindow class]; | |
| 359 } | |
| 360 | 317 |
| 361 // Estimate the initial bounds of the window. Once the frame insets are known, | 318 // Estimate the initial bounds of the window. Once the frame insets are known, |
| 362 // the window bounds and constraints can be set precisely. | 319 // the window bounds and constraints can be set precisely. |
| 363 NSRect cocoa_bounds = GfxToCocoaBounds( | 320 NSRect cocoa_bounds = GfxToCocoaBounds( |
| 364 params.GetInitialWindowBounds(gfx::Insets())); | 321 params.GetInitialWindowBounds(gfx::Insets())); |
| 365 window.reset([[window_class alloc] | 322 window.reset([[window_class alloc] |
| 366 initWithContentRect:cocoa_bounds | 323 initWithContentRect:cocoa_bounds |
| 367 styleMask:GetWindowStyleMask() | 324 styleMask:GetWindowStyleMask() |
| 368 backing:NSBackingStoreBuffered | 325 backing:NSBackingStoreBuffered |
| 369 defer:NO]); | 326 defer:NO]); |
| 370 | 327 |
| 371 std::string name; | 328 std::string name; |
| 372 const extensions::Extension* extension = app_window_->GetExtension(); | 329 const extensions::Extension* extension = app_window_->GetExtension(); |
| 373 if (extension) | 330 if (extension) |
| 374 name = extension->name(); | 331 name = extension->name(); |
| 375 [window setTitle:base::SysUTF8ToNSString(name)]; | 332 [window setTitle:base::SysUTF8ToNSString(name)]; |
| 376 [[window contentView] setWantsLayer:YES]; | 333 [[window contentView] setWantsLayer:YES]; |
| 377 if (has_frame_ && has_frame_color_) { | 334 if (has_frame_ && has_frame_color_) { |
| 378 [base::mac::ObjCCastStrict<ShellCustomFrameNSWindow>(window) | 335 NSView* window_view = [[window contentView] superview]; |
| 336 titlebar_background_view_.reset([[TitlebarBackgroundView alloc] | |
| 337 initWithFrame:NSMakeRect(0, | |
| 338 NSMaxY([window_view bounds]) - | |
| 339 kTitlebarBackgroundViewPaintHeight, | |
| 340 NSWidth([window_view bounds]), | |
| 341 kTitlebarBackgroundViewPaintHeight)]); | |
| 342 [titlebar_background_view_ | |
| 343 setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; | |
| 344 [window_view addSubview:titlebar_background_view_ | |
| 345 positioned:NSWindowBelow | |
| 346 relativeTo:nil]; | |
| 347 [titlebar_background_view_ | |
| 379 setColor:gfx::SkColorToSRGBNSColor(active_frame_color_) | 348 setColor:gfx::SkColorToSRGBNSColor(active_frame_color_) |
| 380 inactiveColor:gfx::SkColorToSRGBNSColor(inactive_frame_color_)]; | 349 inactiveColor:gfx::SkColorToSRGBNSColor(inactive_frame_color_)]; |
| 381 } | 350 } |
| 382 | 351 |
| 383 if (base::mac::IsOSSnowLeopard() && | 352 if (base::mac::IsOSSnowLeopard() && |
| 384 [window respondsToSelector:@selector(setBottomCornerRounded:)]) | 353 [window respondsToSelector:@selector(setBottomCornerRounded:)]) |
| 385 [window setBottomCornerRounded:NO]; | 354 [window setBottomCornerRounded:NO]; |
| 386 | 355 |
| 387 if (params.always_on_top) | 356 if (params.always_on_top) |
| 388 [window setLevel:AlwaysOnTopWindowLevel()]; | 357 [window setLevel:AlwaysOnTopWindowLevel()]; |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 NOTIMPLEMENTED(); | 782 NOTIMPLEMENTED(); |
| 814 } | 783 } |
| 815 | 784 |
| 816 void NativeAppWindowCocoa::WindowWillClose() { | 785 void NativeAppWindowCocoa::WindowWillClose() { |
| 817 [window_controller_ setAppWindow:NULL]; | 786 [window_controller_ setAppWindow:NULL]; |
| 818 app_window_->OnNativeWindowChanged(); | 787 app_window_->OnNativeWindowChanged(); |
| 819 app_window_->OnNativeClose(); | 788 app_window_->OnNativeClose(); |
| 820 } | 789 } |
| 821 | 790 |
| 822 void NativeAppWindowCocoa::WindowDidBecomeKey() { | 791 void NativeAppWindowCocoa::WindowDidBecomeKey() { |
| 792 [titlebar_background_view_ setNeedsDisplay:YES]; | |
| 823 content::RenderWidgetHostView* rwhv = | 793 content::RenderWidgetHostView* rwhv = |
| 824 WebContents()->GetRenderWidgetHostView(); | 794 WebContents()->GetRenderWidgetHostView(); |
| 825 if (rwhv) | 795 if (rwhv) |
| 826 rwhv->SetActive(true); | 796 rwhv->SetActive(true); |
| 827 app_window_->OnNativeWindowActivated(); | 797 app_window_->OnNativeWindowActivated(); |
| 828 | 798 |
| 829 WebContents()->RestoreFocus(); | 799 WebContents()->RestoreFocus(); |
| 830 } | 800 } |
| 831 | 801 |
| 832 void NativeAppWindowCocoa::WindowDidResignKey() { | 802 void NativeAppWindowCocoa::WindowDidResignKey() { |
| 833 // If our app is still active and we're still the key window, ignore this | 803 // If our app is still active and we're still the key window, ignore this |
| 834 // message, since it just means that a menu extra (on the "system status bar") | 804 // message, since it just means that a menu extra (on the "system status bar") |
| 835 // was activated; we'll get another |-windowDidResignKey| if we ever really | 805 // was activated; we'll get another |-windowDidResignKey| if we ever really |
| 836 // lose key window status. | 806 // lose key window status. |
| 837 if ([NSApp isActive] && ([NSApp keyWindow] == window())) | 807 if ([NSApp isActive] && ([NSApp keyWindow] == window())) |
| 838 return; | 808 return; |
| 839 | 809 |
| 810 [titlebar_background_view_ setNeedsDisplay:YES]; | |
| 811 | |
| 840 WebContents()->StoreFocus(); | 812 WebContents()->StoreFocus(); |
| 841 | 813 |
| 842 content::RenderWidgetHostView* rwhv = | 814 content::RenderWidgetHostView* rwhv = |
| 843 WebContents()->GetRenderWidgetHostView(); | 815 WebContents()->GetRenderWidgetHostView(); |
| 844 if (rwhv) | 816 if (rwhv) |
| 845 rwhv->SetActive(false); | 817 rwhv->SetActive(false); |
| 846 } | 818 } |
| 847 | 819 |
| 848 void NativeAppWindowCocoa::WindowDidFinishResize() { | 820 void NativeAppWindowCocoa::WindowDidFinishResize() { |
| 849 // Update |is_maximized_| if needed: | 821 // Update |is_maximized_| if needed: |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1001 } | 973 } |
| 1002 | 974 |
| 1003 void NativeAppWindowCocoa::UpdateRestoredBounds() { | 975 void NativeAppWindowCocoa::UpdateRestoredBounds() { |
| 1004 if (IsRestored(*this)) | 976 if (IsRestored(*this)) |
| 1005 restored_bounds_ = [window() frame]; | 977 restored_bounds_ = [window() frame]; |
| 1006 } | 978 } |
| 1007 | 979 |
| 1008 void NativeAppWindowCocoa::HideWithoutMarkingHidden() { | 980 void NativeAppWindowCocoa::HideWithoutMarkingHidden() { |
| 1009 [window() orderOut:window_controller_]; | 981 [window() orderOut:window_controller_]; |
| 1010 } | 982 } |
| OLD | NEW |