diff options
Diffstat (limited to 'chrome')
26 files changed, 838 insertions, 345 deletions
diff --git a/chrome/browser/cocoa/background_gradient_view.h b/chrome/browser/cocoa/background_gradient_view.h index 9c04b4d..547a08d 100644 --- a/chrome/browser/cocoa/background_gradient_view.h +++ b/chrome/browser/cocoa/background_gradient_view.h @@ -10,7 +10,6 @@ // A custom view that draws a 'standard' background gradient. // Base class for other Chromium views. - @interface BackgroundGradientView : NSView { @private BOOL showsDivider_; @@ -19,6 +18,10 @@ // The color used for the bottom stroke. Public so subclasses can use. - (NSColor *)strokeColor; +// Draws the background for this view. Make sure that your patternphase +// is set up correctly in your graphics context before calling. +- (void)drawBackground; + // Controls whether the bar draws a dividing line at the bottom. @property(assign) BOOL showsDivider; @end diff --git a/chrome/browser/cocoa/background_gradient_view.mm b/chrome/browser/cocoa/background_gradient_view.mm index de35705..96e3773 100644 --- a/chrome/browser/cocoa/background_gradient_view.mm +++ b/chrome/browser/cocoa/background_gradient_view.mm @@ -27,44 +27,31 @@ [self setNeedsDisplay:YES]; } -// The offset of this pattern to make it line up with the top of the window. -- (NSPoint)patternPhase { - NSPoint phase = NSZeroPoint; - phase.y += NSHeight([[self window] frame]) - kToolbarTopOffset; - return phase; -} - -- (void)drawRect:(NSRect)rect { +- (void)drawBackground { BOOL isKey = [[self window] isKeyWindow]; - - GTMTheme *theme = [self gtm_theme]; - - NSImage *backgroundImage = [theme backgroundImageForStyle:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; + GTMTheme* theme = [self gtm_theme]; + NSImage* backgroundImage = + [theme backgroundImageForStyle:GTMThemeStyleToolBar + state:GTMThemeStateActiveWindow]; if (backgroundImage) { - NSPoint phase = [self patternPhase]; - [[NSGraphicsContext currentContext] setPatternPhase:phase]; - - NSColor *color = [NSColor colorWithPatternImage:backgroundImage]; + NSColor* color = [NSColor colorWithPatternImage:backgroundImage]; [color set]; NSRectFill([self bounds]); } else { CGFloat winHeight = NSHeight([[self window] frame]); - NSGradient *gradient = [theme gradientForStyle:GTMThemeStyleToolBar + NSGradient* gradient = [theme gradientForStyle:GTMThemeStyleToolBar state:isKey]; NSPoint startPoint = [self convertPoint:NSMakePoint(0, winHeight - kToolbarTopOffset) fromView:nil]; NSPoint endPoint = - [self convertPoint:NSMakePoint(0, winHeight - - kToolbarTopOffset - - kToolbarMaxHeight) - fromView:nil]; + NSMakePoint(0, winHeight - kToolbarTopOffset - kToolbarMaxHeight); + endPoint = [self convertPoint:endPoint fromView:nil]; [gradient drawFromPoint:startPoint toPoint:endPoint - options:NSGradientDrawsBeforeStartingLocation | - NSGradientDrawsAfterEndingLocation]; + options:(NSGradientDrawsBeforeStartingLocation | + NSGradientDrawsAfterEndingLocation)]; } if (showsDivider_) { diff --git a/chrome/browser/cocoa/background_gradient_view_unittest.mm b/chrome/browser/cocoa/background_gradient_view_unittest.mm index 7b5e0c0..20ff6be 100644 --- a/chrome/browser/cocoa/background_gradient_view_unittest.mm +++ b/chrome/browser/cocoa/background_gradient_view_unittest.mm @@ -10,18 +10,29 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +// Since BackgroundGradientView doesn't do any drawing by default, we +// create a subclass to call its draw method for us. +@interface BackgroundGradientSubClassTest : BackgroundGradientView +@end + +@implementation BackgroundGradientSubClassTest +- (void)drawRect:(NSRect)rect { + [self drawBackground]; +} +@end + namespace { class BackgroundGradientViewTest : public PlatformTest { public: BackgroundGradientViewTest() { NSRect frame = NSMakeRect(0, 0, 100, 30); - view_.reset([[BackgroundGradientView alloc] initWithFrame:frame]); + view_.reset([[BackgroundGradientSubClassTest alloc] initWithFrame:frame]); [cocoa_helper_.contentView() addSubview:view_.get()]; } CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... - scoped_nsobject<BackgroundGradientView> view_; + scoped_nsobject<BackgroundGradientSubClassTest> view_; }; // Test adding/removing from the view hierarchy, mostly to ensure nothing diff --git a/chrome/browser/cocoa/browser_frame_view.h b/chrome/browser/cocoa/browser_frame_view.h new file mode 100644 index 0000000..277a96b --- /dev/null +++ b/chrome/browser/cocoa/browser_frame_view.h @@ -0,0 +1,52 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +// BrowserFrameView is a class whose methods we swizzle into NSGrayFrame +// (an AppKit framework class) so that we can support custom frame drawing, and +// have the ability to move our window widgets (close, zoom, miniaturize) where +// we want them. +// This class is never to be instantiated on its own. +// We explored a variety of ways to support custom frame drawing and custom +// window widgets. +// Our requirements were: +// a) that we could fall back on standard system drawing at any time for the +// "default theme" +// b) We needed to be able to draw both a background pattern, and an overlay +// graphic, and we need to be able to set the pattern phase of our background +// window. +// c) We had to be able to support "transparent" themes, so that you could see +// through to the underlying windows in places without the system theme +// getting in the way. +// d) We had to support having the custom window controls moved down by a couple +// of pixels and rollovers, accessibility, etc. all had to work. +// +// Since we want "A" we couldn't just do a transparent borderless window. At +// least I couldn't find the right combination of HITheme calls to make it draw +// nicely, and I don't trust that the HITheme calls are going to exist in future +// system versions. +// "C" precluded us from inserting a view between the system frame and the +// the content frame in Z order. To get the transparency we actually need to +// replace the drawing of the system frame. +// "D" required us to override _mouseInGroup to get our custom widget rollovers +// drawing correctly. The widgets call _mouseInGroup on their superview to +// decide whether they should draw in highlight mode or not. +// "B" precluded us from just setting a background color on the window. +// +// Originally we tried overriding the private API +frameViewForStyleMask: to +// add our own subclass of NSGrayView to our window. Turns out that if you +// subclass NSGrayView it does not draw correctly when you call NSGrayView's +// drawRect. It appears that NSGrayView's drawRect: method (and that of its +// superclasses) do lots of "isMemberOfClass/isKindOfClass" calls, and if your +// class is NOT an instance of NSGrayView (as opposed to a subclass of +// NSGrayView) then the system drawing will not work correctly. +// +// Given all of the above, we found swizzling drawRect, and adding an +// implementation of _mouseInGroup and updateTrackingAreas, in _load to be the +// easiest and safest method of achieving our goals. We do the best we can to +// check that everything is safe, and attempt to fallback gracefully if it is +// not. +@interface BrowserFrameView : NSView +@end diff --git a/chrome/browser/cocoa/browser_frame_view.mm b/chrome/browser/cocoa/browser_frame_view.mm new file mode 100644 index 0000000..8ccc01e --- /dev/null +++ b/chrome/browser/cocoa/browser_frame_view.mm @@ -0,0 +1,176 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/browser_frame_view.h" + +#import <objc/runtime.h> +#import <Carbon/Carbon.h> + +#include "base/logging.h" +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/chrome_browser_window.h" +#import "third_party/GTM/AppKit/GTMTheme.h" + +// To line up our background pattern with the patterns in the tabs we need +// to move our background patterns in the window frame up by two pixels. +// This will make the themes look slightly different than in Windows/Linux +// because of the differing heights between window top and tab top, but this +// has been approved by UI. +static const NSInteger kBrowserFrameViewPatternPhaseOffset = 2; + +@interface NSView (Swizzles) +- (void)drawRectOriginal:(NSRect)rect; +- (BOOL)_mouseInGroup:(NSButton*)widget; +- (void)updateTrackingAreas; +@end + +@implementation BrowserFrameView + ++ (void)load { + // This is where we swizzle drawRect, and add in two methods that we + // need. If any of these fail it shouldn't affect the functionality of the + // others. If they all fail, we will lose window frame theming and + // roll overs for our close widgets, but things should still function + // correctly. + scoped_nsobject<NSAutoreleasePool> pool([[NSAutoreleasePool alloc] init]); + Class grayFrameClass = NSClassFromString(@"NSGrayFrame"); + DCHECK(grayFrameClass); + if (!grayFrameClass) return; + + // Exchange draw rect + Method m0 = class_getInstanceMethod([self class], @selector(drawRect:)); + DCHECK(m0); + if (m0) { + BOOL didAdd = class_addMethod(grayFrameClass, + @selector(drawRectOriginal:), + method_getImplementation(m0), + method_getTypeEncoding(m0)); + DCHECK(didAdd); + if (didAdd) { + Method m1 = class_getInstanceMethod(grayFrameClass, @selector(drawRect:)); + Method m2 = class_getInstanceMethod(grayFrameClass, + @selector(drawRectOriginal:)); + DCHECK(m1 && m2); + if (m1 && m2) { + method_exchangeImplementations(m1, m2); + } + } + } + + // Add _mouseInGroup + m0 = class_getInstanceMethod([self class], @selector(_mouseInGroup:)); + DCHECK(m0); + if (m0) { + BOOL didAdd = class_addMethod(grayFrameClass, + @selector(_mouseInGroup:), + method_getImplementation(m0), + method_getTypeEncoding(m0)); + DCHECK(didAdd); + } + // Add updateTrackingArea + m0 = class_getInstanceMethod([self class], @selector(updateTrackingAreas)); + DCHECK(m0); + if (m0) { + BOOL didAdd = class_addMethod(grayFrameClass, + @selector(updateTrackingAreas), + method_getImplementation(m0), + method_getTypeEncoding(m0)); + DCHECK(didAdd); + } +} + +- (id)initWithFrame:(NSRect)frame { + // This class is not for instantiating. + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (id)initWithCoder:(NSCoder*)coder { + // This class is not for instantiating. + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +// Here is our custom drawing for our frame. +- (void)drawRect:(NSRect)rect { + // If this isn't the window class we expect, then pass it on to the + // original implementation. + if (![[self window] isKindOfClass:[ChromeBrowserWindow class]]) { + [self drawRectOriginal:rect]; + return; + } + + // Clear out everything + [[NSColor clearColor] set]; + NSRectFillUsingOperation(rect, NSCompositeSourceOver); + + // Set up our clip + NSWindow* window = [self window]; + NSRect windowRect = [window frame]; + windowRect.origin = NSMakePoint(0, 0); + [[NSBezierPath bezierPathWithRoundedRect:windowRect + xRadius:4 + yRadius:4] addClip]; + [[NSBezierPath bezierPathWithRect:rect] addClip]; + + // Draw our background color if we have one, otherwise fall back on + // system drawing. + GTMTheme* theme = [self gtm_theme]; + GTMThemeState state = [window isMainWindow] ? GTMThemeStateActiveWindow + : GTMThemeStateInactiveWindow; + NSColor* color = [theme backgroundPatternColorForStyle:GTMThemeStyleWindow + state:state]; + if (color) { + // If we have a theme pattern, draw it here. + NSPoint phase = NSMakePoint(0, (NSHeight(windowRect) + + kBrowserFrameViewPatternPhaseOffset)); + [[NSGraphicsContext currentContext] setPatternPhase:phase]; + [color set]; + NSRectFill(rect); + } else { + [self drawRectOriginal:rect]; + } + + // Check to see if we have an overlay image. + NSImage* overlayImage = [theme valueForAttribute:@"overlay" + style:GTMThemeStyleWindow + state:state]; + if (overlayImage) { + NSSize overlaySize = [overlayImage size]; + NSRect windowFrame = NSMakeRect(0, + NSHeight(windowRect) - overlaySize.height, + NSWidth(windowRect), + overlaySize.height); + NSRect imageFrame = NSMakeRect(0, 0, overlaySize.width, overlaySize.height); + [overlayImage drawInRect:windowFrame + fromRect:imageFrame + operation:NSCompositeSourceOver + fraction:1.0]; + } +} + +// Check to see if the mouse is currently in one of our window widgets. +- (BOOL)_mouseInGroup:(NSButton*)widget { + BOOL mouseInGroup = NO; + if ([[self window] isKindOfClass:[ChromeBrowserWindow class]]) { + ChromeBrowserWindow* window = + static_cast<ChromeBrowserWindow*>([self window]); + mouseInGroup = [window mouseInGroup:widget]; + } else { + mouseInGroup = [super _mouseInGroup:widget]; + } + return mouseInGroup; +} + +// Let our window handle updating the window widget tracking area. +- (void)updateTrackingAreas { + [super updateTrackingAreas]; + if ([[self window] isKindOfClass:[ChromeBrowserWindow class]]) { + ChromeBrowserWindow* window = + static_cast<ChromeBrowserWindow*>([self window]); + [window updateTrackingAreas]; + } +} + +@end diff --git a/chrome/browser/cocoa/browser_frame_view_unittest.mm b/chrome/browser/cocoa/browser_frame_view_unittest.mm new file mode 100644 index 0000000..90d51c7 --- /dev/null +++ b/chrome/browser/cocoa/browser_frame_view_unittest.mm @@ -0,0 +1,48 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> +#include <objc/runtime.h> + +#include "base/scoped_nsobject.h" +#import "chrome/browser/cocoa/browser_frame_view.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +class BrowserFrameViewTest : public PlatformTest { + public: + BrowserFrameViewTest() { + NSRect frame = NSMakeRect(0, 0, 50, 50); + // We create NSGrayFrame instead of BrowserFrameView because + // we are swizzling into NSGrayFrame. + Class browserFrameClass = NSClassFromString(@"NSGrayFrame"); + view_.reset([[browserFrameClass alloc] initWithFrame:frame]); + } + + scoped_nsobject<NSView> view_; +}; + +// Test to make sure our class modifications were successful. +TEST_F(BrowserFrameViewTest, SuccessfulClassModifications) { + unsigned int count; + BOOL foundMouseInGroup = NO; + BOOL foundDrawRectOriginal = NO; + BOOL foundUpdateTrackingAreas = NO; + + Method* methods = class_copyMethodList([view_ class], &count); + for (unsigned int i = 0; i < count; ++i) { + SEL selector = method_getName(methods[i]); + if (selector == @selector(_mouseInGroup:)) { + foundMouseInGroup = YES; + } else if (selector == @selector(drawRectOriginal:)) { + foundDrawRectOriginal = YES; + } else if (selector == @selector(updateTrackingAreas)) { + foundUpdateTrackingAreas = YES; + } + } + EXPECT_TRUE(foundMouseInGroup); + EXPECT_TRUE(foundDrawRectOriginal); + EXPECT_TRUE(foundUpdateTrackingAreas); + free(methods); +} diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index b9562fa..7c37bbb 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -51,8 +51,8 @@ const int kWindowGradientHeight = 24; } @interface GTMTheme (BrowserThemeProviderInitialization) -+ (GTMTheme *)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider - isOffTheRecord:(BOOL)offTheRecord; ++ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider + isOffTheRecord:(BOOL)offTheRecord; @end @interface NSWindow (NSPrivateApis) @@ -72,12 +72,6 @@ const int kWindowGradientHeight = 24; @interface BrowserWindowController(Private) -// Leopard's gradient heuristic gets confused by our tabs and makes the title -// gradient jump when creating a tab that is less than a tab width from the -// right side of the screen. This function disables Leopard's gradient -// heuristic. -- (void)fixWindowGradient; - // Saves the window's position in the local state preferences. - (void)saveWindowPositionIfNeeded; @@ -93,9 +87,6 @@ willPositionSheet:(NSWindow*)sheet // Assign a theme to the window. - (void)setTheme; -// Theme up the window. -- (void)applyTheme; - // Repositions the windows subviews. - (void)layoutSubviews; @@ -226,8 +217,6 @@ willPositionSheet:(NSWindow*)sheet [extensionShelfController_ wasInsertedIntoWindow]; } - [self fixWindowGradient]; - // Force a relayout of all the various bars. [self layoutSubviews]; @@ -338,11 +327,16 @@ willPositionSheet:(NSWindow*)sheet - (void)windowDidBecomeMain:(NSNotification*)notification { BrowserList::SetLastActive(browser_.get()); [self saveWindowPositionIfNeeded]; - [self applyTheme]; + + // TODO(dmaclach): Instead of redrawing the whole window, views that care + // about the active window state should be registering for notifications. + [[self window] setViewsNeedDisplay:YES]; } - (void)windowDidResignMain:(NSNotification*)notification { - [self applyTheme]; + // TODO(dmaclach): Instead of redrawing the whole window, views that care + // about the active window state should be registering for notifications. + [[self window] setViewsNeedDisplay:YES]; } // Called when we are activated (when we gain focus). @@ -534,7 +528,7 @@ willPositionSheet:(NSWindow*)sheet EncodingMenuController encoding_controller; if (encoding_controller.DoesCommandBelongToEncodingMenu(tag)) { DCHECK(browser_.get()); - Profile *profile = browser_->profile(); + Profile* profile = browser_->profile(); DCHECK(profile); TabContents* current_tab = browser_->GetSelectedTabContents(); if (!current_tab) { @@ -753,7 +747,7 @@ willPositionSheet:(NSWindow*)sheet return [tabStripController_ selectedTabView]; } -- (TabStripController *)tabStripController { +- (TabStripController*)tabStripController { return tabStripController_; } @@ -1022,13 +1016,35 @@ willPositionSheet:(NSWindow*)sheet - (void)userChangedTheme { [self setTheme]; - [self applyTheme]; + NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter postNotificationName:kGTMThemeDidChangeNotification + object:theme_]; + // TODO(dmaclach): Instead of redrawing the whole window, views that care + // about the active window state should be registering for notifications. + [[self window] setViewsNeedDisplay:YES]; } -- (GTMTheme *)gtm_themeForWindow:(NSWindow*)window { +- (GTMTheme*)gtm_themeForWindow:(NSWindow*)window { return theme_ ? theme_ : [GTMTheme defaultTheme]; } +- (NSPoint)gtm_themePatternPhaseForWindow:(NSWindow*)window { + // Our patterns want to be drawn from the upper left hand corner of the view. + // Cocoa wants to do it from the lower left of the window. + // Rephase our pattern to fit this view. Some other views (Tabs, Toolbar etc.) + // will phase their patterns relative to this so all the views look right. + NSView* tabStripView = [self tabStripView]; + NSRect tabStripViewWindowBounds = [tabStripView bounds]; + NSView* windowChromeView = [[window contentView] superview]; + tabStripViewWindowBounds = + [tabStripView convertRect:tabStripViewWindowBounds + toView:windowChromeView]; + NSPoint phase = NSMakePoint(NSMinX(tabStripViewWindowBounds), + NSMinY(tabStripViewWindowBounds) + + [TabStripController defaultTabHeight]); + return phase; +} + - (NSPoint)topLeftForBubble { NSRect rect = [toolbarController_ starButtonInWindowCoordinates]; NSPoint p = NSMakePoint(NSMinX(rect), NSMinY(rect)); // bottom left @@ -1134,17 +1150,6 @@ willPositionSheet:(NSWindow*)sheet [[[[self window] contentView] superview] addSubview:incognitoView.get()]; } -- (void)fixWindowGradient { - NSWindow* win = [self window]; - if ([win respondsToSelector:@selector( - setAutorecalculatesContentBorderThickness:forEdge:)] && - [win respondsToSelector:@selector( - setContentBorderThickness:forEdge:)]) { - [win setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; - [win setContentBorderThickness:kWindowGradientHeight forEdge:NSMaxYEdge]; - } -} - - (void)saveWindowPositionIfNeeded { if (browser_ != BrowserList::GetLastActive()) return; @@ -1215,22 +1220,17 @@ willPositionSheet:(NSWindow*)sheet - (void)setTheme { ThemeProvider* theme_provider = browser_->profile()->GetThemeProvider(); - if (theme_provider) { - GTMTheme *theme = [GTMTheme themeWithBrowserThemeProvider: - (BrowserThemeProvider *)theme_provider - isOffTheRecord:browser_->profile()->IsOffTheRecord()]; + BrowserThemeProvider* browser_theme_provider = + static_cast<BrowserThemeProvider*>(theme_provider); + if (browser_theme_provider) { + bool offtheRecord = browser_->profile()->IsOffTheRecord(); + GTMTheme* theme = + [GTMTheme themeWithBrowserThemeProvider:browser_theme_provider + isOffTheRecord:offtheRecord]; theme_.reset([theme retain]); } } -- (void)applyTheme { - NSColor* color = - [theme_ backgroundPatternColorForStyle:GTMThemeStyleWindow - state:[[self window] isMainWindow]]; - [[self window] setBackgroundColor:color]; - [tabStripController_ applyTheme]; -} - // Private method to layout browser window subviews. Positions the toolbar and // the infobar above the tab content area. Positions the download shelf below // the tab content area. If the toolbar is not a child of the contentview, this @@ -1349,8 +1349,8 @@ willPositionSheet:(NSWindow*)sheet @end @implementation GTMTheme (BrowserThemeProviderInitialization) -+ (GTMTheme *)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider - isOffTheRecord:(BOOL)isOffTheRecord { ++ (GTMTheme*)themeWithBrowserThemeProvider:(BrowserThemeProvider*)provider + isOffTheRecord:(BOOL)isOffTheRecord { // First check if it's in the cache. // TODO(pinkerton): This might be a good candidate for a singleton. typedef std::pair<std::string, BOOL> ThemeKey; @@ -1375,7 +1375,7 @@ willPositionSheet:(NSWindow*)sheet [theme setBackgroundColor:incognitoColor]; [theme setValue:[NSColor blackColor] forAttribute:@"textColor" - style:GTMThemeStyleToolBar + style:GTMThemeStyleTabBarSelected state:GTMThemeStateActiveWindow]; [theme setValue:[NSColor blackColor] forAttribute:@"textColor" @@ -1401,7 +1401,7 @@ willPositionSheet:(NSWindow*)sheet provider->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT); [theme setValue:tabTextColor forAttribute:@"textColor" - style:GTMThemeStyleToolBar + style:GTMThemeStyleTabBarSelected state:GTMThemeStateActiveWindow]; NSColor* tabInactiveTextColor = @@ -1480,7 +1480,24 @@ willPositionSheet:(NSWindow*)sheet style:GTMThemeStyleToolBar state:GTMThemeStateActiveWindow]; + NSImage* frameOverlayImage = + provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY); + if (frameOverlayImage) { + [theme setValue:frameOverlayImage + forAttribute:@"overlay" + style:GTMThemeStyleWindow + state:GTMThemeStateActiveWindow]; + } + + NSImage* frameOverlayInactiveImage = + provider->GetNSImageNamed(IDR_THEME_FRAME_OVERLAY_INACTIVE); + if (frameOverlayInactiveImage) { + [theme setValue:frameOverlayInactiveImage + forAttribute:@"overlay" + style:GTMThemeStyleWindow + state:GTMThemeStateInactiveWindow]; + } + return theme; } @end - diff --git a/chrome/browser/cocoa/bubble_view.mm b/chrome/browser/cocoa/bubble_view.mm index 012e930..32159001 100644 --- a/chrome/browser/cocoa/bubble_view.mm +++ b/chrome/browser/cocoa/bubble_view.mm @@ -102,7 +102,7 @@ const float kWindowEdge = 0.7f; [border stroke]; // Text - NSColor* textColor = [theme textColorForStyle:GTMThemeStyleToolBar + NSColor* textColor = [theme textColorForStyle:GTMThemeStyleTabBarSelected state:GTMThemeStateActiveWindow]; NSFont* textFont = [self font]; scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]); diff --git a/chrome/browser/cocoa/chrome_browser_window.h b/chrome/browser/cocoa/chrome_browser_window.h index 9130616..c25b489 100644 --- a/chrome/browser/cocoa/chrome_browser_window.h +++ b/chrome/browser/cocoa/chrome_browser_window.h @@ -7,12 +7,31 @@ #import <Cocoa/Cocoa.h> +#include "base/scoped_nsobject.h" + +// Offset from the top of the window frame to the top of the window controls +// (zoom, close, miniaturize). +const NSInteger kChromeWindowButtonsOffsetFromTop = 7; + +// Offset from the left of the window frame to the top of the window controls +// (zoom, close, miniaturize). +const NSInteger kChromeWindowButtonsOffsetFromLeft = 8; + +// Offset between the window controls (zoom, close, miniaturize). +const NSInteger kChromeWindowButtonsInterButtonSpacing = 7; + // Cocoa class representing a Chrome browser window. // We need to override NSWindow with our own class since we need access to all // unhandled keyboard events and subclassing NSWindow is the only method to do -// this. +// this. We also handle our own window controls and custom window frame drawing. @interface ChromeBrowserWindow : NSWindow { + @private BOOL shouldHideTitle_; + NSButton* closeButton_; + NSButton* miniaturizeButton_; + NSButton* zoomButton_; + BOOL entered_; + scoped_nsobject<NSTrackingArea> widgetTrackingArea_; } // See global_keyboard_shortcuts_mac.h for details on the next two functions. @@ -31,6 +50,12 @@ // Tells the window to suppress title drawing. - (void)setShouldHideTitle:(BOOL)flag; +// Return true if the mouse is currently in our tracking area for our window +// widgets. +- (BOOL)mouseInGroup:(NSButton*)widget; + +// Update the tracking areas for our window widgets as appropriate. +- (void)updateTrackingAreas; @end @interface ChromeBrowserWindow (UndocumentedAPI) diff --git a/chrome/browser/cocoa/chrome_browser_window.mm b/chrome/browser/cocoa/chrome_browser_window.mm index a6df8d5..6786cda 100644 --- a/chrome/browser/cocoa/chrome_browser_window.mm +++ b/chrome/browser/cocoa/chrome_browser_window.mm @@ -6,12 +6,261 @@ #include "base/logging.h" #import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/browser_frame_view.h" +#import "chrome/browser/cocoa/tab_strip_controller.h" #import "chrome/browser/renderer_host/render_widget_host_view_mac.h" #include "chrome/browser/global_keyboard_shortcuts_mac.h" +// Our browser window does some interesting things to get the behaviors that +// we want. We replace the standard window controls (zoom, close, miniaturize) +// with our own versions, so that we can position them slightly differently than +// the default window has them. To do this, we hide the ones that Apple provides +// us with, and create our own. This requires us to handle tracking for the +// buttons (so that they highlight and activate correctly) as well as implement +// the private method _mouseInGroup in our frame view class which is required +// to get the rollover highlight drawing to draw correctly. +@interface ChromeBrowserWindow(ChromeBrowserWindowPrivateMethods) +// Return the view that does the "frame" drawing. +- (NSView*)frameView; +@end + typedef int (*KeyToCommandMapper)(bool, bool, bool, int); @implementation ChromeBrowserWindow +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(NSUInteger)aStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag { + if ((self = [super initWithContentRect:contentRect + styleMask:aStyle + backing:bufferingType + defer:flag])) { + NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver:self + selector:@selector(themeDidChangeNotification:) + name:kGTMThemeDidChangeNotification + object:nil]; + + // Hook ourselves up to get notified if the user changes the system + // theme on us. + NSDistributedNotificationCenter* distCenter = + [NSDistributedNotificationCenter defaultCenter]; + [distCenter addObserver:self + selector:@selector(systemThemeDidChangeNotification:) + name:@"AppleAquaColorVariantChanged" + object:nil]; + [self setOpaque:NO]; + // Set up our buttons how we like them. + NSView* frameView = [self frameView]; + NSRect frameViewBounds = [frameView bounds]; + + // Find all the "original" buttons, and hide them. We can't use the original + // buttons because the OS likes to move them around when we resize windows + // and will put them back in what it considers to be their "preferred" + // locations. + NSButton* oldButton = [self standardWindowButton:NSWindowCloseButton]; + [oldButton setHidden:YES]; + oldButton = [self standardWindowButton:NSWindowMiniaturizeButton]; + [oldButton setHidden:YES]; + oldButton = [self standardWindowButton:NSWindowZoomButton]; + [oldButton setHidden:YES]; + + // Create and position our new buttons. + closeButton_ = [NSWindow standardWindowButton:NSWindowCloseButton + forStyleMask:aStyle]; + NSRect closeButtonFrame = [closeButton_ frame]; + closeButtonFrame.origin = + NSMakePoint(kChromeWindowButtonsOffsetFromLeft, + (NSHeight(frameViewBounds) - + NSHeight(closeButtonFrame) - + kChromeWindowButtonsOffsetFromTop)); + [closeButton_ setFrame:closeButtonFrame]; + [closeButton_ setTarget:self]; + [closeButton_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; + [frameView addSubview:closeButton_]; + + miniaturizeButton_ = + [NSWindow standardWindowButton:NSWindowMiniaturizeButton + forStyleMask:aStyle]; + NSRect miniaturizeButtonFrame = [miniaturizeButton_ frame]; + miniaturizeButtonFrame.origin = + NSMakePoint((NSMaxX(closeButtonFrame) + + kChromeWindowButtonsInterButtonSpacing), + NSMinY(closeButtonFrame)); + [miniaturizeButton_ setFrame:miniaturizeButtonFrame]; + [miniaturizeButton_ setTarget:self]; + [miniaturizeButton_ setAutoresizingMask:(NSViewMaxXMargin | + NSViewMinYMargin)]; + [frameView addSubview:miniaturizeButton_]; + + zoomButton_ = [NSWindow standardWindowButton:NSWindowZoomButton + forStyleMask:aStyle]; + NSRect zoomButtonFrame = [zoomButton_ frame]; + zoomButtonFrame.origin = + NSMakePoint((NSMaxX(miniaturizeButtonFrame) + + kChromeWindowButtonsInterButtonSpacing), + NSMinY(miniaturizeButtonFrame)); + [zoomButton_ setFrame:zoomButtonFrame]; + [zoomButton_ setTarget:self]; + [zoomButton_ setAutoresizingMask:(NSViewMaxXMargin | + NSViewMinYMargin)]; + + [frameView addSubview:zoomButton_]; + [self updateTrackingAreas]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (NSView*)frameView { + return [[self contentView] superview]; +} + +// The tab strip view covers our window buttons. So we add hit testing here +// to find them properly and return them to the accessibility system. +- (id)accessibilityHitTest:(NSPoint)point { + NSPoint windowPoint = [self convertScreenToBase:point]; + NSControl* controls[] = { closeButton_, zoomButton_, miniaturizeButton_ }; + id value = nil; + for (size_t i = 0; i < sizeof(controls) / sizeof(controls[0]); ++i) { + if (NSPointInRect(windowPoint, [controls[i] frame])) { + value = [controls[i] accessibilityHitTest:point]; + break; + } + } + if (!value) { + value = [super accessibilityHitTest:point]; + } + return value; +} + +// Map our custom buttons into the accessibility hierarchy correctly. +- (id)accessibilityAttributeValue:(NSString*)attribute { + id value = nil; + struct { + NSString* attribute_; + id value_; + } attributeMap[] = { + { NSAccessibilityCloseButtonAttribute, [closeButton_ cell]}, + { NSAccessibilityZoomButtonAttribute, [zoomButton_ cell]}, + { NSAccessibilityMinimizeButtonAttribute, [miniaturizeButton_ cell]}, + }; + + for (size_t i = 0; i < sizeof(attributeMap) / sizeof(attributeMap[0]); ++i) { + if ([attributeMap[i].attribute_ isEqualToString:attribute]) { + value = attributeMap[i].value_; + break; + } + } + if (!value) { + value = [super accessibilityAttributeValue:attribute]; + } + return value; +} + +- (void)updateTrackingAreas { + NSView* frameView = [self frameView]; + if (widgetTrackingArea_) { + [frameView removeTrackingArea:widgetTrackingArea_]; + } + NSRect trackingRect = [closeButton_ frame]; + trackingRect.size.width = NSMaxX([zoomButton_ frame]) - NSMinX(trackingRect); + widgetTrackingArea_.reset( + [[NSTrackingArea alloc] initWithRect:trackingRect + options:(NSTrackingMouseEnteredAndExited | + NSTrackingActiveAlways) + owner:self + userInfo:nil]); + [frameView addTrackingArea:widgetTrackingArea_]; +} + +- (void)windowMainStatusChanged { + [closeButton_ setNeedsDisplay]; + [zoomButton_ setNeedsDisplay]; + [miniaturizeButton_ setNeedsDisplay]; + NSView* frameView = [self frameView]; + NSView* contentView = [self contentView]; + NSRect updateRect = [frameView frame]; + NSRect contentRect = [contentView frame]; + CGFloat tabStripHeight = [TabStripController defaultTabHeight]; + updateRect.size.height -= NSHeight(contentRect) - tabStripHeight; + updateRect.origin.y = NSMaxY(contentRect) - tabStripHeight; + [[self frameView] setNeedsDisplayInRect:updateRect]; +} + +- (void)becomeMainWindow { + [self windowMainStatusChanged]; + [super becomeMainWindow]; +} + +- (void)resignMainWindow { + [self windowMainStatusChanged]; + [super resignMainWindow]; +} + +- (void)themeDidChangeNotification:(NSNotification*)aNotification { + GTMTheme* theme = [aNotification object]; + if ([theme isEqual:[self gtm_theme]]) { + [[self frameView] setNeedsDisplay:YES]; + } +} + +- (void)systemThemeDidChangeNotification:(NSNotification*)aNotification { + [closeButton_ setNeedsDisplay]; + [zoomButton_ setNeedsDisplay]; + [miniaturizeButton_ setNeedsDisplay]; +} + +- (void)sendEvent:(NSEvent*)event { + // For cocoa windows, clicking on the close and the miniaturize (but not the + // zoom buttons) while a window is in the background does NOT bring that + // window to the front. We don't get that behavior for free, so we handle + // it here. Zoom buttons do bring the window to the front. Note that + // Finder windows (in Leopard) behave differently in this regard in that + // zoom buttons don't bring the window to the foreground. + BOOL eventHandled = NO; + if (![self isMainWindow]) { + if ([event type] == NSLeftMouseDown) { + NSView* frameView = [self frameView]; + NSPoint mouse = [frameView convertPointFromBase:[event locationInWindow]]; + if (NSPointInRect(mouse, [closeButton_ frame])) { + [closeButton_ mouseDown:event]; + eventHandled = YES; + } else if (NSPointInRect(mouse, [miniaturizeButton_ frame])) { + [miniaturizeButton_ mouseDown:event]; + eventHandled = YES; + } + } + } + if (!eventHandled) { + [super sendEvent:event]; + } +} + +// Update our buttons so that they highlight correctly. +- (void)mouseEntered:(NSEvent*)event { + entered_ = YES; + [closeButton_ setNeedsDisplay]; + [zoomButton_ setNeedsDisplay]; + [miniaturizeButton_ setNeedsDisplay]; +} + +// Update our buttons so that they highlight correctly. +- (void)mouseExited:(NSEvent*)event { + entered_ = NO; + [closeButton_ setNeedsDisplay]; + [zoomButton_ setNeedsDisplay]; + [miniaturizeButton_ setNeedsDisplay]; +} + +- (BOOL)mouseInGroup:(NSButton*)widget { + return entered_; +} - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event fromTable: (KeyToCommandMapper)commandForKeyboardShortcut { diff --git a/chrome/browser/cocoa/chrome_browser_window_unittest.mm b/chrome/browser/cocoa/chrome_browser_window_unittest.mm index e531e43..77986df 100644 --- a/chrome/browser/cocoa/chrome_browser_window_unittest.mm +++ b/chrome/browser/cocoa/chrome_browser_window_unittest.mm @@ -8,6 +8,7 @@ #include "chrome/app/chrome_dll_resource.h" #import "chrome/browser/cocoa/chrome_browser_window.h" #import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/browser_frame_view.h" #import "chrome/browser/cocoa/cocoa_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -73,7 +74,7 @@ TEST_F(ChromeBrowserWindowTest, ShowAndClose) { // forwards it to [delegate executeCommand:]. Assume that other // CommandForKeyboardShortcut() will work the same for the rest. TEST_F(ChromeBrowserWindowTest, PerformKeyEquivalentForwardToExecuteCommand) { - NSEvent *event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1); + NSEvent* event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1); id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; // -stub to satisfy the DCHECK. @@ -95,7 +96,7 @@ TEST_F(ChromeBrowserWindowTest, PerformKeyEquivalentForwardToExecuteCommand) { // TODO(shess) Think of a way to test that it is sent to the // superclass. TEST_F(ChromeBrowserWindowTest, PerformKeyEquivalentNoForward) { - NSEvent *event = KeyEvent(0, 0); + NSEvent* event = KeyEvent(0, 0); id delegate = [OCMockObject mockForClass:[BrowserWindowController class]]; // -stub to satisfy the DCHECK. @@ -142,4 +143,50 @@ TEST_F(ChromeBrowserWindowTest, DoesHideTitle) { EXPECT_TRUE([emptyTitleData isEqualToData:hiddenTitleData]); } +// Test to make sure that our window widgets are in the right place. +TEST_F(ChromeBrowserWindowTest, WindowWidgetLocation) { + NSCell* closeBoxCell = [window_ accessibilityAttributeValue: + NSAccessibilityCloseButtonAttribute]; + NSView* closeBoxControl = [closeBoxCell controlView]; + EXPECT_TRUE(closeBoxControl); + NSRect closeBoxFrame = [closeBoxControl frame]; + NSRect windowBounds = [window_ frame]; + windowBounds.origin = NSZeroPoint; + EXPECT_EQ(NSMaxY(closeBoxFrame), + NSMaxY(windowBounds) - kChromeWindowButtonsOffsetFromTop); + EXPECT_EQ(NSMinX(closeBoxFrame), kChromeWindowButtonsOffsetFromLeft); + + NSCell* miniaturizeCell = [window_ accessibilityAttributeValue: + NSAccessibilityMinimizeButtonAttribute]; + NSView* miniaturizeControl = [miniaturizeCell controlView]; + EXPECT_TRUE(miniaturizeControl); + NSRect miniaturizeFrame = [miniaturizeControl frame]; + EXPECT_EQ(NSMaxY(miniaturizeFrame), + NSMaxY(windowBounds) - kChromeWindowButtonsOffsetFromTop); + EXPECT_EQ(NSMinX(miniaturizeFrame), + NSMaxX(closeBoxFrame) + kChromeWindowButtonsInterButtonSpacing); +} + +// Test that we actually have a tracking area in place. +TEST_F(ChromeBrowserWindowTest, WindowWidgetTrackingArea) { + NSCell* closeBoxCell = [window_ accessibilityAttributeValue: + NSAccessibilityCloseButtonAttribute]; + NSView* closeBoxControl = [closeBoxCell controlView]; + NSView* frameView = [[window_ contentView] superview]; + NSArray* trackingAreas = [frameView trackingAreas]; + NSPoint point = [closeBoxControl frame].origin; + point.x += 1; + point.y += 1; + BOOL foundArea = NO; + for (NSTrackingArea* area in trackingAreas) { + NSRect rect = [area rect]; + foundArea = NSPointInRect(point, rect); + if (foundArea) { + EXPECT_TRUE([[area owner] isEqual:window_]); + break; + } + } + EXPECT_TRUE(foundArea); +} + } // namespace diff --git a/chrome/browser/cocoa/download_shelf_view.mm b/chrome/browser/cocoa/download_shelf_view.mm index 4d12529..1dcc562 100644 --- a/chrome/browser/cocoa/download_shelf_view.mm +++ b/chrome/browser/cocoa/download_shelf_view.mm @@ -17,17 +17,20 @@ - (void)drawRect:(NSRect)rect { BOOL isKey = [[self window] isKeyWindow]; - GTMTheme *theme = [self gtm_theme]; + GTMTheme* theme = [self gtm_theme]; - NSImage *backgroundImage = [theme backgroundImageForStyle:GTMThemeStyleToolBar + NSImage* backgroundImage = [theme backgroundImageForStyle:GTMThemeStyleToolBar state:GTMThemeStateActiveWindow]; if (backgroundImage) { - [[NSGraphicsContext currentContext] setPatternPhase:NSZeroPoint]; - NSColor *color = [NSColor colorWithPatternImage:backgroundImage]; + // We want our backgrounds for the shelf to be phased from the upper + // left hand corner of the view. + NSPoint phase = NSMakePoint(0, NSHeight([self bounds])); + [[NSGraphicsContext currentContext] setPatternPhase:phase]; + NSColor* color = [NSColor colorWithPatternImage:backgroundImage]; [color set]; NSRectFill([self bounds]); } else { - NSGradient *gradient = [theme gradientForStyle:GTMThemeStyleToolBar + NSGradient* gradient = [theme gradientForStyle:GTMThemeStyleToolBar state:isKey]; NSPoint startPoint = [self convertPointFromBase:NSMakePoint(0, 0)]; NSPoint endPoint = [self convertPointFromBase: diff --git a/chrome/browser/cocoa/find_bar_view.mm b/chrome/browser/cocoa/find_bar_view.mm index 238884d..259d59d 100644 --- a/chrome/browser/cocoa/find_bar_view.mm +++ b/chrome/browser/cocoa/find_bar_view.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/cocoa/find_bar_view.h" +#import "chrome/browser/cocoa/find_bar_view.h" @implementation FindBarView @@ -27,7 +27,7 @@ NSPoint bottomRight = NSMakePoint(NSMaxX(rect) - (2 * curveSize), NSMinY(rect)); - NSBezierPath *path = [NSBezierPath bezierPath]; + NSBezierPath* path = [NSBezierPath bezierPath]; [path moveToPoint:topLeft]; [path curveToPoint:midLeft1 controlPoint1:NSMakePoint(midLeft1.x, topLeft.y) @@ -45,11 +45,16 @@ [path curveToPoint:topRight controlPoint1:NSMakePoint(midRight2.x, topLeft.y) controlPoint2:NSMakePoint(midRight2.x, topLeft.y)]; - - [NSGraphicsContext saveGraphicsState]; + NSGraphicsContext* context = [NSGraphicsContext currentContext]; + [context saveGraphicsState]; [path addClip]; - [super drawRect:rect]; - [NSGraphicsContext restoreGraphicsState]; + + // Set the pattern phase + NSPoint phase = [self gtm_themePatternPhase]; + + [context setPatternPhase:phase]; + [super drawBackground]; + [context restoreGraphicsState]; [[self strokeColor] set]; [path stroke]; diff --git a/chrome/browser/cocoa/status_bubble_mac_unittest.mm b/chrome/browser/cocoa/status_bubble_mac_unittest.mm index d462f0d..8d5681b 100644 --- a/chrome/browser/cocoa/status_bubble_mac_unittest.mm +++ b/chrome/browser/cocoa/status_bubble_mac_unittest.mm @@ -16,9 +16,13 @@ @interface StatusBubbleMacTestWindowDelegate : NSObject <GTMThemeDelegate>; @end @implementation StatusBubbleMacTestWindowDelegate -- (GTMTheme *)gtm_themeForWindow:(NSWindow *)window { +- (GTMTheme*)gtm_themeForWindow:(NSWindow*)window { return [[[GTMTheme alloc] init] autorelease]; } + +- (NSPoint)gtm_themePatternPhaseForWindow:(NSWindow*)window { + return NSZeroPoint; +} @end class StatusBubbleMacTest : public PlatformTest { diff --git a/chrome/browser/cocoa/tab_cell.h b/chrome/browser/cocoa/tab_cell.h index 0f0ff0f..e69de29 100644 --- a/chrome/browser/cocoa/tab_cell.h +++ b/chrome/browser/cocoa/tab_cell.h @@ -1,20 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_COCOA_TAB_CELL_H_ -#define CHROME_BROWSER_COCOA_TAB_CELL_H_ - -#import <Cocoa/Cocoa.h> - -// A button cell that handles drawing/highlighting of tabs in the tab bar. Text -// drawing leaves room for an icon view on the left of the tab and a close -// button on the right. Technically, though, it doesn't know anything about what -// it's leaving space for, so they could be reversed or even replaced by views -// for other purposes. - -@interface TabCell : NSButtonCell { -} -@end - -#endif // CHROME_BROWSER_COCOA_TAB_CELL_H_ diff --git a/chrome/browser/cocoa/tab_cell.mm b/chrome/browser/cocoa/tab_cell.mm index 6e2c22c..e69de29 100644 --- a/chrome/browser/cocoa/tab_cell.mm +++ b/chrome/browser/cocoa/tab_cell.mm @@ -1,76 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "base/scoped_nsobject.h" -#import "chrome/browser/cocoa/tab_cell.h" -#import "third_party/GTM/AppKit/GTMTheme.h" -#import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" - - -@implementation TabCell - -- (id)initTextCell:(NSString *)aString { - self = [super initTextCell:aString]; - if (self != nil) { - // nothing for now... - } - return self; -} - -- (NSBackgroundStyle)interiorBackgroundStyle { - return [[[self controlView] gtm_theme] - interiorBackgroundStyleForStyle:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; -} - -// Override drawing the button so that it looks like a Chromium tab instead -// of just a normal MacOS button. -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { - // Inset where the text is drawn to keep it away from the sloping edges of the - // tab, the close box, and the icon view. These constants are derived - // empirically as the cell doesn't know about the surrounding view objects. - // TODO(pinkerton/alcor): Fix this somehow? - const int kIconXOffset = 28; - const int kCloseBoxXOffset = 21; - NSRect frame = NSOffsetRect(cellFrame, kIconXOffset, 0); - frame.size.width -= kCloseBoxXOffset + kIconXOffset; - [self drawInteriorWithFrame:frame - inView:controlView]; -} - -- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { - GTMTheme* theme = [[self controlView] gtm_theme]; - NSColor* textColor = [theme textColorForStyle:GTMThemeStyleToolBar - state:[self isHighlighted]]; - - scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]); - [textShadow setShadowBlurRadius:0.0f]; - [textShadow.get() setShadowColor:[textColor gtm_legibleTextColor]]; - [textShadow.get() setShadowOffset:NSMakeSize(0.0f, -1.0f)]; - - NSDictionary* attributes = - [NSDictionary dictionaryWithObjectsAndKeys: - [self font], NSFontAttributeName, - textColor, NSForegroundColorAttributeName, - textShadow.get(), NSShadowAttributeName, - nil]; - - [[self title] drawInRect:[self titleRectForBounds:cellFrame] - withAttributes:attributes]; - - NSRect imageBounds = NSZeroRect; - imageBounds.size = [[self image] size]; - [[self image] drawInRect:[self imageRectForBounds:cellFrame] - fromRect:imageBounds - operation:NSCompositeSourceOver - fraction:1.0]; -} - -- (void)highlight:(BOOL)flag - withFrame:(NSRect)cellFrame - inView:(NSView *)controlView { - // Don't do normal highlighting -} - -@end diff --git a/chrome/browser/cocoa/tab_cell_unittest.mm b/chrome/browser/cocoa/tab_cell_unittest.mm index 9eb29fc..e69de29 100644 --- a/chrome/browser/cocoa/tab_cell_unittest.mm +++ b/chrome/browser/cocoa/tab_cell_unittest.mm @@ -1,42 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import <Cocoa/Cocoa.h> - -#include "base/scoped_nsobject.h" -#import "chrome/browser/cocoa/tab_cell.h" -#import "chrome/browser/cocoa/cocoa_test_helper.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -namespace { - -class TabCellTest : public PlatformTest { - public: - TabCellTest() { - NSRect frame = NSMakeRect(0, 0, 50, 30); - view_.reset([[NSButton alloc] initWithFrame:frame]); - scoped_nsobject<TabCell> cell([[TabCell alloc] initTextCell:@"Testing"]); - [view_ setCell:cell.get()]; - [cocoa_helper_.contentView() addSubview:view_.get()]; - } - - CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... - scoped_nsobject<NSButton> view_; -}; - -// Test adding/removing from the view hierarchy, mostly to ensure nothing -// leaks or crashes. -TEST_F(TabCellTest, AddRemove) { - EXPECT_EQ(cocoa_helper_.contentView(), [view_ superview]); - [view_.get() removeFromSuperview]; - EXPECT_FALSE([view_ superview]); -} - -// Test drawing, mostly to ensure nothing leaks or crashes. -TEST_F(TabCellTest, Display) { - [view_ display]; -} - -} // namespace diff --git a/chrome/browser/cocoa/tab_controller.h b/chrome/browser/cocoa/tab_controller.h index 7d44751..1bc9300 100644 --- a/chrome/browser/cocoa/tab_controller.h +++ b/chrome/browser/cocoa/tab_controller.h @@ -64,7 +64,7 @@ enum TabLoadingState { + (float)minSelectedTabWidth; // The view associated with this controller, pre-casted as a TabView -- (TabView *)tabView; +- (TabView*)tabView; // Closes the associated TabView by relaying the message to |target_| to // perform the close. @@ -78,18 +78,17 @@ enum TabLoadingState { - (void)setIconView:(NSView*)iconView; - (NSView*)iconView; -// (Re)apply the current theme. -- (void)applyTheme; - // Called by the tabs to determine whether we are in rapid (tab) closure mode. // In this mode, we handle clicks slightly differently due to animation. // Ideally, tabs would know about their own animation and wouldn't need this. - (BOOL)inRapidClosureMode; +// Update the title color to match the tabs current state. +- (void)updateTitleColor; @end @interface TabController(TestingAPI) -- (NSString *)toolTip; +- (NSString*)toolTip; - (int)iconCapacity; - (BOOL)shouldShowIcon; - (BOOL)shouldShowCloseButton; diff --git a/chrome/browser/cocoa/tab_controller.mm b/chrome/browser/cocoa/tab_controller.mm index 64207f9..94de7cfc 100644 --- a/chrome/browser/cocoa/tab_controller.mm +++ b/chrome/browser/cocoa/tab_controller.mm @@ -33,11 +33,15 @@ self = [super initWithNibName:@"TabView" bundle:mac_util::MainAppBundle()]; if (self != nil) { isIconShowing_ = YES; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(viewResized:) - name:NSViewFrameDidChangeNotification - object:[self view]]; + NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver:self + selector:@selector(viewResized:) + name:NSViewFrameDidChangeNotification + object:[self view]]; + [defaultCenter addObserver:self + selector:@selector(themeChangedNotification:) + name:kGTMThemeDidChangeNotification + object:nil]; } return self; } @@ -52,9 +56,10 @@ // mark ourselves as needing a redraw. - (void)internalSetSelected:(BOOL)selected { selected_ = selected; - [(TabView *)[self view] setState:selected]; + TabView* tabView = static_cast<TabView*>([self view]); + [tabView setState:selected]; [self updateVisibility]; - [self applyTheme]; + [self updateTitleColor]; } // Called when the tab's nib is done loading and all outlets are hooked up. @@ -71,9 +76,6 @@ iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_); titleCloseWidthOffset_ = NSMaxX([closeButton_ frame]) - NSMaxX(titleFrame); - // Ensure we don't show favicon if the tab is already too small to begin with. - [self updateVisibility]; - [self internalSetSelected:selected_]; } @@ -100,7 +102,7 @@ return [[self target] isCommandEnabled:command forController:self]; } -- (void)setTitle:(NSString *)title { +- (void)setTitle:(NSString*)title { [[self view] setToolTip:title]; [super setTitle:title]; } @@ -131,7 +133,7 @@ return iconView_; } -- (NSString *)toolTip { +- (NSString*)toolTip { return [[self view] toolTip]; } @@ -212,6 +214,21 @@ [titleView_ setFrame:titleFrame]; } +- (void)updateTitleColor { + NSColor* titleColor = nil; + GTMTheme* theme = [[self view] gtm_theme]; + if (![self selected]) { + titleColor = [theme textColorForStyle:GTMThemeStyleTabBarDeselected + state:GTMThemeStateActiveWindow]; + } + // Default to the selected text color unless told otherwise. + if (!titleColor) { + titleColor = [theme textColorForStyle:GTMThemeStyleTabBarSelected + state:GTMThemeStateActiveWindow]; + } + [titleView_ setTextColor:titleColor ? titleColor : [NSColor textColor]]; +} + // Called when our view is resized. If it gets too small, start by hiding // the close button and only show it if tab is selected. Eventually, hide the // icon as well. We know that this is for our view because we only registered @@ -220,21 +237,12 @@ [self updateVisibility]; } -- (void)applyTheme { - GTMTheme* theme = [[self view] gtm_theme]; - NSColor* color = nil; - if (!selected_) { - color = [theme textColorForStyle:GTMThemeStyleTabBarDeselected - state:GTMThemeStateActiveWindow]; +- (void)themeChangedNotification:(NSNotification*)notification { + GTMTheme* theme = [notification object]; + NSView* view = [self view]; + if ([theme isEqual:[view gtm_theme]]) { + [self updateTitleColor]; } - // Default to the selected text color unless told otherwise. - if (!color) { - color = [theme textColorForStyle:GTMThemeStyleToolBar - state:GTMThemeStateActiveWindow]; - } - - [titleView_ setTextColor:color ? color : [NSColor textColor]]; - [[self view] setNeedsDisplay:YES]; } // Called by the tabs to determine whether we are in rapid (tab) closure mode. diff --git a/chrome/browser/cocoa/tab_strip_controller.h b/chrome/browser/cocoa/tab_strip_controller.h index e9f0625..2c37f64 100644 --- a/chrome/browser/cocoa/tab_strip_controller.h +++ b/chrome/browser/cocoa/tab_strip_controller.h @@ -94,7 +94,7 @@ class ToolbarModel; browser:(Browser*)browser; // Return the view for the currently selected tab. -- (NSView *)selectedTabView; +- (NSView*)selectedTabView; // Set the frame of the selected tab, also updates the internal frame dict. - (void)setFrameOfSelectedTab:(NSRect)frame; @@ -133,9 +133,6 @@ class ToolbarModel; // Force the tabs to rearrange themselves to reflect the current model. - (void)layoutTabs; -// The user changed the theme, or theme state changed. -- (void)applyTheme; - // Are we in rapid (tab) closure mode? I.e., is a full layout deferred (while // the user closes tabs)? Needed to overcome missing clicks during rapid tab // closure. diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm index 2f10f27..e72eb19 100644 --- a/chrome/browser/cocoa/tab_strip_controller.mm +++ b/chrome/browser/cocoa/tab_strip_controller.mm @@ -18,7 +18,6 @@ #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/constrained_window_mac.h" #import "chrome/browser/cocoa/tab_strip_view.h" -#import "chrome/browser/cocoa/tab_cell.h" #import "chrome/browser/cocoa/tab_contents_controller.h" #import "chrome/browser/cocoa/tab_controller.h" #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" @@ -426,7 +425,7 @@ static const float kIndentLeavingSpaceForControls = 64.0; [NSAnimationContext endGrouping]; // Store the frame by identifier to aviod redundant calls to animator. - NSValue *identifier = [NSValue valueWithPointer:[tab view]]; + NSValue* identifier = [NSValue valueWithPointer:[tab view]]; [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] forKey:identifier]; continue; @@ -455,8 +454,8 @@ static const float kIndentLeavingSpaceForControls = 64.0; // Check the frame by identifier to avoid redundant calls to animator. id frameTarget = visible && animate ? [[tab view] animator] : [tab view]; - NSValue *identifier = [NSValue valueWithPointer:[tab view]]; - NSValue *oldTargetValue = [targetFrames_ objectForKey:identifier]; + NSValue* identifier = [NSValue valueWithPointer:[tab view]]; + NSValue* oldTargetValue = [targetFrames_ objectForKey:identifier]; if (!oldTargetValue || !NSEqualRects([oldTargetValue rectValue], tabFrame)) { [frameTarget setFrame:tabFrame]; @@ -641,7 +640,7 @@ static const float kIndentLeavingSpaceForControls = 64.0; hoveredTab_ = nil; } - NSValue *identifier = [NSValue valueWithPointer:tab]; + NSValue* identifier = [NSValue valueWithPointer:tab]; [targetFrames_ removeObjectForKey:identifier]; // Once we're totally done with the tab, delete its controller @@ -782,14 +781,14 @@ static const float kIndentLeavingSpaceForControls = 64.0; } - (void)setFrameOfSelectedTab:(NSRect)frame { - NSView *view = [self selectedTabView]; - NSValue *identifier = [NSValue valueWithPointer:view]; + NSView* view = [self selectedTabView]; + NSValue* identifier = [NSValue valueWithPointer:view]; [targetFrames_ setObject:[NSValue valueWithRect:frame] forKey:identifier]; [view setFrame:frame]; } -- (NSView *)selectedTabView { +- (NSView*)selectedTabView { int selectedIndex = tabModel_->selected_index(); return [self viewAtIndex:selectedIndex]; } @@ -837,12 +836,6 @@ static const float kIndentLeavingSpaceForControls = 64.0; tabModel_->InsertTabContentsAt(index, contents, true, false); } -- (void)applyTheme { - for (TabController* tab in tabArray_.get()) { - [tab applyTheme]; - } -} - // Called when the tab strip view changes size. As we only registered for // changes on our view, we know it's only for our view. Layout w/out // animations since they are blocked by the resize nested runloop. We need @@ -856,7 +849,7 @@ static const float kIndentLeavingSpaceForControls = 64.0; return availableResizeWidth_ != kUseFullAvailableWidth; } -- (void)mouseMoved:(NSEvent *)event { +- (void)mouseMoved:(NSEvent*)event { // Use hit test to figure out what view we are hovering over. TabView* targetView = (TabView*)[tabView_ hitTest:[event locationInWindow]]; if (![targetView isKindOfClass:[TabView class]]) { diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm index fd6a2a4..fd1be74 100644 --- a/chrome/browser/cocoa/tab_view.mm +++ b/chrome/browser/cocoa/tab_view.mm @@ -59,7 +59,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; // Overridden so that mouse clicks come to this view (the parent of the // hierarchy) first. We want to handle clicks and drags in this class and // leave the background button for display purposes only. -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { +- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent { return YES; } @@ -88,7 +88,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; [self setNeedsDisplay:YES]; } -- (void)mouseEntered:(NSEvent *)theEvent { +- (void)mouseEntered:(NSEvent*)theEvent { if ([theEvent trackingArea] == closeTrackingArea_) { [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar_h.pdf")]; } else { @@ -99,13 +99,13 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; } } -- (void)mouseMoved:(NSEvent *)theEvent { +- (void)mouseMoved:(NSEvent*)theEvent { hoverPoint_ = [self convertPoint:[theEvent locationInWindow] fromView:nil]; [self setNeedsDisplay:YES]; } -- (void)mouseExited:(NSEvent *)theEvent { +- (void)mouseExited:(NSEvent*)theEvent { if ([theEvent trackingArea] == closeTrackingArea_) { [closeButton_ setImage:nsimage_cache::ImageNamed(@"close_bar.pdf")]; } else { @@ -118,7 +118,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; // Determines which view a click in our frame actually hit. It's either this // view or our child close button. -- (NSView *)hitTest:(NSPoint)aPoint { +- (NSView*)hitTest:(NSPoint)aPoint { NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]]; NSRect frame = [self frame]; @@ -136,7 +136,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; // Returns |YES| if this tab can be torn away into a new window. - (BOOL)canBeDragged { - NSWindowController *controller = [sourceWindow_ windowController]; + NSWindowController* controller = [sourceWindow_ windowController]; if ([controller isKindOfClass:[TabWindowController class]]) { TabWindowController* realController = static_cast<TabWindowController*>(controller); @@ -154,7 +154,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; for (NSWindow* window in [NSApp windows]) { if (window == dragWindow) continue; if (![window isVisible]) continue; - NSWindowController *controller = [window windowController]; + NSWindowController* controller = [window windowController]; if ([controller isKindOfClass:[TabWindowController class]]) { TabWindowController* realController = static_cast<TabWindowController*>(controller); @@ -189,7 +189,7 @@ static const NSTimeInterval kTearDuration = 0.333; // has moved less than the threshold, we want to close the tab. static const CGFloat kRapidCloseDist = 2.5; -- (void)mouseDown:(NSEvent *)theEvent { +- (void)mouseDown:(NSEvent*)theEvent { NSPoint downLocation = [theEvent locationInWindow]; // During the tab closure animation (in particular, during rapid tab closure), @@ -284,7 +284,7 @@ static const CGFloat kRapidCloseDist = 2.5; } } -- (void)mouseDragged:(NSEvent *)theEvent { +- (void)mouseDragged:(NSEvent*)theEvent { // Special-case this to keep the logic below simpler. if (moveWindowOnDrag_) { NSPoint thisPoint = [NSEvent mouseLocation]; @@ -452,7 +452,7 @@ static const CGFloat kRapidCloseDist = 2.5; // Compute where placeholder should go and insert it into the // destination tab strip. NSRect dropTabFrame = [[targetController_ tabStripView] frame]; - TabView *draggedTabView = (TabView *)[draggedController_ selectedTabView]; + TabView* draggedTabView = (TabView*)[draggedController_ selectedTabView]; NSRect tabFrame = [draggedTabView frame]; tabFrame.origin = [dragWindow_ convertBaseToScreen:tabFrame.origin]; tabFrame.origin = [[targetController_ window] @@ -490,7 +490,7 @@ static const CGFloat kRapidCloseDist = 2.5; } } -- (void)mouseUp:(NSEvent *)theEvent { +- (void)mouseUp:(NSEvent*)theEvent { // The drag/click is done. If the user dragged the mouse, finalize the drag // and clean up. @@ -549,19 +549,12 @@ static const CGFloat kRapidCloseDist = 2.5; } } -- (NSPoint)patternPhase { - NSPoint phase = NSZeroPoint; - phase.x -= [self convertRect:[self bounds] toView:nil].origin.x; - // offset to start pattern in upper left corner - phase.y += NSHeight([self bounds]) - 1; - return phase; -} - - (void)drawRect:(NSRect)rect { - [[NSGraphicsContext currentContext] saveGraphicsState]; + NSGraphicsContext* context = [NSGraphicsContext currentContext]; + [context saveGraphicsState]; rect = [self bounds]; BOOL active = [[self window] isKeyWindow] || [[self window] isMainWindow]; - BOOL selected = [(NSButton *)self state]; + BOOL selected = [(NSButton*)self state]; // Inset by 0.5 in order to draw on pixels rather than on borders (which would // cause blurry pixels). Decrease height by 1 in order to move away from the @@ -583,7 +576,7 @@ static const CGFloat kRapidCloseDist = 2.5; // Outset many of these values by 1 to cause the fill to bleed outside the // clip area. - NSBezierPath *path = [NSBezierPath bezierPath]; + NSBezierPath* path = [NSBezierPath bezierPath]; [path moveToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y - 2)]; [path lineToPoint:NSMakePoint(bottomLeft.x - 1, bottomLeft.y)]; [path lineToPoint:bottomLeft]; @@ -601,52 +594,51 @@ static const CGFloat kRapidCloseDist = 2.5; [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y)]; [path lineToPoint:NSMakePoint(bottomRight.x + 1, bottomRight.y - 2)]; - GTMTheme *theme = [self gtm_theme]; + GTMTheme* theme = [self gtm_theme]; + + // Setting the pattern phase + NSPoint phase = [self gtm_themePatternPhase]; + [context setPatternPhase:phase]; if (!selected) { - NSColor *windowColor = + NSColor* windowColor = [theme backgroundPatternColorForStyle:GTMThemeStyleWindow state:GTMThemeStateActiveWindow]; if (windowColor) { [windowColor set]; - - [[NSGraphicsContext currentContext] setPatternPhase:[self patternPhase]]; } else { - NSPoint phase = [self patternPhase]; - phase.y += 1; - [[NSGraphicsContext currentContext] setPatternPhase:phase]; [[NSColor windowBackgroundColor] set]; } [path fill]; - NSColor *tabColor = + NSColor* tabColor = [theme backgroundPatternColorForStyle:GTMThemeStyleTabBarDeselected state:GTMThemeStateActiveWindow]; if (tabColor) { [tabColor set]; - [[NSGraphicsContext currentContext] setPatternPhase:[self patternPhase]]; } else { [[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set]; } [path fill]; - } - [[NSGraphicsContext currentContext] saveGraphicsState]; + [context saveGraphicsState]; [path addClip]; if (selected || hoverAlpha_ > 0) { // Draw the background. CGFloat backgroundAlpha = hoverAlpha_ * 0.5; - [[NSGraphicsContext currentContext] saveGraphicsState]; - CGContextRef context = - (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]); - CGContextBeginTransparencyLayer(context, 0); + [context saveGraphicsState]; + CGContextRef cgContext = + (CGContextRef)([context graphicsPort]); + CGContextBeginTransparencyLayer(cgContext, 0); if (!selected) - CGContextSetAlpha(context, backgroundAlpha); + CGContextSetAlpha(cgContext, backgroundAlpha); [path addClip]; - [super drawRect:rect]; + [context saveGraphicsState]; + [super drawBackground]; + [context restoreGraphicsState]; // Draw a mouse hover gradient for the default themes if (!selected) { @@ -671,8 +663,8 @@ static const CGFloat kRapidCloseDist = 2.5; } } - CGContextEndTransparencyLayer(context); - [[NSGraphicsContext currentContext] restoreGraphicsState]; + CGContextEndTransparencyLayer(cgContext); + [context restoreGraphicsState]; } // Draw the top inner highlight. @@ -684,10 +676,10 @@ static const CGFloat kRapidCloseDist = 2.5; setStroke]; [highlightPath stroke]; - [[NSGraphicsContext currentContext] restoreGraphicsState]; + [context restoreGraphicsState]; // Draw the top stroke. - [[NSGraphicsContext currentContext] saveGraphicsState]; + [context saveGraphicsState]; if (selected) { [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.3 : 0.15] set]; } else { @@ -696,7 +688,7 @@ static const CGFloat kRapidCloseDist = 2.5; } [path setLineWidth:1.0]; [path stroke]; - [[NSGraphicsContext currentContext] restoreGraphicsState]; + [context restoreGraphicsState]; // Draw the bottom border. if (!selected) { @@ -706,7 +698,7 @@ static const CGFloat kRapidCloseDist = 2.5; [[NSColor colorWithDeviceWhite:0.0 alpha:active ? 0.3 : 0.15] set]; NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); } - [[NSGraphicsContext currentContext] restoreGraphicsState]; + [context restoreGraphicsState]; } // Called when the user hits the right mouse button (or control-clicks) to @@ -715,4 +707,11 @@ static const CGFloat kRapidCloseDist = 2.5; [NSMenu popUpContextMenu:[self menu] withEvent:theEvent forView:self]; } +- (void)viewDidMoveToWindow { + [super viewDidMoveToWindow]; + if ([self window]) { + [controller_ updateTitleColor]; + } +} + @end diff --git a/chrome/browser/cocoa/tab_window_controller.mm b/chrome/browser/cocoa/tab_window_controller.mm index 2d02e70..20267c8 100644 --- a/chrome/browser/cocoa/tab_window_controller.mm +++ b/chrome/browser/cocoa/tab_window_controller.mm @@ -15,7 +15,7 @@ @synthesize tabStripView = tabStripView_; @synthesize tabContentArea = tabContentArea_; -- (id)initWithWindow:(NSWindow *)window { +- (id)initWithWindow:(NSWindow*)window { if ((self = [super initWithWindow:window]) != nil) { lockedTabs_.reset([[NSMutableSet alloc] initWithCapacity:10]); } @@ -77,6 +77,7 @@ } else { [[[[self window] contentView] superview] addSubview:[self tabStripView]]; [[self window] setContentView:cachedContentView_]; + [[[[self window] contentView] superview] updateTrackingAreas]; } } @@ -89,9 +90,10 @@ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(removeOverlay) object:nil]; + NSWindow* window = [self window]; if (useOverlay && !overlayWindow_) { DCHECK(!cachedContentView_); - overlayWindow_ = [[NSPanel alloc] initWithContentRect:[[self window] frame] + overlayWindow_ = [[NSPanel alloc] initWithContentRect:[window frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; @@ -99,17 +101,17 @@ [overlayWindow_ setBackgroundColor:[NSColor clearColor]]; [overlayWindow_ setOpaque:NO]; [overlayWindow_ setDelegate:self]; - cachedContentView_ = [[self window] contentView]; + cachedContentView_ = [window contentView]; [self moveViewsBetweenWindowAndOverlay:useOverlay]; - [[self window] addChildWindow:overlayWindow_ ordered:NSWindowAbove]; + [window addChildWindow:overlayWindow_ ordered:NSWindowAbove]; [overlayWindow_ orderFront:nil]; } else if (!useOverlay && overlayWindow_) { DCHECK(cachedContentView_); - [[self window] setContentView:cachedContentView_]; + [window setContentView:cachedContentView_]; [self moveViewsBetweenWindowAndOverlay:useOverlay]; - [[self window] makeFirstResponder:cachedContentView_]; - [[self window] display]; - [[self window] removeChildWindow:overlayWindow_]; + [window makeFirstResponder:cachedContentView_]; + [window display]; + [window removeChildWindow:overlayWindow_]; [overlayWindow_ orderOut:nil]; [overlayWindow_ release]; overlayWindow_ = nil; @@ -134,7 +136,7 @@ NOTIMPLEMENTED(); } -- (NSView *)selectedTabView { +- (NSView*)selectedTabView { NOTIMPLEMENTED(); return nil; } diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index 5f591db..e85f3a1 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -179,9 +179,7 @@ class PrefObserverBridge : public NotificationObserver { EncodingMenuControllerDelegate::BuildEncodingMenu(profile_, encodingMenu_); } -- (void)removeFromSuperview { - NSLog(@"remove"); -} + - (void)mouseExited:(NSEvent*)theEvent { [[hoveredButton_ cell] setMouseInside:NO animate:YES]; [hoveredButton_ release]; @@ -189,8 +187,8 @@ class PrefObserverBridge : public NotificationObserver { } - (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent { - NSButton* targetView = (NSButton *)[[self view] - hitTest:[theEvent locationInWindow]]; + NSButton* targetView = (NSButton*)[[self view] + hitTest:[theEvent locationInWindow]]; // Only interpret the view as a hoverButton_ if it's both button and has a // button cell that cares. GradientButtonCell derived cells care. @@ -434,10 +432,10 @@ class PrefObserverBridge : public NotificationObserver { [resizeDelegate_ resizeView:[self view] newHeight:newToolbarHeight]; } -- (NSString *)view:(NSView *)view - stringForToolTip:(NSToolTipTag)tag - point:(NSPoint)point - userData:(void *)userData { +- (NSString*)view:(NSView*)view + stringForToolTip:(NSToolTipTag)tag + point:(NSPoint)point + userData:(void*)userData { DCHECK(view == goButton_); // Following chrome/browser/views/go_button.cc: GoButton::GetTooltipText() diff --git a/chrome/browser/cocoa/toolbar_view.mm b/chrome/browser/cocoa/toolbar_view.mm index 17278aa..e8111d0 100644 --- a/chrome/browser/cocoa/toolbar_view.mm +++ b/chrome/browser/cocoa/toolbar_view.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/cocoa/toolbar_view.h" +#import "chrome/browser/cocoa/toolbar_view.h" @implementation ToolbarView @@ -11,4 +11,12 @@ return NO; } +- (void)drawRect:(NSRect)rect { + // The toolbar's background pattern is phased relative to the + // tab strip view's background pattern. + NSPoint phase = [self gtm_themePatternPhase]; + [[NSGraphicsContext currentContext] setPatternPhase:phase]; + [self drawBackground]; +} + @end diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 0120dc2..9f4827d 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1011,6 +1011,8 @@ 'browser/cocoa/bookmark_name_folder_controller.h', 'browser/cocoa/bookmark_name_folder_controller.mm', 'browser/cocoa/browser_test_helper.h', + 'browser/cocoa/browser_frame_view.h', + 'browser/cocoa/browser_frame_view.mm', 'browser/cocoa/browser_window_cocoa.h', 'browser/cocoa/browser_window_cocoa.mm', 'browser/cocoa/browser_window_controller.h', @@ -1125,8 +1127,6 @@ 'browser/cocoa/shell_dialogs_mac.mm', 'browser/cocoa/status_bubble_mac.h', 'browser/cocoa/status_bubble_mac.mm', - 'browser/cocoa/tab_cell.h', - 'browser/cocoa/tab_cell.mm', 'browser/cocoa/tab_contents_controller.h', 'browser/cocoa/tab_contents_controller.mm', 'browser/cocoa/tab_controller.h', @@ -4183,6 +4183,7 @@ 'browser/cocoa/bookmark_menu_bridge_unittest.mm', 'browser/cocoa/bookmark_menu_cocoa_controller_unittest.mm', 'browser/cocoa/bookmark_name_folder_controller_unittest.mm', + 'browser/cocoa/browser_frame_view_unittest.mm', 'browser/cocoa/browser_window_cocoa_unittest.mm', 'browser/cocoa/browser_window_controller_unittest.mm', 'browser/cocoa/bubble_view_unittest.mm', @@ -4226,7 +4227,6 @@ 'browser/cocoa/sad_tab_view_unittest.mm', 'browser/cocoa/search_engine_list_model_unittest.mm', 'browser/cocoa/status_bubble_mac_unittest.mm', - 'browser/cocoa/tab_cell_unittest.mm', 'browser/cocoa/tab_controller_unittest.mm', 'browser/cocoa/tab_strip_controller_unittest.mm', 'browser/cocoa/tab_strip_view_unittest.mm', |