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

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: Address comments 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
« no previous file with comments | « chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 200
202 - (BOOL)handledByExtensionCommand:(NSEvent*)event 201 - (BOOL)handledByExtensionCommand:(NSEvent*)event
203 priority:(ui::AcceleratorManager::HandlerPriority)priority { 202 priority:(ui::AcceleratorManager::HandlerPriority)priority {
204 if (appWindow_) 203 if (appWindow_)
205 return appWindow_->HandledByExtensionCommand(event, priority); 204 return appWindow_->HandledByExtensionCommand(event, priority);
206 return NO; 205 return NO;
207 } 206 }
208 207
209 @end 208 @end
210 209
211 // This is really a method on NSGrayFrame, so it should only be called on the 210 // A view that paints a solid color. Used to change the title bar background.
212 // view passed into -[NSWindow drawCustomFrameRect:forView:]. 211 @interface TitlebarBackgroundView : NSView {
213 @interface NSView (PrivateMethods)
214 - (CGFloat)roundedCornerRadius;
215 @end
216
217 // TODO(jamescook): Should these be AppNSWindow to match AppWindow?
218 // http://crbug.com/344082
219 @interface ShellNSWindow : ChromeEventProcessingWindow
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 212 @private
252 base::scoped_nsobject<NSColor> color_; 213 base::scoped_nsobject<NSColor> color_;
253 base::scoped_nsobject<NSColor> inactiveColor_; 214 base::scoped_nsobject<NSColor> inactiveColor_;
254 } 215 }
255
256 - (void)setColor:(NSColor*)color 216 - (void)setColor:(NSColor*)color
257 inactiveColor:(NSColor*)inactiveColor; 217 inactiveColor:(NSColor*)inactiveColor;
258
259 @end 218 @end
260 219
261 @implementation ShellCustomFrameNSWindow 220 @implementation TitlebarBackgroundView
262 221
263 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view { 222 - (void)drawRect:(NSRect)rect {
264 [[NSBezierPath bezierPathWithRect:rect] addClip]; 223 // Only the top corners are rounded. For simplicity, round all 4 corners but
265 [[NSColor clearColor] set]; 224 // draw the bottom corners outside of the visible bounds.
266 NSRectFill(rect);
267
268 // Set up our clip.
269 CGFloat cornerRadius = 4.0; 225 CGFloat cornerRadius = 4.0;
270 if ([view respondsToSelector:@selector(roundedCornerRadius)]) 226 NSRect roundedRect = [self bounds];
271 cornerRadius = [view roundedCornerRadius]; 227 roundedRect.origin.y -= cornerRadius;
272 [[NSBezierPath bezierPathWithRoundedRect:[view bounds] 228 roundedRect.size.height += cornerRadius;
229 [[NSBezierPath bezierPathWithRoundedRect:roundedRect
273 xRadius:cornerRadius 230 xRadius:cornerRadius
274 yRadius:cornerRadius] addClip]; 231 yRadius:cornerRadius] addClip];
275 if ([self isMainWindow] || [self isKeyWindow]) 232 if ([[self window] isMainWindow] || [[self window] isKeyWindow])
276 [color_ set]; 233 [color_ set];
277 else 234 else
278 [inactiveColor_ set]; 235 [inactiveColor_ set];
279 NSRectFill(rect); 236 NSRectFill(rect);
280 } 237 }
281 238
282 - (void)setColor:(NSColor*)color 239 - (void)setColor:(NSColor*)color
283 inactiveColor:(NSColor*)inactiveColor { 240 inactiveColor:(NSColor*)inactiveColor {
284 color_.reset([color retain]); 241 color_.reset([color retain]);
285 inactiveColor_.reset([inactiveColor retain]); 242 inactiveColor_.reset([inactiveColor retain]);
286 } 243 }
287 244
288 @end 245 @end
289 246
247 // TODO(jamescook): Should these be AppNSWindow to match AppWindow?
248 // http://crbug.com/344082
249 @interface ShellNSWindow : ChromeEventProcessingWindow
250 @end
251
252 @implementation ShellNSWindow
253
254 // Similar to ChromeBrowserWindow, don't draw the title, but allow it to be seen
255 // in menus, Expose, etc.
256 - (BOOL)_isTitleHidden {
257 return YES;
258 }
259
260 @end
261
290 @interface ShellFramelessNSWindow : ShellNSWindow 262 @interface ShellFramelessNSWindow : ShellNSWindow
291 @end 263 @end
292 264
293 @implementation ShellFramelessNSWindow 265 @implementation ShellFramelessNSWindow
294 266
295 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view {}
296
297 + (NSRect)frameRectForContentRect:(NSRect)contentRect 267 + (NSRect)frameRectForContentRect:(NSRect)contentRect
298 styleMask:(NSUInteger)mask { 268 styleMask:(NSUInteger)mask {
299 return contentRect; 269 return contentRect;
300 } 270 }
301 271
302 + (NSRect)contentRectForFrameRect:(NSRect)frameRect 272 + (NSRect)contentRectForFrameRect:(NSRect)frameRect
303 styleMask:(NSUInteger)mask { 273 styleMask:(NSUInteger)mask {
304 return frameRect; 274 return frameRect;
305 } 275 }
306 276
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 is_fullscreen_(false), 313 is_fullscreen_(false),
344 is_resizable_(params.resizable), 314 is_resizable_(params.resizable),
345 shows_resize_controls_(true), 315 shows_resize_controls_(true),
346 shows_fullscreen_controls_(true), 316 shows_fullscreen_controls_(true),
347 has_frame_color_(params.has_frame_color), 317 has_frame_color_(params.has_frame_color),
348 active_frame_color_(params.active_frame_color), 318 active_frame_color_(params.active_frame_color),
349 inactive_frame_color_(params.inactive_frame_color) { 319 inactive_frame_color_(params.inactive_frame_color) {
350 Observe(WebContents()); 320 Observe(WebContents());
351 321
352 base::scoped_nsobject<NSWindow> window; 322 base::scoped_nsobject<NSWindow> window;
353 Class window_class; 323 Class window_class = has_frame_ ?
354 if (has_frame_) { 324 [ShellNSWindow class] : [ShellFramelessNSWindow class];
355 window_class = has_frame_color_ ?
356 [ShellCustomFrameNSWindow class] : [ShellNSWindow class];
357 } else {
358 window_class = [ShellFramelessNSWindow class];
359 }
360 325
361 // Estimate the initial bounds of the window. Once the frame insets are known, 326 // Estimate the initial bounds of the window. Once the frame insets are known,
362 // the window bounds and constraints can be set precisely. 327 // the window bounds and constraints can be set precisely.
363 NSRect cocoa_bounds = GfxToCocoaBounds( 328 NSRect cocoa_bounds = GfxToCocoaBounds(
364 params.GetInitialWindowBounds(gfx::Insets())); 329 params.GetInitialWindowBounds(gfx::Insets()));
365 window.reset([[window_class alloc] 330 window.reset([[window_class alloc]
366 initWithContentRect:cocoa_bounds 331 initWithContentRect:cocoa_bounds
367 styleMask:GetWindowStyleMask() 332 styleMask:GetWindowStyleMask()
368 backing:NSBackingStoreBuffered 333 backing:NSBackingStoreBuffered
369 defer:NO]); 334 defer:NO]);
370 335
371 std::string name; 336 std::string name;
372 const extensions::Extension* extension = app_window_->GetExtension(); 337 const extensions::Extension* extension = app_window_->GetExtension();
373 if (extension) 338 if (extension)
374 name = extension->name(); 339 name = extension->name();
375 [window setTitle:base::SysUTF8ToNSString(name)]; 340 [window setTitle:base::SysUTF8ToNSString(name)];
376 [[window contentView] setWantsLayer:YES]; 341 [[window contentView] setWantsLayer:YES];
377 if (has_frame_ && has_frame_color_) { 342 if (has_frame_ && has_frame_color_) {
378 [base::mac::ObjCCastStrict<ShellCustomFrameNSWindow>(window) 343 // AppKit only officially supports adding subviews to the window's
344 // contentView and not its superview (an NSNextStepFrame). The 10.10 SDK
345 // allows adding an NSTitlebarAccessoryViewController to a window, but the
346 // view can only be placed above the window control buttons, so we'd have to
347 // replicate those.
348 NSView* window_view = [[window contentView] superview];
349 CGFloat height = NSHeight([window_view bounds]) -
350 NSHeight([[window contentView] bounds]);
351 titlebar_background_view_.reset([[TitlebarBackgroundView alloc]
352 initWithFrame:NSMakeRect(0, NSMaxY([window_view bounds]) - height,
353 NSWidth([window_view bounds]), height)]);
354 [titlebar_background_view_
355 setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
356 [window_view addSubview:titlebar_background_view_
357 positioned:NSWindowBelow
358 relativeTo:nil];
359 [titlebar_background_view_
379 setColor:gfx::SkColorToSRGBNSColor(active_frame_color_) 360 setColor:gfx::SkColorToSRGBNSColor(active_frame_color_)
380 inactiveColor:gfx::SkColorToSRGBNSColor(inactive_frame_color_)]; 361 inactiveColor:gfx::SkColorToSRGBNSColor(inactive_frame_color_)];
381 } 362 }
382 363
383 if (base::mac::IsOSSnowLeopard() && 364 if (base::mac::IsOSSnowLeopard() &&
384 [window respondsToSelector:@selector(setBottomCornerRounded:)]) 365 [window respondsToSelector:@selector(setBottomCornerRounded:)])
385 [window setBottomCornerRounded:NO]; 366 [window setBottomCornerRounded:NO];
386 367
387 if (params.always_on_top) 368 if (params.always_on_top)
388 [window setLevel:AlwaysOnTopWindowLevel()]; 369 [window setLevel:AlwaysOnTopWindowLevel()];
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 NOTIMPLEMENTED(); 794 NOTIMPLEMENTED();
814 } 795 }
815 796
816 void NativeAppWindowCocoa::WindowWillClose() { 797 void NativeAppWindowCocoa::WindowWillClose() {
817 [window_controller_ setAppWindow:NULL]; 798 [window_controller_ setAppWindow:NULL];
818 app_window_->OnNativeWindowChanged(); 799 app_window_->OnNativeWindowChanged();
819 app_window_->OnNativeClose(); 800 app_window_->OnNativeClose();
820 } 801 }
821 802
822 void NativeAppWindowCocoa::WindowDidBecomeKey() { 803 void NativeAppWindowCocoa::WindowDidBecomeKey() {
804 [titlebar_background_view_ setNeedsDisplay:YES];
823 content::RenderWidgetHostView* rwhv = 805 content::RenderWidgetHostView* rwhv =
824 WebContents()->GetRenderWidgetHostView(); 806 WebContents()->GetRenderWidgetHostView();
825 if (rwhv) 807 if (rwhv)
826 rwhv->SetActive(true); 808 rwhv->SetActive(true);
827 app_window_->OnNativeWindowActivated(); 809 app_window_->OnNativeWindowActivated();
828 810
829 WebContents()->RestoreFocus(); 811 WebContents()->RestoreFocus();
830 } 812 }
831 813
832 void NativeAppWindowCocoa::WindowDidResignKey() { 814 void NativeAppWindowCocoa::WindowDidResignKey() {
833 // If our app is still active and we're still the key window, ignore this 815 // 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") 816 // 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 817 // was activated; we'll get another |-windowDidResignKey| if we ever really
836 // lose key window status. 818 // lose key window status.
837 if ([NSApp isActive] && ([NSApp keyWindow] == window())) 819 if ([NSApp isActive] && ([NSApp keyWindow] == window()))
838 return; 820 return;
839 821
822 [titlebar_background_view_ setNeedsDisplay:YES];
823
840 WebContents()->StoreFocus(); 824 WebContents()->StoreFocus();
841 825
842 content::RenderWidgetHostView* rwhv = 826 content::RenderWidgetHostView* rwhv =
843 WebContents()->GetRenderWidgetHostView(); 827 WebContents()->GetRenderWidgetHostView();
844 if (rwhv) 828 if (rwhv)
845 rwhv->SetActive(false); 829 rwhv->SetActive(false);
846 } 830 }
847 831
848 void NativeAppWindowCocoa::WindowDidFinishResize() { 832 void NativeAppWindowCocoa::WindowDidFinishResize() {
849 // Update |is_maximized_| if needed: 833 // Update |is_maximized_| if needed:
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 } 985 }
1002 986
1003 void NativeAppWindowCocoa::UpdateRestoredBounds() { 987 void NativeAppWindowCocoa::UpdateRestoredBounds() {
1004 if (IsRestored(*this)) 988 if (IsRestored(*this))
1005 restored_bounds_ = [window() frame]; 989 restored_bounds_ = [window() frame];
1006 } 990 }
1007 991
1008 void NativeAppWindowCocoa::HideWithoutMarkingHidden() { 992 void NativeAppWindowCocoa::HideWithoutMarkingHidden() {
1009 [window() orderOut:window_controller_]; 993 [window() orderOut:window_controller_];
1010 } 994 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698