OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #import "chrome/browser/ui/cocoa/framed_browser_window.h" | 5 #import "chrome/browser/ui/cocoa/framed_browser_window.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | 8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" |
9 #include "chrome/browser/profiles/profile_info_util.h" | 9 #include "chrome/browser/profiles/profile_info_util.h" |
10 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 10 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 11 #import "chrome/browser/ui/cocoa/browser_window_utils.h" |
11 #import "chrome/browser/ui/cocoa/custom_frame_view.h" | 12 #import "chrome/browser/ui/cocoa/custom_frame_view.h" |
12 #import "chrome/browser/ui/cocoa/nsview_additions.h" | 13 #import "chrome/browser/ui/cocoa/nsview_additions.h" |
13 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" | 14 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" |
14 #import "chrome/browser/ui/cocoa/themed_window.h" | 15 #import "chrome/browser/ui/cocoa/themed_window.h" |
15 #include "chrome/browser/themes/theme_properties.h" | 16 #include "chrome/browser/themes/theme_properties.h" |
16 #include "chrome/browser/themes/theme_service.h" | 17 #include "chrome/browser/themes/theme_service.h" |
17 #include "grit/theme_resources.h" | 18 #include "grit/theme_resources.h" |
| 19 #include "ui/base/cocoa/nsgraphics_context_additions.h" |
18 | 20 |
19 // Replicate specific 10.7 SDK declarations for building with prior SDKs. | 21 // Replicate specific 10.7 SDK declarations for building with prior SDKs. |
20 #if !defined(MAC_OS_X_VERSION_10_7) || \ | 22 #if !defined(MAC_OS_X_VERSION_10_7) || \ |
21 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | 23 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
22 | 24 |
23 @interface NSWindow (LionSDKDeclarations) | 25 @interface NSWindow (LionSDKDeclarations) |
24 - (void)toggleFullScreen:(id)sender; | 26 - (void)toggleFullScreen:(id)sender; |
25 @end | 27 @end |
26 | 28 |
27 enum { | 29 enum { |
28 NSWindowDocumentVersionsButton = 6, | 30 NSWindowDocumentVersionsButton = 6, |
29 NSWindowFullScreenButton | 31 NSWindowFullScreenButton |
30 }; | 32 }; |
31 | 33 |
32 #endif // MAC_OS_X_VERSION_10_7 | 34 #endif // MAC_OS_X_VERSION_10_7 |
33 | 35 |
34 | 36 |
35 // Implementer's note: Moving the window controls is tricky. When altering the | 37 // Implementer's note: Moving the window controls is tricky. When altering the |
36 // code, ensure that: | 38 // code, ensure that: |
37 // - accessibility hit testing works | 39 // - accessibility hit testing works |
38 // - the accessibility hierarchy is correct | 40 // - the accessibility hierarchy is correct |
39 // - close/min in the background don't bring the window forward | 41 // - close/min in the background don't bring the window forward |
40 // - rollover effects work correctly | 42 // - rollover effects work correctly |
41 | 43 |
42 namespace { | 44 namespace { |
43 | 45 |
44 const CGFloat kBrowserFrameViewPaintHeight = 60.0; | 46 const CGFloat kBrowserFrameViewPaintHeight = 60.0; |
45 const NSPoint kBrowserFrameViewPatternPhaseOffset = { -5, 3 }; | |
46 | 47 |
47 // Size of the gradient. Empirically determined so that the gradient looks | 48 // Size of the gradient. Empirically determined so that the gradient looks |
48 // like what the heuristic does when there are just a few tabs. | 49 // like what the heuristic does when there are just a few tabs. |
49 const CGFloat kWindowGradientHeight = 24.0; | 50 const CGFloat kWindowGradientHeight = 24.0; |
50 | 51 |
51 } | 52 } |
52 | 53 |
53 @interface FramedBrowserWindow (Private) | 54 @interface FramedBrowserWindow (Private) |
54 | 55 |
55 - (void)adjustCloseButton:(NSNotification*)notification; | 56 - (void)adjustCloseButton:(NSNotification*)notification; |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 [[NSBezierPath bezierPathWithRoundedRect:windowRect | 355 [[NSBezierPath bezierPathWithRoundedRect:windowRect |
355 xRadius:cornerRadius | 356 xRadius:cornerRadius |
356 yRadius:cornerRadius] addClip]; | 357 yRadius:cornerRadius] addClip]; |
357 [[NSBezierPath bezierPathWithRect:rect] addClip]; | 358 [[NSBezierPath bezierPathWithRect:rect] addClip]; |
358 | 359 |
359 // Do the theming. | 360 // Do the theming. |
360 BOOL themed = [FramedBrowserWindow | 361 BOOL themed = [FramedBrowserWindow |
361 drawWindowThemeInDirtyRect:rect | 362 drawWindowThemeInDirtyRect:rect |
362 forView:view | 363 forView:view |
363 bounds:windowRect | 364 bounds:windowRect |
364 offset:NSZeroPoint | |
365 forceBlackBackground:NO]; | 365 forceBlackBackground:NO]; |
366 | 366 |
367 // If the window needs a title and we painted over the title as drawn by the | 367 // If the window needs a title and we painted over the title as drawn by the |
368 // default window paint, paint it ourselves. | 368 // default window paint, paint it ourselves. |
369 if (themed && [view respondsToSelector:@selector(_titlebarTitleRect)] && | 369 if (themed && [view respondsToSelector:@selector(_titlebarTitleRect)] && |
370 [view respondsToSelector:@selector(_drawTitleStringIn:withColor:)] && | 370 [view respondsToSelector:@selector(_drawTitleStringIn:withColor:)] && |
371 ![self _isTitleHidden]) { | 371 ![self _isTitleHidden]) { |
372 [view _drawTitleStringIn:[view _titlebarTitleRect] | 372 [view _drawTitleStringIn:[view _titlebarTitleRect] |
373 withColor:[self titleColor]]; | 373 withColor:[self titleColor]]; |
374 } | 374 } |
(...skipping 12 matching lines...) Expand all Loading... |
387 xRadius:cornerRadius | 387 xRadius:cornerRadius |
388 yRadius:cornerRadius]; | 388 yRadius:cornerRadius]; |
389 [path setLineWidth:lineWidth]; | 389 [path setLineWidth:lineWidth]; |
390 [path stroke]; | 390 [path stroke]; |
391 } | 391 } |
392 } | 392 } |
393 | 393 |
394 + (BOOL)drawWindowThemeInDirtyRect:(NSRect)dirtyRect | 394 + (BOOL)drawWindowThemeInDirtyRect:(NSRect)dirtyRect |
395 forView:(NSView*)view | 395 forView:(NSView*)view |
396 bounds:(NSRect)bounds | 396 bounds:(NSRect)bounds |
397 offset:(NSPoint)offset | |
398 forceBlackBackground:(BOOL)forceBlackBackground { | 397 forceBlackBackground:(BOOL)forceBlackBackground { |
399 ui::ThemeProvider* themeProvider = [[view window] themeProvider]; | 398 ui::ThemeProvider* themeProvider = [[view window] themeProvider]; |
400 if (!themeProvider) | 399 if (!themeProvider) |
401 return NO; | 400 return NO; |
402 | 401 |
403 ThemedWindowStyle windowStyle = [[view window] themedWindowStyle]; | 402 ThemedWindowStyle windowStyle = [[view window] themedWindowStyle]; |
404 | 403 |
405 // Devtools windows don't get themed. | 404 // Devtools windows don't get themed. |
406 if (windowStyle & THEMED_DEVTOOLS) | 405 if (windowStyle & THEMED_DEVTOOLS) |
407 return NO; | 406 return NO; |
(...skipping 20 matching lines...) Expand all Loading... |
428 | 427 |
429 // If no theme image, use a gradient if incognito. | 428 // If no theme image, use a gradient if incognito. |
430 NSGradient* gradient = nil; | 429 NSGradient* gradient = nil; |
431 if (!themeImageColor && incognito) | 430 if (!themeImageColor && incognito) |
432 gradient = themeProvider->GetNSGradient( | 431 gradient = themeProvider->GetNSGradient( |
433 active ? ThemeProperties::GRADIENT_FRAME_INCOGNITO : | 432 active ? ThemeProperties::GRADIENT_FRAME_INCOGNITO : |
434 ThemeProperties::GRADIENT_FRAME_INCOGNITO_INACTIVE); | 433 ThemeProperties::GRADIENT_FRAME_INCOGNITO_INACTIVE); |
435 | 434 |
436 BOOL themed = NO; | 435 BOOL themed = NO; |
437 if (themeImageColor) { | 436 if (themeImageColor) { |
438 // The titlebar/tabstrip header on the mac is slightly smaller than on | |
439 // Windows. To keep the window background lined up with the tab and toolbar | |
440 // patterns, we have to shift the pattern slightly, rather than simply | |
441 // drawing it from the top left corner. The offset below was empirically | |
442 // determined in order to line these patterns up. | |
443 // | |
444 // This will make the themes look slightly different than in Windows/Linux | |
445 // because of the differing heights between window top and tab top, but this | |
446 // has been approved by UI. | |
447 NSView* frameView = [[[view window] contentView] superview]; | |
448 NSPoint topLeft = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); | |
449 NSPoint topLeftInFrameCoordinates = | |
450 [view convertPoint:topLeft toView:frameView]; | |
451 | |
452 NSPoint phase = kBrowserFrameViewPatternPhaseOffset; | |
453 phase.x += (offset.x + topLeftInFrameCoordinates.x); | |
454 phase.y += (offset.y + topLeftInFrameCoordinates.y); | |
455 | |
456 // Align the phase to physical pixels so resizing the window under HiDPI | |
457 // doesn't cause wiggling of the theme. | |
458 phase = [frameView convertPointToBase:phase]; | |
459 phase.x = floor(phase.x); | |
460 phase.y = floor(phase.y); | |
461 phase = [frameView convertPointFromBase:phase]; | |
462 | |
463 // Default to replacing any existing pixels with the theme image, but if | 437 // Default to replacing any existing pixels with the theme image, but if |
464 // asked paint black first and blend the theme with black. | 438 // asked paint black first and blend the theme with black. |
465 NSCompositingOperation operation = NSCompositeCopy; | 439 NSCompositingOperation operation = NSCompositeCopy; |
466 if (forceBlackBackground) { | 440 if (forceBlackBackground) { |
467 [[NSColor blackColor] set]; | 441 [[NSColor blackColor] set]; |
468 NSRectFill(dirtyRect); | 442 NSRectFill(dirtyRect); |
469 operation = NSCompositeSourceOver; | 443 operation = NSCompositeSourceOver; |
470 } | 444 } |
471 | 445 |
472 [[NSGraphicsContext currentContext] setPatternPhase:phase]; | 446 NSPoint position = [[view window] themeImagePositionForAlignment: |
| 447 THEME_IMAGE_ALIGN_WITH_FRAME]; |
| 448 |
| 449 // Align the phase to physical pixels so resizing the window under HiDPI |
| 450 // doesn't cause wiggling of the theme. |
| 451 NSView* frameView = [[[view window] contentView] superview]; |
| 452 position = [frameView convertPointToBase:position]; |
| 453 position.x = floor(position.x); |
| 454 position.y = floor(position.y); |
| 455 position = [frameView convertPointFromBase:position]; |
| 456 [[NSGraphicsContext currentContext] cr_setPatternPhase:position |
| 457 forView:view]; |
| 458 |
473 [themeImageColor set]; | 459 [themeImageColor set]; |
474 NSRectFillUsingOperation(dirtyRect, operation); | 460 NSRectFillUsingOperation(dirtyRect, operation); |
475 themed = YES; | 461 themed = YES; |
476 } else if (gradient) { | 462 } else if (gradient) { |
477 NSPoint startPoint = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); | 463 NSPoint startPoint = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); |
478 NSPoint endPoint = startPoint; | 464 NSPoint endPoint = startPoint; |
479 endPoint.y -= kBrowserFrameViewPaintHeight; | 465 endPoint.y -= kBrowserFrameViewPaintHeight; |
480 [gradient drawFromPoint:startPoint toPoint:endPoint options:0]; | 466 [gradient drawFromPoint:startPoint toPoint:endPoint options:0]; |
481 themed = YES; | 467 themed = YES; |
482 } | 468 } |
483 | 469 |
484 // Check to see if we have an overlay image. | 470 // Check to see if we have an overlay image. |
485 NSImage* overlayImage = nil; | 471 NSImage* overlayImage = nil; |
486 if (themeProvider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !incognito && | 472 if (themeProvider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !incognito && |
487 !popup) { | 473 !popup) { |
488 overlayImage = themeProvider-> | 474 overlayImage = themeProvider-> |
489 GetNSImageNamed(active ? IDR_THEME_FRAME_OVERLAY : | 475 GetNSImageNamed(active ? IDR_THEME_FRAME_OVERLAY : |
490 IDR_THEME_FRAME_OVERLAY_INACTIVE); | 476 IDR_THEME_FRAME_OVERLAY_INACTIVE); |
491 } | 477 } |
492 | 478 |
493 if (overlayImage) { | 479 if (overlayImage) { |
494 // Anchor to top-left and don't scale. | 480 // Anchor to top-left and don't scale. |
| 481 NSView* frameView = [[[view window] contentView] superview]; |
| 482 NSPoint position = [[view window] themeImagePositionForAlignment: |
| 483 THEME_IMAGE_ALIGN_WITH_FRAME]; |
| 484 position = [view convertPoint:position fromView:frameView]; |
495 NSSize overlaySize = [overlayImage size]; | 485 NSSize overlaySize = [overlayImage size]; |
496 NSRect imageFrame = NSMakeRect(0, 0, overlaySize.width, overlaySize.height); | 486 NSRect imageFrame = NSMakeRect(0, 0, overlaySize.width, overlaySize.height); |
497 [overlayImage drawAtPoint:NSMakePoint(offset.x, | 487 [overlayImage drawAtPoint:NSMakePoint(position.x, |
498 NSHeight(bounds) + offset.y - | 488 position.y - overlaySize.height) |
499 overlaySize.height) | |
500 fromRect:imageFrame | 489 fromRect:imageFrame |
501 operation:NSCompositeSourceOver | 490 operation:NSCompositeSourceOver |
502 fraction:1.0]; | 491 fraction:1.0]; |
503 } | 492 } |
504 | 493 |
505 return themed; | 494 return themed; |
506 } | 495 } |
507 | 496 |
508 - (NSColor*)titleColor { | 497 - (NSColor*)titleColor { |
509 ui::ThemeProvider* themeProvider = [self themeProvider]; | 498 ui::ThemeProvider* themeProvider = [self themeProvider]; |
510 if (!themeProvider) | 499 if (!themeProvider) |
511 return [NSColor windowFrameTextColor]; | 500 return [NSColor windowFrameTextColor]; |
512 | 501 |
513 ThemedWindowStyle windowStyle = [self themedWindowStyle]; | 502 ThemedWindowStyle windowStyle = [self themedWindowStyle]; |
514 BOOL incognito = windowStyle & THEMED_INCOGNITO; | 503 BOOL incognito = windowStyle & THEMED_INCOGNITO; |
515 | 504 |
516 if (incognito) | 505 if (incognito) |
517 return [NSColor whiteColor]; | 506 return [NSColor whiteColor]; |
518 else | 507 else |
519 return [NSColor windowFrameTextColor]; | 508 return [NSColor windowFrameTextColor]; |
520 } | 509 } |
521 | 510 |
522 @end | 511 @end |
OLD | NEW |