diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-09 22:37:55 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-09 22:37:55 +0000 |
commit | d546029a268e19c244bcbfba57e4bd2d39d44a83 (patch) | |
tree | 82090113ed3095ac5db6fe5610a908846b7cf0ec /chrome/browser/cocoa/chrome_browser_window.mm | |
parent | 8717745b839efbe446902f3449a3a348f687a42f (diff) | |
download | chromium_src-d546029a268e19c244bcbfba57e4bd2d39d44a83.zip chromium_src-d546029a268e19c244bcbfba57e4bd2d39d44a83.tar.gz chromium_src-d546029a268e19c244bcbfba57e4bd2d39d44a83.tar.bz2 |
Several theming fixes for the Mac. Sorry for the extensive change, but they
were all sort of intertwined.
Fixes up patterns in general so that they are all in phase.
Moves the window widget buttons down by two pixels.
Draws overlays correctly.
Fixes up some accessibility issues with the default window widgets.
Gets rid of some out of date files (tab_cell).
BUG=18438, 18547, 19851, 20295, 22213, 23651, 24338
TEST=Launch Chrome. Switch to "dots" theme from the Google themes. Create a couple of tabs. Check to make sure that the background pattern line up with the tabs. Move the tabs around. Check that the hightlight colors and text colors look correct for all of the tabs. Make sure the patterns stay lined up. Resize the window, make sure none of the patterns move around. Create new windows by dragging the tabs out of the windows and make sure a new window is created with the correct pattern. Show the "find" bar. Make sure its pattern lines up correctly with the tabbar. Switch to default theme. Make sure it looks correct and draws properly. Switch to Zen theme and make sure that the overlay at the top draws correctly. Create a new window. make sure that the rollovers in the window widgets work correctly in both the active and inactive window. Mouse down on the zoom button in the inactive window and notice that the window context changes. Move off of the zoom button and mouse up. Mouse down on the miniaturize button on the inactive window and notice that the window context does not change. Move off of the miniaturize button and mouse up. Do the same thing you did for the miniaturize button for the close button. Start up Accessibility Inspector from the developer tools. Make sure that the window widgets report their accessibility information correctly.
Review URL: http://codereview.chromium.org/260009
Patch from dmaclach@chromium.org.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28613 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/chrome_browser_window.mm')
-rw-r--r-- | chrome/browser/cocoa/chrome_browser_window.mm | 249 |
1 files changed, 249 insertions, 0 deletions
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 { |