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/browser_frame_view.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/browser_frame_view.mm')
-rw-r--r-- | chrome/browser/cocoa/browser_frame_view.mm | 176 |
1 files changed, 176 insertions, 0 deletions
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 |