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

Side by Side Diff: chrome/browser/cocoa/tab_view.mm

Issue 2834059: [Mac] Give active tabs an appropriate inner highlight to reduce visual artifa... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/cocoa/tab_view.h" 5 #import "chrome/browser/cocoa/tab_view.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/mac_util.h" 8 #import "base/mac_util.h"
9 #include "base/nsimage_cache_mac.h" 9 #include "base/nsimage_cache_mac.h"
10 #include "base/scoped_cftyperef.h" 10 #include "base/scoped_cftyperef.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 } // namespace 44 } // namespace
45 45
46 @interface TabView(Private) 46 @interface TabView(Private)
47 47
48 - (void)resetLastGlowUpdateTime; 48 - (void)resetLastGlowUpdateTime;
49 - (NSTimeInterval)timeElapsedSinceLastGlowUpdate; 49 - (NSTimeInterval)timeElapsedSinceLastGlowUpdate;
50 - (void)adjustGlowValue; 50 - (void)adjustGlowValue;
51 // TODO(davidben): When we stop supporting 10.5, this can be removed. 51 // TODO(davidben): When we stop supporting 10.5, this can be removed.
52 - (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache; 52 - (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache;
53 - (NSBezierPath*)bezierPathForRect:(NSRect)rect;
53 54
54 @end // TabView(Private) 55 @end // TabView(Private)
55 56
56 @implementation TabView 57 @implementation TabView
57 58
58 @synthesize state = state_; 59 @synthesize state = state_;
59 @synthesize hoverAlpha = hoverAlpha_; 60 @synthesize hoverAlpha = hoverAlpha_;
60 @synthesize alertAlpha = alertAlpha_; 61 @synthesize alertAlpha = alertAlpha_;
61 @synthesize closing = closing_; 62 @synthesize closing = closing_;
62 63
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 NSPoint upLocation = 610 NSPoint upLocation =
610 [[self superview] convertPoint:[theEvent locationInWindow] 611 [[self superview] convertPoint:[theEvent locationInWindow]
611 fromView:nil]; 612 fromView:nil];
612 // If the mouse up occurred in our view or over the close button, then 613 // If the mouse up occurred in our view or over the close button, then
613 // close. 614 // close.
614 if ([self hitTest:upLocation]) 615 if ([self hitTest:upLocation])
615 [controller_ closeTab:self]; 616 [controller_ closeTab:self];
616 } 617 }
617 } 618 }
618 619
619 - (void)drawRect:(NSRect)rect { 620 - (void)drawRect:(NSRect)dirtyRect {
620 // If this tab is phantom, do not draw the tab background itself. The only UI 621 // If this tab is phantom, do not draw the tab background itself. The only UI
621 // element that will represent this tab is the favicon. 622 // element that will represent this tab is the favicon.
622 if ([controller_ phantom]) 623 if ([controller_ phantom])
623 return; 624 return;
624 625
625 NSGraphicsContext* context = [NSGraphicsContext currentContext]; 626 NSGraphicsContext* context = [NSGraphicsContext currentContext];
626 [context saveGraphicsState]; 627 [context saveGraphicsState];
627 rect = [self bounds];
628 BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
629 BOOL selected = [self state];
630
631 // Outset by 0.5 in order to draw on pixels rather than on borders (which
632 // would cause blurry pixels). Subtract 1px of height to compensate, otherwise
633 // clipping will occur.
634 rect = NSInsetRect(rect, -0.5, -0.5);
635 rect.size.height -= 1.0;
636
637 NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect) + 2);
638 NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect) + 2);
639 NSPoint topRight =
640 NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
641 NSMaxY(rect));
642 NSPoint topLeft =
643 NSMakePoint(NSMinX(rect) + kInsetMultiplier * NSHeight(rect),
644 NSMaxY(rect));
645
646 CGFloat baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
647 CGFloat bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
648
649 // Outset many of these values by 1 to cause the fill to bleed outside the
650 // clip area.
651 NSBezierPath* path = [NSBezierPath bezierPath];
652 [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)];
653 [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
654 [path lineToPoint:bottomLeft];
655 [path curveToPoint:topLeft
656 controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
657 bottomLeft.y)
658 controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
659 topLeft.y)];
660 [path lineToPoint:topRight];
661 [path curveToPoint:bottomRight
662 controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
663 topRight.y)
664 controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
665 bottomRight.y)];
666 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
667 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)];
668 628
669 ThemeProvider* themeProvider = [[self window] themeProvider]; 629 ThemeProvider* themeProvider = [[self window] themeProvider];
630 [context setPatternPhase:[[self window] themePatternPhase]];
670 631
671 // Set the pattern phase. 632 NSRect rect = [self bounds];
672 NSPoint phase = [[self window] themePatternPhase]; 633 NSBezierPath* path = [self bezierPathForRect:rect];
673 [context setPatternPhase:phase];
674 634
635 BOOL selected = [self state];
675 // Don't draw the window/tab bar background when selected, since the tab 636 // Don't draw the window/tab bar background when selected, since the tab
676 // background overlay drawn over it (see below) will be fully opaque. 637 // background overlay drawn over it (see below) will be fully opaque.
677 BOOL hasBackgroundImage = NO; 638 BOOL hasBackgroundImage = NO;
678 if (!selected) { 639 if (!selected) {
679 // ThemeProvider::HasCustomImage is true only if the theme provides the 640 // ThemeProvider::HasCustomImage is true only if the theme provides the
680 // image. However, even if the theme doesn't provide a tab background, the 641 // image. However, even if the theme doesn't provide a tab background, the
681 // theme machinery will make one if given a frame image. See 642 // theme machinery will make one if given a frame image. See
682 // BrowserThemePack::GenerateTabBackgroundImages for details. 643 // BrowserThemePack::GenerateTabBackgroundImages for details.
683 hasBackgroundImage = themeProvider && 644 hasBackgroundImage = themeProvider &&
684 (themeProvider->HasCustomImage(IDR_THEME_TAB_BACKGROUND) || 645 (themeProvider->HasCustomImage(IDR_THEME_TAB_BACKGROUND) ||
685 themeProvider->HasCustomImage(IDR_THEME_FRAME)); 646 themeProvider->HasCustomImage(IDR_THEME_FRAME));
686 647
687 NSColor* backgroundImageColor = 648 NSColor* backgroundImageColor = hasBackgroundImage ?
688 hasBackgroundImage ? 649 themeProvider->GetNSImageColorNamed(IDR_THEME_TAB_BACKGROUND, true) :
689 themeProvider->GetNSImageColorNamed(IDR_THEME_TAB_BACKGROUND, true) : 650 nil;
690 nil; 651
691 if (backgroundImageColor) { 652 if (backgroundImageColor) {
692 [backgroundImageColor set]; 653 [backgroundImageColor set];
693 [path fill]; 654 [path fill];
694 } else { 655 } else {
695 // Use the window's background color rather than |[NSColor 656 // Use the window's background color rather than |[NSColor
696 // windowBackgroundColor]|, which gets confused by the fullscreen window. 657 // windowBackgroundColor]|, which gets confused by the fullscreen window.
697 // (The result is the same for normal, non-fullscreen windows.) 658 // (The result is the same for normal, non-fullscreen windows.)
698 [[[self window] backgroundColor] set]; 659 [[[self window] backgroundColor] set];
699 [path fill]; 660 [path fill];
700 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set]; 661 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set];
701 [path fill]; 662 [path fill];
702 } 663 }
703 } 664 }
704 665
705 [context saveGraphicsState]; 666 [context saveGraphicsState];
706 [path addClip]; 667 [path addClip];
707 668
708 // Use the same overlay for the selected state and for hover and alert glows; 669 // Use the same overlay for the selected state and for hover and alert glows;
709 // for the selected state, it's fully opaque. 670 // for the selected state, it's fully opaque.
710 CGFloat hoverAlpha = [self hoverAlpha]; 671 CGFloat hoverAlpha = [self hoverAlpha];
711 CGFloat alertAlpha = [self alertAlpha]; 672 CGFloat alertAlpha = [self alertAlpha];
712 if (selected || hoverAlpha > 0 || alertAlpha > 0) { 673 if (selected || hoverAlpha > 0 || alertAlpha > 0) {
713 // Draw the selected background / glow overlay. 674 // Draw the selected background / glow overlay.
714 [context saveGraphicsState]; 675 [context saveGraphicsState];
715 CGContextRef cgContext = 676 CGContextRef cgContext = static_cast<CGContextRef>([context graphicsPort]);
716 (CGContextRef)([context graphicsPort]);
717 CGContextBeginTransparencyLayer(cgContext, 0); 677 CGContextBeginTransparencyLayer(cgContext, 0);
718 if (!selected) { 678 if (!selected) {
719 // The alert glow overlay is like the selected state but at most at most 679 // The alert glow overlay is like the selected state but at most at most
720 // 80% opaque. The hover glow brings up the overlay's opacity at most 50%. 680 // 80% opaque. The hover glow brings up the overlay's opacity at most 50%.
721 CGFloat backgroundAlpha = 0.8 * alertAlpha; 681 CGFloat backgroundAlpha = 0.8 * alertAlpha;
722 backgroundAlpha += (1 - backgroundAlpha) * 0.5 * hoverAlpha; 682 backgroundAlpha += (1 - backgroundAlpha) * 0.5 * hoverAlpha;
723 CGContextSetAlpha(cgContext, backgroundAlpha); 683 CGContextSetAlpha(cgContext, backgroundAlpha);
724 } 684 }
725 [path addClip]; 685 [path addClip];
726 [context saveGraphicsState]; 686 [context saveGraphicsState];
727 [super drawBackground]; 687 [super drawBackground];
728 [context restoreGraphicsState]; 688 [context restoreGraphicsState];
729 689
730 // Draw a mouse hover gradient for the default themes. 690 // Draw a mouse hover gradient for the default themes.
731 if (!selected && hoverAlpha > 0) { 691 if (!selected && hoverAlpha > 0) {
732 if (themeProvider && !hasBackgroundImage) { 692 if (themeProvider && !hasBackgroundImage) {
733 scoped_nsobject<NSGradient> glow([NSGradient alloc]); 693 scoped_nsobject<NSGradient> glow([NSGradient alloc]);
734 [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0 694 [glow initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0
735 alpha:1.0 * hoverAlpha] 695 alpha:1.0 * hoverAlpha]
736 endingColor:[NSColor colorWithCalibratedWhite:1.0 696 endingColor:[NSColor colorWithCalibratedWhite:1.0
737 alpha:0.0]]; 697 alpha:0.0]];
738 698
739 NSPoint point = hoverPoint_; 699 NSPoint point = hoverPoint_;
740 point.y = NSHeight(rect); 700 point.y = NSHeight(rect);
741 [glow drawFromCenter:point 701 [glow drawFromCenter:point
742 radius:0 702 radius:0.0
743 toCenter:point 703 toCenter:point
744 radius:NSWidth(rect)/3 704 radius:NSWidth(rect) / 3.0
745 options:NSGradientDrawsBeforeStartingLocation]; 705 options:NSGradientDrawsBeforeStartingLocation];
746 706
747 [glow drawInBezierPath:path relativeCenterPosition:hoverPoint_]; 707 [glow drawInBezierPath:path relativeCenterPosition:hoverPoint_];
748 } 708 }
749 } 709 }
750 710
751 CGContextEndTransparencyLayer(cgContext); 711 CGContextEndTransparencyLayer(cgContext);
752 [context restoreGraphicsState]; 712 [context restoreGraphicsState];
753 } 713 }
754 714
755 // Draw the top inner highlight. 715 BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow];
756 NSAffineTransform* highlightTransform = [NSAffineTransform transform]; 716 CGFloat borderAlpha = selected ? (active ? 0.3 : 0.2) : 0.2;
757 [highlightTransform translateXBy:1 yBy:-1]; 717 NSColor* borderColor = [NSColor colorWithDeviceWhite:0.0 alpha:borderAlpha];
758 scoped_nsobject<NSBezierPath> highlightPath([path copy]); 718 NSColor* highlightColor = [NSColor colorWithCalibratedWhite:0.96 alpha:1.0];
759 [highlightPath transformUsingAffineTransform:highlightTransform]; 719
760 [[NSColor colorWithCalibratedWhite:1.0 alpha:0.2 + 0.3 * hoverAlpha] 720 // Draw the top inner highlight within the currently selected tab.
761 setStroke]; 721 if (selected) {
762 [highlightPath stroke]; 722 NSAffineTransform* highlightTransform = [NSAffineTransform transform];
723 [highlightTransform translateXBy:1.0 yBy:-1.0];
724 scoped_nsobject<NSBezierPath> highlightPath([path copy]);
725 [highlightPath transformUsingAffineTransform:highlightTransform];
726 [highlightColor setStroke];
727 [highlightPath setLineWidth:1.0];
728 [highlightPath stroke];
729 highlightTransform = [NSAffineTransform transform];
730 [highlightTransform translateXBy:-2.0 yBy:0.0];
731 [highlightPath transformUsingAffineTransform:highlightTransform];
732 [highlightPath stroke];
733 }
763 734
764 [context restoreGraphicsState]; 735 [context restoreGraphicsState];
765 736
766 // Draw the top stroke. 737 // Draw the top stroke.
767 [context saveGraphicsState]; 738 [context saveGraphicsState];
768 if (selected) { 739 [borderColor set];
769 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.3 : 0.15] set];
770 } else {
771 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.2 : 0.15] set];
772 [[NSBezierPath bezierPathWithRect:NSOffsetRect(rect, 0, 2.5)] addClip];
773 }
774 [path setLineWidth:1.0]; 740 [path setLineWidth:1.0];
775 [path stroke]; 741 [path stroke];
776 [context restoreGraphicsState]; 742 [context restoreGraphicsState];
777 743
778 // Mimic the tab strip's bottom border, which consists of a dark border 744 // Mimic the tab strip's bottom border, which consists of a dark border
779 // and light highlight. 745 // and light highlight.
780 if (!selected) { 746 if (!selected) {
781 [path addClip]; 747 [path addClip];
782 NSRect borderRect = rect; 748 NSRect borderRect = rect;
783 borderRect.origin.y = 1; 749 borderRect.origin.y = 1;
784 borderRect.size.height = 1; 750 borderRect.size.height = 1;
785 [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.2 : 0.15] set]; 751 [borderColor set];
786 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); 752 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
787 753
788 borderRect.origin.y = 0; 754 borderRect.origin.y = 0;
789 [[NSColor colorWithCalibratedWhite:0.96 alpha:1.0] set]; 755 [highlightColor set];
790 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); 756 NSRectFillUsingOperation(borderRect, NSCompositeSourceOver);
791 } 757 }
792 758
793 [context restoreGraphicsState]; 759 [context restoreGraphicsState];
794 } 760 }
795 761
796 - (void)viewDidMoveToWindow { 762 - (void)viewDidMoveToWindow {
797 [super viewDidMoveToWindow]; 763 [super viewDidMoveToWindow];
798 if ([self window]) { 764 if ([self window]) {
799 [controller_ updateTitleColor]; 765 [controller_ updateTitleColor];
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 } else { 989 } else {
1024 NOTREACHED(); 990 NOTREACHED();
1025 } 991 }
1026 } 992 }
1027 if (useCache) { 993 if (useCache) {
1028 workspaceIDCache_[windowID] = workspace; 994 workspaceIDCache_[windowID] = workspace;
1029 } 995 }
1030 return workspace; 996 return workspace;
1031 } 997 }
1032 998
999 // Returns the bezier path used to draw the tab given the bounds to draw it in.
1000 - (NSBezierPath*)bezierPathForRect:(NSRect)rect {
1001 // Outset by 0.5 in order to draw on pixels rather than on borders (which
1002 // would cause blurry pixels). Subtract 1px of height to compensate, otherwise
1003 // clipping will occur.
1004 rect = NSInsetRect(rect, -0.5, -0.5);
1005 rect.size.height -= 1.0;
1006
1007 NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect) + 2);
1008 NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect) + 2);
1009 NSPoint topRight =
1010 NSMakePoint(NSMaxX(rect) - kInsetMultiplier * NSHeight(rect),
1011 NSMaxY(rect));
1012 NSPoint topLeft =
1013 NSMakePoint(NSMinX(rect) + kInsetMultiplier * NSHeight(rect),
1014 NSMaxY(rect));
1015
1016 CGFloat baseControlPointOutset = NSHeight(rect) * kControlPoint1Multiplier;
1017 CGFloat bottomControlPointInset = NSHeight(rect) * kControlPoint2Multiplier;
1018
1019 // Outset many of these values by 1 to cause the fill to bleed outside the
1020 // clip area.
1021 NSBezierPath* path = [NSBezierPath bezierPath];
1022 [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)];
1023 [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)];
1024 [path lineToPoint:bottomLeft];
1025 [path curveToPoint:topLeft
1026 controlPoint1:NSMakePoint(bottomLeft.x + baseControlPointOutset,
1027 bottomLeft.y)
1028 controlPoint2:NSMakePoint(topLeft.x - bottomControlPointInset,
1029 topLeft.y)];
1030 [path lineToPoint:topRight];
1031 [path curveToPoint:bottomRight
1032 controlPoint1:NSMakePoint(topRight.x + bottomControlPointInset,
1033 topRight.y)
1034 controlPoint2:NSMakePoint(bottomRight.x - baseControlPointOutset,
1035 bottomRight.y)];
1036 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)];
1037 [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)];
1038 return path;
1039 }
1040
1033 @end // @implementation TabView(Private) 1041 @end // @implementation TabView(Private)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698