Bug 668195 - Use CoreUI to draw window chrome and toolbars. r=josh

This commit is contained in:
Markus Stange 2011-08-08 16:42:20 +02:00
parent 6ce6bafa91
commit a3c5c31f20
7 changed files with 107 additions and 182 deletions

View File

@ -152,6 +152,7 @@ OS_LIBS += \
-framework SystemConfiguration \
-framework QuickTime \
-framework IOKit \
-F/System/Library/PrivateFrameworks -framework CoreUI \
$(TK_LIBS) \
$(NULL)
endif

View File

@ -143,4 +143,5 @@ LOCAL_INCLUDES = \
LDFLAGS += \
-framework QuickTime \
-framework IOKit \
-F/System/Library/PrivateFrameworks -framework CoreUI \
$(NULL)

View File

@ -293,8 +293,6 @@ public:
NS_IMETHOD BeginSecureKeyboardInput();
NS_IMETHOD EndSecureKeyboardInput();
static void UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut);
void SetPopupWindowLevel();
PRBool IsChildInFailingLeftClickThrough(NSView *aChild);

View File

@ -1649,26 +1649,6 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// Callback used by the default titlebar and toolbar shading.
// *aIn == 0 at the top of the titlebar/toolbar, *aIn == 1 at the bottom
/* static */ void
nsCocoaWindow::UnifiedShading(void* aInfo, const CGFloat* aIn, CGFloat* aOut)
{
UnifiedGradientInfo* info = (UnifiedGradientInfo*)aInfo;
// The gradient percentage at the bottom of the titlebar / top of the toolbar
float start = info->titlebarHeight / (info->titlebarHeight + info->toolbarHeight - 1);
const float startGrey = NativeGreyColorAsFloat(headerStartGrey, info->windowIsMain);
const float endGrey = NativeGreyColorAsFloat(headerEndGrey, info->windowIsMain);
// *aIn is the gradient percentage of the titlebar or toolbar gradient,
// a is the gradient percentage of the whole unified gradient.
float a = info->drawTitlebar ? *aIn * start : start + *aIn * (1 - start);
float result = (1.0f - a) * startGrey + a * endGrey;
aOut[0] = result;
aOut[1] = result;
aOut[2] = result;
aOut[3] = 1.0f;
}
void nsCocoaWindow::SetPopupWindowLevel()
{
// Floating popups are at the floating level and hide when the window is
@ -2377,93 +2357,79 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
return self;
}
// Our pattern width is 1 pixel. CoreGraphics can cache and tile for us.
static const float sPatternWidth = 1.0f;
static void
DrawTitlebarGradient(CGContextRef aContext, float aTitlebarHeight,
float aTitlebarOrigin, float aToolbarHeight, BOOL aIsMain)
DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
float aToolbarHeight, BOOL aIsMain)
{
// Create and draw a CGShading that uses nsCocoaWindow::UnifiedShading() as its callback.
CGFunctionCallbacks callbacks = {0, nsCocoaWindow::UnifiedShading, NULL};
UnifiedGradientInfo info = { aTitlebarHeight, aToolbarHeight, aIsMain, YES };
CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGShadingRef shading = CGShadingCreateAxial(colorSpace,
CGPointMake(0.0f, aTitlebarOrigin + aTitlebarHeight),
CGPointMake(0.0f, aTitlebarOrigin),
function, NO, NO);
CGColorSpaceRelease(colorSpace);
CGFunctionRelease(function);
CGContextDrawShading(aContext, shading);
CGShadingRelease(shading);
// Draw the one pixel border at the bottom of the titlebar.
if (aToolbarHeight == 0) {
CGRect borderRect = CGRectMake(0.0f, aTitlebarOrigin, sPatternWidth, 1.0f);
DrawNativeGreyColorInRect(aContext, headerBorderGrey, borderRect, aIsMain);
}
int unifiedHeight = aTitlebarRect.size.height + aToolbarHeight;
CUIDraw([NSWindow coreUIRenderer], aTitlebarRect, aContext,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetWindowFrame", @"widget",
@"regularwin", @"windowtype",
(aIsMain ? @"normal" : @"inactive"), @"state",
[NSNumber numberWithInt:unifiedHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey",
[NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawTitleSeparatorKey",
nil],
nil);
// At some window widths the call to CUIDraw doesn't draw the top pixel strip.
// We don't want to have a flickering transparent line, so we overdraw it.
CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1);
CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1,
aTitlebarRect.size.width, 1));
}
// Pattern draw callback for standard titlebar gradients and solid titlebar colors
static void
RepeatedPatternDrawCallback(void* aInfo, CGContextRef aContext)
TitlebarDrawCallback(void* aInfo, CGContextRef aContext)
{
ToolbarWindow *window = (ToolbarWindow*)aInfo;
// Remember: this context is NOT flipped, so the origin is in the bottom left.
float titlebarWidth = [window frame].size.width;
float titlebarHeight = [window titlebarHeight];
float titlebarOrigin = [window frame].size.height - titlebarHeight;
NSRect titlebarRect = NSMakeRect(0, titlebarOrigin, titlebarWidth, titlebarHeight);
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:aContext flipped:NO]];
BOOL isMain = [window isMainWindow];
NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain];
if (!titlebarColor) {
// If the titlebar color is nil, draw the default titlebar shading.
DrawTitlebarGradient(aContext, titlebarHeight, titlebarOrigin,
[window unifiedToolbarHeight], isMain);
} else {
// If the titlebar color is not nil, just set and draw it normally.
[titlebarColor set];
NSRectFill(NSMakeRect(0.0f, titlebarOrigin, sPatternWidth, titlebarHeight));
}
if ([window drawsContentsIntoWindowFrame]) {
NSView* view = [[[window contentView] subviews] lastObject];
if (!view || ![view isKindOfClass:[ChildView class]])
return;
// Draw the background color of the window everywhere but where the titlebar is.
[[window windowBackgroundColor] set];
NSRectFill(NSMakeRect(0.0f, 0.0f, 1.0f, titlebarOrigin));
// Gecko drawing assumes flippedness, but the current context isn't flipped
// (because we're painting into the window's border view, which is not a
// ChildView, so it isn't flpped).
// So we need to set a flip transform.
CGContextScaleCTM(aContext, 1.0f, -1.0f);
CGContextTranslateCTM(aContext, 0.0f, -[window frame].size.height);
NSRect flippedTitlebarRect = NSMakeRect(0, 0, titlebarWidth, titlebarHeight);
[(ChildView*)view drawRect:flippedTitlebarRect inTitlebarContext:aContext];
} else {
BOOL isMain = [window isMainWindow];
NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain];
if (!titlebarColor) {
// If the titlebar color is nil, draw the default titlebar shading.
DrawNativeTitlebar(aContext, NSRectToCGRect(titlebarRect),
[window unifiedToolbarHeight], isMain);
} else {
// If the titlebar color is not nil, just set and draw it normally.
[titlebarColor set];
NSRectFill(titlebarRect);
}
}
[NSGraphicsContext restoreGraphicsState];
}
// Pattern draw callback for "drawsContentsIntoWindowFrame" windows
static void
ContentPatternDrawCallback(void* aInfo, CGContextRef aContext)
{
ToolbarWindow *window = (ToolbarWindow*)aInfo;
NSView* view = [[[window contentView] subviews] lastObject];
if (!view || ![view isKindOfClass:[ChildView class]])
return;
// Gecko drawing assumes flippedness, but the current context isn't flipped
// (because we're painting into the window's border view, which is not a
// ChildView, so it isn't flpped).
// So we need to set a flip transform.
CGContextScaleCTM(aContext, 1.0f, -1.0f);
CGContextTranslateCTM(aContext, 0.0f, -[window frame].size.height);
NSRect titlebarRect = NSMakeRect(0, 0, [window frame].size.width, [window titlebarHeight]);
[(ChildView*)view drawRect:titlebarRect inTitlebarContext:aContext];
}
- (void)setFill
{
CGPatternDrawPatternCallback cb = [mWindow drawsContentsIntoWindowFrame] ?
&ContentPatternDrawCallback : &RepeatedPatternDrawCallback;
float patternWidth = [mWindow drawsContentsIntoWindowFrame] ? [mWindow frame].size.width : sPatternWidth;
float patternWidth = [mWindow frame].size.width;
CGPatternCallbacks callbacks = {0, cb, NULL};
CGPatternCallbacks callbacks = {0, &TitlebarDrawCallback, NULL};
CGPatternRef pattern = CGPatternCreate(mWindow, CGRectMake(0.0f, 0.0f, patternWidth, [mWindow frame].size.height),
CGAffineTransformIdentity, patternWidth, [mWindow frame].size.height,
kCGPatternTilingConstantSpacing, true, &callbacks);

View File

@ -247,7 +247,7 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
break;
case eColor__moz_mac_chrome_active:
case eColor__moz_mac_chrome_inactive: {
int grey = NativeGreyColorAsInt(headerEndGrey, (aID == eColor__moz_mac_chrome_active));
int grey = NativeGreyColorAsInt(toolbarFillGrey, (aID == eColor__moz_mac_chrome_active));
aColor = NS_RGB(grey, grey, grey);
}
break;

View File

@ -1596,73 +1596,30 @@ nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inB
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
float titlebarHeight = [(ToolbarWindow*)aWindow titlebarHeight];
float unifiedHeight = titlebarHeight + inBoxRect.size.height;
BOOL isMain = [aWindow isMainWindow] || ![NSView focusView];
// Draw the gradient
UnifiedGradientInfo info = { titlebarHeight, inBoxRect.size.height, isMain, NO };
struct CGFunctionCallbacks callbacks = { 0, nsCocoaWindow::UnifiedShading, NULL };
CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
float srcY = inBoxRect.origin.y;
float dstY = srcY + inBoxRect.size.height - 1;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGShadingRef shading = CGShadingCreateAxial(colorSpace,
CGPointMake(0, srcY),
CGPointMake(0, dstY), function,
NO, NO);
CGColorSpaceRelease(colorSpace);
CGFunctionRelease(function);
CGContextSaveGState(cgContext);
CGContextClipToRect(cgContext, inBoxRect);
CGContextDrawShading(cgContext, shading);
CGShadingRelease(shading);
// Draw the border at the bottom of the toolbar.
CGRect borderRect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y +
inBoxRect.size.height - 1.0f,
inBoxRect.size.width, 1.0f);
DrawNativeGreyColorInRect(cgContext, headerBorderGrey, borderRect, isMain);
CGRect drawRect = CGRectOffset(inBoxRect, 0, -titlebarHeight);
CUIDraw([NSWindow coreUIRenderer], drawRect, cgContext,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetWindowFrame", @"widget",
@"regularwin", @"windowtype",
(isMain ? @"normal" : @"inactive"), @"state",
[NSNumber numberWithInt:unifiedHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey",
[NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawTitleSeparatorKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil],
nil);
CGContextRestoreGState(cgContext);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
struct GreyGradientInfo {
float startGrey;
float endGrey;
};
static void GreyGradientCallback(void* aInfo, const CGFloat* aIn, CGFloat* aOut)
{
GreyGradientInfo* info = static_cast<GreyGradientInfo*>(aInfo);
CGFloat result = (1.0f - *aIn) * info->startGrey + *aIn * info->endGrey;
aOut[0] = result;
aOut[1] = result;
aOut[2] = result;
aOut[3] = 1.0f;
}
static void DrawGreyGradient(CGContextRef cgContext, const HIRect& rect,
float startGrey, float endGrey)
{
if (rect.size.height <= 0.0f)
return;
GreyGradientInfo info = { startGrey, endGrey };
struct CGFunctionCallbacks callbacks = { 0, GreyGradientCallback, NULL };
CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGShadingRef shading = CGShadingCreateAxial(colorSpace,
CGPointMake(0, CGRectGetMinY(rect)),
CGPointMake(0, CGRectGetMaxY(rect)),
function, false, false);
CGColorSpaceRelease(colorSpace);
CGFunctionRelease(function);
CGContextSaveGState(cgContext);
CGContextClipToRect(cgContext, rect);
CGContextDrawShading(cgContext, shading);
CGContextRestoreGState(cgContext);
CGShadingRelease(shading);
}
void
nsNativeThemeCocoa::DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
nsIFrame *aFrame)
@ -1674,18 +1631,28 @@ nsNativeThemeCocoa::DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRec
BOOL isMain = [NativeWindowForFrame(aFrame) isMainWindow] || ![NSView focusView];
// Draw the borders at the top of the statusbar.
CGRect rect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y,
inBoxRect.size.width, 1.0f);
DrawNativeGreyColorInRect(cgContext, statusbarFirstTopBorderGrey, rect, isMain);
rect.origin.y += 1.0f;
DrawNativeGreyColorInRect(cgContext, statusbarSecondTopBorderGrey, rect, isMain);
CGContextSaveGState(cgContext);
CGContextClipToRect(cgContext, inBoxRect);
// Draw the gradient.
DrawGreyGradient(cgContext, CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y + 2.0f,
inBoxRect.size.width, inBoxRect.size.height - 2.0f),
NativeGreyColorAsFloat(statusbarGradientStartGrey, isMain),
NativeGreyColorAsFloat(statusbarGradientEndGrey, isMain));
// kCUIWidgetWindowFrame draws a complete window frame with both title bar
// and bottom bar. We only want the bottom bar, so we extend the draw rect
// upwards to make space for the title bar, and then we clip it away.
CGRect drawRect = inBoxRect;
const int extendUpwards = 40;
drawRect.origin.y -= extendUpwards;
drawRect.size.height += extendUpwards;
CUIDraw([NSWindow coreUIRenderer], drawRect, cgContext,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetWindowFrame", @"widget",
@"regularwin", @"windowtype",
(isMain ? @"normal" : @"inactive"), @"state",
[NSNumber numberWithInt:inBoxRect.size.height], @"kCUIWindowFrameBottomBarHeightKey",
[NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawBottomBarSeparatorKey",
[NSNumber numberWithBool:YES], @"is.flipped",
nil],
nil);
CGContextRestoreGState(cgContext);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -1921,12 +1888,12 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
// background
drawRect.origin.y += drawRect.size.height;
drawRect.size.height = macRect.size.height - 2.0f;
DrawNativeGreyColorInRect(cgContext, headerEndGrey, drawRect, isMain);
DrawNativeGreyColorInRect(cgContext, toolbarFillGrey, drawRect, isMain);
// bottom border
drawRect.origin.y += drawRect.size.height;
drawRect.size.height = 1.0f;
DrawNativeGreyColorInRect(cgContext, headerBorderGrey, drawRect, isMain);
DrawNativeGreyColorInRect(cgContext, toolbarBottomBorderGrey, drawRect, isMain);
}
break;

View File

@ -41,43 +41,35 @@
#include "nsToolkit.h"
#import <Cocoa/Cocoa.h>
extern "C" {
typedef CFTypeRef CUIRendererRef;
void CUIDraw(CUIRendererRef r, CGRect rect, CGContextRef ctx, CFDictionaryRef options, CFDictionaryRef* result);
}
@interface NSWindow(CoreUIRendererPrivate)
+ (CUIRendererRef)coreUIRenderer;
@end
enum ColorName {
headerStartGrey,
headerEndGrey,
headerBorderGrey,
toolbarTopBorderGrey,
statusbarFirstTopBorderGrey,
statusbarSecondTopBorderGrey,
statusbarGradientStartGrey,
statusbarGradientEndGrey
toolbarFillGrey,
toolbarBottomBorderGrey,
};
static const int sLeopardThemeColors[][2] = {
/* { active window, inactive window } */
// titlebar and toolbar:
{ 0xC5, 0xE9 }, // start grey
{ 0x96, 0xCA }, // end grey
{ 0x42, 0x89 }, // bottom separator line
// toolbar:
{ 0xC0, 0xE2 }, // top separator line
// statusbar:
{ 0x42, 0x86 }, // first top border
{ 0xD8, 0xEE }, // second top border
{ 0xBD, 0xE4 }, // gradient start
{ 0x96, 0xCF } // gradient end
{ 0x96, 0xCA }, // fill color
{ 0x42, 0x89 }, // bottom separator line
};
static const int sSnowLeopardThemeColors[][2] = {
/* { active window, inactive window } */
// titlebar and toolbar:
{ 0xD1, 0xEE }, // start grey
{ 0xA7, 0xD8 }, // end grey
{ 0x51, 0x99 }, // bottom separator line
// toolbar:
{ 0xD0, 0xF1 }, // top separator line
// statusbar:
{ 0x51, 0x99 }, // first top border
{ 0xE8, 0xF6 }, // second top border
{ 0xCB, 0xEA }, // gradient start
{ 0xA7, 0xDE } // gradient end
{ 0xA7, 0xD8 }, // fill color
{ 0x51, 0x99 }, // bottom separator line
};
__attribute__((unused))