summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/cocoa/background_gradient_view.h5
-rw-r--r--chrome/browser/cocoa/background_gradient_view.mm35
-rw-r--r--chrome/browser/cocoa/background_gradient_view_unittest.mm15
-rw-r--r--chrome/browser/cocoa/browser_frame_view.h52
-rw-r--r--chrome/browser/cocoa/browser_frame_view.mm176
-rw-r--r--chrome/browser/cocoa/browser_frame_view_unittest.mm48
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm111
-rw-r--r--chrome/browser/cocoa/bubble_view.mm2
-rw-r--r--chrome/browser/cocoa/chrome_browser_window.h27
-rw-r--r--chrome/browser/cocoa/chrome_browser_window.mm249
-rw-r--r--chrome/browser/cocoa/chrome_browser_window_unittest.mm51
-rw-r--r--chrome/browser/cocoa/download_shelf_view.mm13
-rw-r--r--chrome/browser/cocoa/find_bar_view.mm17
-rw-r--r--chrome/browser/cocoa/status_bubble_mac_unittest.mm6
-rw-r--r--chrome/browser/cocoa/tab_cell.h20
-rw-r--r--chrome/browser/cocoa/tab_cell.mm76
-rw-r--r--chrome/browser/cocoa/tab_cell_unittest.mm42
-rw-r--r--chrome/browser/cocoa/tab_controller.h9
-rw-r--r--chrome/browser/cocoa/tab_controller.mm60
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.h5
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm23
-rw-r--r--chrome/browser/cocoa/tab_view.mm89
-rw-r--r--chrome/browser/cocoa/tab_window_controller.mm20
-rw-r--r--chrome/browser/cocoa/toolbar_controller.mm16
-rw-r--r--chrome/browser/cocoa/toolbar_view.mm10
-rwxr-xr-xchrome/chrome.gyp6
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',