Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1536)

Side by Side Diff: chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm

Issue 916833005: [Mac] Use a custom view to implement colored app windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync and rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698