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