1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Mike Pinkerton (pinkerton@netscape.com).
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
23 * Vladimir Vukicevic <vladimir@pobox.com> (HITheme rewrite)
24 * Josh Aas <josh@mozilla.com>
25 * Colin Barrett <cbarrett@mozilla.com>
26 * Matthew Gregan <kinetik@flim.org>
27 * Markus Stange <mstange@themasta.com>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either of the GNU General Public License Version 2 or later (the "GPL"),
31 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
43 #include "nsNativeThemeCocoa.h"
44 #include "nsObjCExceptions.h"
45 #include "nsIRenderingContext.h"
48 #include "nsThemeConstants.h"
49 #include "nsIPresShell.h"
50 #include "nsPresContext.h"
51 #include "nsIContent.h"
52 #include "nsIDocument.h"
55 #include "nsIEventStateManager.h"
56 #include "nsINameSpaceManager.h"
57 #include "nsPresContext.h"
58 #include "nsILookAndFeel.h"
59 #include "nsWidgetAtoms.h"
60 #include "nsToolkit.h"
61 #include "nsCocoaWindow.h"
62 #include "nsNativeThemeColors.h"
64 #include "gfxContext.h"
65 #include "gfxQuartzSurface.h"
66 #include "gfxQuartzNativeDrawing.h"
68 #define DRAW_IN_FRAME_DEBUG 0
69 #define SCROLLBARS_VISUAL_DEBUG 0
71 // private Quartz routines needed here
73 CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
76 // Workaround for NSCell control tint drawing
77 // Without this workaround, NSCells are always drawn with the clear control tint
78 // as long as they're not attached to an NSControl which is a subview of an active window.
79 // XXXmstange Why doesn't Webkit need this?
80 @implementation NSCell (ControlTintWorkaround)
81 - (int)_realControlTint { return [self controlTint]; }
84 // On 10.4, NSSearchFieldCells can't draw focus rings.
85 @interface SearchFieldCellWithFocusRing : NSSearchFieldCell {} @end
87 @implementation SearchFieldCellWithFocusRing
89 - (void) drawWithFrame:(NSRect)rect inView:(NSView*)controlView
91 [super drawWithFrame:rect inView:controlView];
92 if (!nsToolkit::OnLeopardOrLater() && [self showsFirstResponder]) {
93 NSSetFocusRingStyle(NSFocusRingOnly);
94 NSBezierPath* path = [NSBezierPath bezierPath];
95 float radius = NSHeight(rect) / 2;
96 rect = NSInsetRect(rect, radius, radius);
97 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMinY(rect)) radius:radius startAngle:180.0 endAngle:270.0];
98 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMinY(rect)) radius:radius startAngle:270.0 endAngle:360.0];
99 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMaxY(rect)) radius:radius startAngle: 0.0 endAngle: 90.0];
100 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMaxY(rect)) radius:radius startAngle: 90.0 endAngle:180.0];
108 // Copied from nsLookAndFeel.h
109 // Apple hasn't defined a constant for scollbars with two arrows on each end, so we'll use this one.
110 static const int kThemeScrollBarArrowsBoth = 2;
112 #define HITHEME_ORIENTATION kHIThemeOrientationNormal
113 #define MAX_FOCUS_RING_WIDTH 4
115 // These enums are for indexing into the margin array.
134 static int EnumSizeForCocoaSize(NSControlSize cocoaControlSize) {
135 if (cocoaControlSize == NSMiniControlSize)
136 return miniControlSize;
137 else if (cocoaControlSize == NSSmallControlSize)
138 return smallControlSize;
140 return regularControlSize;
143 static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, const float marginSet[][3][4])
147 static int osIndex = nsToolkit::OnLeopardOrLater() ? leopardOS : tigerOS;
148 int controlSize = EnumSizeForCocoaSize(cocoaControlSize);
149 const float* buttonMargins = marginSet[osIndex][controlSize];
150 rect->origin.x -= buttonMargins[leftMargin];
151 rect->origin.y -= buttonMargins[bottomMargin];
152 rect->size.width += buttonMargins[leftMargin] + buttonMargins[rightMargin];
153 rect->size.height += buttonMargins[bottomMargin] + buttonMargins[topMargin];
156 static NSView* NativeViewForFrame(nsIFrame* aFrame)
161 nsIWidget* widget = aFrame->GetWindow();
165 return (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
168 static NSWindow* NativeWindowForFrame(nsIFrame* aFrame, int* aLevelsUp = NULL,
169 nsIWidget** aTopLevelWidget = NULL)
174 nsIWidget* widget = aFrame->GetWindow();
178 nsIWidget* topLevelWidget = widget->GetTopLevelWidget(aLevelsUp);
180 *aTopLevelWidget = topLevelWidget;
182 return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
185 static BOOL FrameIsInActiveWindow(nsIFrame* aFrame)
187 nsIWidget* topLevelWidget = NULL;
188 NSWindow* win = NativeWindowForFrame(aFrame, NULL, &topLevelWidget);
189 if (!topLevelWidget || !win)
192 // XUL popups, e.g. the toolbar customization popup, can't become key windows,
193 // but controls in these windows should still get the active look.
194 nsWindowType windowType;
195 topLevelWidget->GetWindowType(windowType);
196 if (windowType == eWindowType_popup)
199 return [win isKeyWindow];
200 return [win isMainWindow] && ![win attachedSheet];
203 NS_IMPL_ISUPPORTS1(nsNativeThemeCocoa, nsITheme)
206 nsNativeThemeCocoa::nsNativeThemeCocoa()
208 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
210 mPushButtonCell = [[NSButtonCell alloc] initTextCell:nil];
211 [mPushButtonCell setButtonType:NSMomentaryPushInButton];
212 [mPushButtonCell setHighlightsBy:NSPushInCellMask];
214 mRadioButtonCell = [[NSButtonCell alloc] initTextCell:nil];
215 [mRadioButtonCell setButtonType:NSRadioButton];
217 mCheckboxCell = [[NSButtonCell alloc] initTextCell:nil];
218 [mCheckboxCell setButtonType:NSSwitchButton];
220 mSearchFieldCell = [[SearchFieldCellWithFocusRing alloc] initTextCell:@""];
221 [mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel];
222 [mSearchFieldCell setBezeled:YES];
223 [mSearchFieldCell setEditable:YES];
224 [mSearchFieldCell setFocusRingType:NSFocusRingTypeExterior];
226 NS_OBJC_END_TRY_ABORT_BLOCK;
229 nsNativeThemeCocoa::~nsNativeThemeCocoa()
231 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
233 [mPushButtonCell release];
234 [mRadioButtonCell release];
235 [mCheckboxCell release];
236 [mSearchFieldCell release];
238 NS_OBJC_END_TRY_ABORT_BLOCK;
241 // Limit on the area of the target rect (in pixels^2) in
242 // DrawCellWithScaling(), DrawButton() and DrawScrollbar(), above which we
243 // don't draw the object into a bitmap buffer. This is to avoid crashes in
244 // [NSGraphicsContext graphicsContextWithGraphicsPort:flipped:] and
245 // CGContextDrawImage(), and also to avoid very poor drawing performance in
246 // CGContextDrawImage() when it scales the bitmap (particularly if xscale or
247 // yscale is less than but near 1 -- e.g. 0.9). This value was determined
248 // by trial and error, on OS X 10.4.11 and 10.5.4, and on systems with
249 // different amounts of RAM.
250 #define BITMAP_MAX_AREA 500000
253 * Draw the given NSCell into the given cgContext.
255 * destRect - the size and position of the resulting control rectangle
256 * controlSize - the NSControlSize which will be given to the NSCell before
257 * asking it to render
258 * naturalSize - The natural dimensions of this control.
259 * If the control rect size is not equal to either of these, a scale
260 * will be applied to the context so that rendering the control at the
261 * natural size will result in it filling the destRect space.
262 * If a control has no natural dimensions in either/both axes, pass 0.0f.
263 * minimumSize - The minimum dimensions of this control.
264 * If the control rect size is less than the minimum for a given axis,
265 * a scale will be applied to the context so that the minimum is used
266 * for drawing. If a control has no minimum dimensions in either/both
268 * marginSet - an array of margins; a multidimensional array of [2][3][4],
269 * with the first dimension being the OS version (Tiger or Leopard),
270 * the second being the control size (mini, small, regular), and the third
271 * being the 4 margin values (left, top, right, bottom).
272 * flip - Whether to draw the control mirrored
273 * view - The NSView that we're drawing into. As far as I can tell, it doesn't
274 * matter if this is really the right view; it just has to return YES when
275 * asked for isFlipped. Otherwise we'll get drawing bugs on 10.4.
277 static void DrawCellWithScaling(NSCell *cell,
278 CGContextRef cgContext,
279 const HIRect& destRect,
280 NSControlSize controlSize,
283 const float marginSet[][3][4],
286 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
288 NSRect drawRect = NSMakeRect(destRect.origin.x, destRect.origin.y, destRect.size.width, destRect.size.height);
290 if (naturalSize.width != 0.0f)
291 drawRect.size.width = naturalSize.width;
292 if (naturalSize.height != 0.0f)
293 drawRect.size.height = naturalSize.height;
295 // Keep aspect ratio when scaling if one dimension is free.
296 if (naturalSize.width == 0.0f && naturalSize.height != 0.0f)
297 drawRect.size.width = destRect.size.width * naturalSize.height / destRect.size.height;
298 if (naturalSize.height == 0.0f && naturalSize.width != 0.0f)
299 drawRect.size.height = destRect.size.height * naturalSize.width / destRect.size.width;
301 // Honor minimum sizes.
302 if (drawRect.size.width < minimumSize.width)
303 drawRect.size.width = minimumSize.width;
304 if (drawRect.size.height < minimumSize.height)
305 drawRect.size.height = minimumSize.height;
307 [NSGraphicsContext saveGraphicsState];
309 // Only skip the buffer if the area of our cell (in pixels^2) is too large.
310 if (drawRect.size.width * drawRect.size.height > BITMAP_MAX_AREA) {
311 // Inflate the rect Gecko gave us by the margin for the control.
312 InflateControlRect(&drawRect, controlSize, marginSet);
314 NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
315 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]];
317 [cell drawWithFrame:drawRect inView:view];
319 [NSGraphicsContext setCurrentContext:savedContext];
322 float w = ceil(drawRect.size.width);
323 float h = ceil(drawRect.size.height);
324 NSRect tmpRect = NSMakeRect(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, w, h);
326 // inflate to figure out the frame we need to tell NSCell to draw in, to get something that's 0,0,w,h
327 InflateControlRect(&tmpRect, controlSize, marginSet);
329 // and then, expand by MAX_FOCUS_RING_WIDTH size to make sure we can capture any focus ring
330 w += MAX_FOCUS_RING_WIDTH * 2.0;
331 h += MAX_FOCUS_RING_WIDTH * 2.0;
333 CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
334 CGContextRef ctx = CGBitmapContextCreate(NULL,
337 rgb, kCGImageAlphaPremultipliedFirst);
338 CGColorSpaceRelease(rgb);
340 // We need to flip the image twice in order to avoid drawing bugs on 10.4, see bug 465069.
341 // This is the first flip transform, applied to cgContext.
342 CGContextScaleCTM(cgContext, 1.0f, -1.0f);
343 CGContextTranslateCTM(cgContext, 0.0f, -(2.0 * destRect.origin.y + destRect.size.height));
345 NSGraphicsContext* savedContext = [NSGraphicsContext currentContext];
346 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]];
348 // This is the second flip transform, applied to ctx.
349 CGContextScaleCTM(ctx, 1.0f, -1.0f);
350 CGContextTranslateCTM(ctx, 0.0f, -(2.0 * tmpRect.origin.y + tmpRect.size.height));
352 [cell drawWithFrame:tmpRect inView:view];
354 [NSGraphicsContext setCurrentContext:savedContext];
356 CGImageRef img = CGBitmapContextCreateImage(ctx);
358 // Drop the image into the original destination rectangle, scaling to fit
359 // Only scale MAX_FOCUS_RING_WIDTH by xscale/yscale when the resulting rect
360 // doesn't extend beyond the overflow rect
361 float xscale = destRect.size.width / drawRect.size.width;
362 float yscale = destRect.size.height / drawRect.size.height;
363 float scaledFocusRingX = xscale < 1.0f ? MAX_FOCUS_RING_WIDTH * xscale : MAX_FOCUS_RING_WIDTH;
364 float scaledFocusRingY = yscale < 1.0f ? MAX_FOCUS_RING_WIDTH * yscale : MAX_FOCUS_RING_WIDTH;
365 CGContextDrawImage(cgContext, CGRectMake(destRect.origin.x - scaledFocusRingX,
366 destRect.origin.y - scaledFocusRingY,
367 destRect.size.width + scaledFocusRingX * 2,
368 destRect.size.height + scaledFocusRingY * 2),
372 CGContextRelease(ctx);
375 [NSGraphicsContext restoreGraphicsState];
377 #if DRAW_IN_FRAME_DEBUG
378 CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
379 CGContextFillRect(cgContext, destRect);
382 NS_OBJC_END_TRY_ABORT_BLOCK;
385 struct CellRenderSettings {
386 // The natural dimensions of the control.
387 // If a control has no natural dimensions in either/both axes, set to 0.0f.
388 NSSize naturalSizes[3];
390 // The minimum dimensions of the control.
391 // If a control has no minimum dimensions in either/both axes, set to 0.0f.
392 NSSize minimumSizes[3];
394 // A multidimensional array of [2][3][4],
395 // with the first dimension being the OS version (Tiger or Leopard),
396 // the second being the control size (mini, small, regular), and the third
397 // being the 4 margin values (left, top, right, bottom).
398 float margins[2][3][4];
402 * Draw the given NSCell into the given cgContext with a nice control size.
404 * This function is similar to DrawCellWithScaling, but it decides what
405 * control size to use based on the destRect's size.
406 * Scaling is only applied when the difference between the destRect's size
407 * and the next smaller natural size is greater than sSnapTolerance. Otherwise
408 * it snaps to the next smaller control size without scaling because unscaled
409 * controls look nicer.
411 static const float sSnapTolerance = 2.0f;
412 static void DrawCellWithSnapping(NSCell *cell,
413 CGContextRef cgContext,
414 const HIRect& destRect,
415 const CellRenderSettings settings,
416 float verticalAlignFactor,
419 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
421 const float rectWidth = destRect.size.width, rectHeight = destRect.size.height;
422 const NSSize *sizes = settings.naturalSizes;
423 const NSSize miniSize = sizes[EnumSizeForCocoaSize(NSMiniControlSize)];
424 const NSSize smallSize = sizes[EnumSizeForCocoaSize(NSSmallControlSize)];
425 const NSSize regularSize = sizes[EnumSizeForCocoaSize(NSRegularControlSize)];
427 NSControlSize controlSizeX = NSRegularControlSize, controlSizeY = NSRegularControlSize;
428 HIRect drawRect = destRect;
430 if (rectWidth <= miniSize.width + sSnapTolerance && rectWidth < smallSize.width)
431 controlSizeX = NSMiniControlSize;
432 else if(rectWidth <= smallSize.width + sSnapTolerance && rectWidth < regularSize.width)
433 controlSizeX = NSSmallControlSize;
435 if (rectHeight <= miniSize.height + sSnapTolerance && rectHeight < smallSize.height)
436 controlSizeY = NSMiniControlSize;
437 else if(rectHeight <= smallSize.height + sSnapTolerance && rectHeight < regularSize.height)
438 controlSizeY = NSSmallControlSize;
440 NSControlSize controlSize = NSRegularControlSize;
443 // At some sizes, don't scale but snap.
444 const NSControlSize smallerControlSize =
445 EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ?
446 controlSizeX : controlSizeY;
447 const int smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize);
448 const NSSize size = sizes[smallerControlSizeIndex];
449 float diffWidth = size.width ? rectWidth - size.width : 0.0f;
450 float diffHeight = size.height ? rectHeight - size.height : 0.0f;
451 if (diffWidth >= 0.0f && diffHeight >= 0.0f &&
452 diffWidth <= sSnapTolerance && diffHeight <= sSnapTolerance) {
453 // Snap to the smaller control size.
454 controlSize = smallerControlSize;
455 sizeIndex = smallerControlSizeIndex;
456 // Resize and center the drawRect.
457 if (sizes[sizeIndex].width) {
458 drawRect.origin.x += ceil((destRect.size.width - sizes[sizeIndex].width) / 2);
459 drawRect.size.width = sizes[sizeIndex].width;
461 if (sizes[sizeIndex].height) {
462 drawRect.origin.y += floor((destRect.size.height - sizes[sizeIndex].height) * verticalAlignFactor);
463 drawRect.size.height = sizes[sizeIndex].height;
466 // Use the larger control size.
467 controlSize = EnumSizeForCocoaSize(controlSizeX) > EnumSizeForCocoaSize(controlSizeY) ?
468 controlSizeX : controlSizeY;
469 sizeIndex = EnumSizeForCocoaSize(controlSize);
472 [cell setControlSize:controlSize];
474 NSSize minimumSize = settings.minimumSizes ? settings.minimumSizes[sizeIndex] : NSZeroSize;
475 DrawCellWithScaling(cell, cgContext, drawRect, controlSize, sizes[sizeIndex],
476 minimumSize, settings.margins, view);
478 NS_OBJC_END_TRY_ABORT_BLOCK;
481 static float VerticalAlignFactor(nsIFrame *aFrame)
484 return 0.5f; // default: center
486 const nsStyleCoord& va = aFrame->GetStyleTextReset()->mVerticalAlign;
487 PRUint8 intval = (va.GetUnit() == eStyleUnit_Enumerated)
489 : NS_STYLE_VERTICAL_ALIGN_MIDDLE;
491 case NS_STYLE_VERTICAL_ALIGN_TOP:
492 case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
495 case NS_STYLE_VERTICAL_ALIGN_SUB:
496 case NS_STYLE_VERTICAL_ALIGN_SUPER:
497 case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
498 case NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE:
501 case NS_STYLE_VERTICAL_ALIGN_BASELINE:
502 case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
503 case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
507 NS_NOTREACHED("invalid vertical-align");
512 // These are the sizes that Gecko needs to request to draw if it wants
513 // to get a standard-sized Aqua radio button drawn. Note that the rects
514 // that draw these are actually a little bigger.
515 static const CellRenderSettings radioSettings = {
517 NSMakeSize(11, 11), // mini
518 NSMakeSize(13, 13), // small
519 NSMakeSize(16, 16) // regular
522 NSZeroSize, NSZeroSize, NSZeroSize
526 {0, 0, 0, 0}, // mini
527 {0, 2, 1, 1}, // small
528 {0, 1, 0, -1} // regular
531 {0, 0, 0, 0}, // mini
532 {0, 1, 1, 1}, // small
533 {0, 0, 0, 0} // regular
538 static const CellRenderSettings checkboxSettings = {
540 NSMakeSize(11, 11), // mini
541 NSMakeSize(13, 13), // small
542 NSMakeSize(16, 16) // regular
545 NSZeroSize, NSZeroSize, NSZeroSize
549 {0, 1, 0, 0}, // mini
550 {0, 2, 0, 1}, // small
551 {0, 1, 0, 1} // regular
554 {0, 1, 0, 0}, // mini
555 {0, 1, 0, 1}, // small
556 {0, 1, 0, 1} // regular
562 nsNativeThemeCocoa::DrawCheckboxOrRadio(CGContextRef cgContext, PRBool inCheckbox,
563 const HIRect& inBoxRect, PRBool inSelected,
564 PRBool inDisabled, PRInt32 inState,
567 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
569 NSButtonCell *cell = inCheckbox ? mCheckboxCell : mRadioButtonCell;
571 [cell setEnabled:!inDisabled];
572 [cell setShowsFirstResponder:(inState & NS_EVENT_STATE_FOCUS)];
573 [cell setState:(inSelected ? NSOnState : NSOffState)];
574 [cell setHighlighted:((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))];
575 [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)];
577 // Ensure that the control is square.
578 float length = PR_MIN(inBoxRect.size.width, inBoxRect.size.height);
579 HIRect drawRect = CGRectMake(inBoxRect.origin.x + (int)((inBoxRect.size.width - length) / 2.0f),
580 inBoxRect.origin.y + (int)((inBoxRect.size.height - length) / 2.0f),
583 DrawCellWithSnapping(cell, cgContext, drawRect,
584 inCheckbox ? checkboxSettings : radioSettings,
585 VerticalAlignFactor(aFrame),
586 NativeViewForFrame(aFrame));
588 NS_OBJC_END_TRY_ABORT_BLOCK;
591 static const CellRenderSettings searchFieldSettings = {
593 NSMakeSize(0, 16), // mini
594 NSMakeSize(0, 19), // small
595 NSMakeSize(0, 22) // regular
598 NSMakeSize(32, 0), // mini
599 NSMakeSize(38, 0), // small
600 NSMakeSize(44, 0) // regular
604 {0, 0, 0, 0}, // mini
605 {0, 0, 0, 0}, // small
606 {0, 0, 0, 0} // regular
609 {0, 0, 0, 0}, // mini
610 {0, 0, 0, 0}, // small
611 {0, 0, 0, 0} // regular
617 nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
620 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
622 NSSearchFieldCell* cell = mSearchFieldCell;
623 [cell setEnabled:!IsDisabled(aFrame)];
624 [cell setShowsFirstResponder:IsFocused(aFrame)];
626 DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings,
627 VerticalAlignFactor(aFrame), NativeViewForFrame(aFrame));
629 NS_OBJC_END_TRY_ABORT_BLOCK;
633 // These are the sizes that Gecko needs to request to draw if it wants
634 // to get a standard-sized Aqua rounded bevel button drawn. Note that
635 // the rects that draw these are actually a little bigger.
636 #define NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH 18
637 #define NATURAL_MINI_ROUNDED_BUTTON_HEIGHT 16
638 #define NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH 26
639 #define NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT 19
640 #define NATURAL_REGULAR_ROUNDED_BUTTON_MIN_WIDTH 30
641 #define NATURAL_REGULAR_ROUNDED_BUTTON_HEIGHT 22
643 // These were calculated by testing all three sizes on the respective operating system.
644 static const float pushButtonMargins[2][3][4] =
647 {1, 1, 1, 1}, // mini
648 {5, 1, 5, 1}, // small
649 {6, 0, 6, 2} // regular
652 {0, 0, 0, 0}, // mini
653 {4, 0, 4, 1}, // small
654 {5, 0, 5, 2} // regular
658 // The height at which we start doing square buttons instead of rounded buttons
659 // Rounded buttons look bad if drawn at a height greater than 26, so at that point
660 // we switch over to doing square buttons which looks fine at any size.
661 #define DO_SQUARE_BUTTON_HEIGHT 26
664 nsNativeThemeCocoa::DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, PRBool inIsDefault,
665 PRBool inDisabled, PRInt32 inState, nsIFrame* aFrame)
667 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
669 NSRect drawRect = NSMakeRect(inBoxRect.origin.x, inBoxRect.origin.y, inBoxRect.size.width, inBoxRect.size.height);
671 BOOL isActive = FrameIsInActiveWindow(aFrame);
673 [mPushButtonCell setEnabled:!inDisabled];
674 [mPushButtonCell setHighlighted:(((inState & NS_EVENT_STATE_ACTIVE) &&
675 (inState & NS_EVENT_STATE_HOVER) ||
676 (inIsDefault && !inDisabled)) &&
678 [mPushButtonCell setShowsFirstResponder:(inState & NS_EVENT_STATE_FOCUS) && !inDisabled && isActive];
680 // If the button is tall enough, draw the square button style so that buttons with
681 // non-standard content look good. Otherwise draw normal rounded aqua buttons.
682 if (drawRect.size.height > DO_SQUARE_BUTTON_HEIGHT) {
683 [mPushButtonCell setBezelStyle:NSShadowlessSquareBezelStyle];
684 DrawCellWithScaling(mPushButtonCell, cgContext, inBoxRect, NSRegularControlSize,
685 NSZeroSize, NSMakeSize(14, 0), NULL, NativeViewForFrame(aFrame));
687 [mPushButtonCell setBezelStyle:NSRoundedBezelStyle];
689 // Figure out what size cell control we're going to draw and grab its
690 // natural height and min width.
691 NSControlSize controlSize = NSRegularControlSize;
692 float naturalHeight = NATURAL_REGULAR_ROUNDED_BUTTON_HEIGHT;
693 float minWidth = NATURAL_REGULAR_ROUNDED_BUTTON_MIN_WIDTH;
694 if (drawRect.size.height <= NATURAL_MINI_ROUNDED_BUTTON_HEIGHT &&
695 drawRect.size.width >= NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH) {
696 controlSize = NSMiniControlSize;
697 naturalHeight = NATURAL_MINI_ROUNDED_BUTTON_HEIGHT;
698 minWidth = NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH;
700 else if (drawRect.size.height <= NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT &&
701 drawRect.size.width >= NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH) {
702 controlSize = NSSmallControlSize;
703 naturalHeight = NATURAL_SMALL_ROUNDED_BUTTON_HEIGHT;
704 minWidth = NATURAL_SMALL_ROUNDED_BUTTON_MIN_WIDTH;
706 [mPushButtonCell setControlSize:controlSize];
708 DrawCellWithScaling(mPushButtonCell, cgContext, inBoxRect, controlSize,
709 NSMakeSize(0.0f, naturalHeight),
710 NSMakeSize(minWidth, 0.0f), pushButtonMargins,
711 NativeViewForFrame(aFrame));
714 #if DRAW_IN_FRAME_DEBUG
715 CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
716 CGContextFillRect(cgContext, inBoxRect);
719 NS_OBJC_END_TRY_ABORT_BLOCK;
724 nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind,
725 const HIRect& inBoxRect, PRBool inIsDefault, PRBool inDisabled,
726 ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
727 PRInt32 inState, nsIFrame* aFrame)
729 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
731 BOOL isActive = FrameIsInActiveWindow(aFrame);
733 HIThemeButtonDrawInfo bdi;
737 bdi.adornment = inAdornment;
740 bdi.state = kThemeStateUnavailable;
742 else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER)) {
743 bdi.state = kThemeStatePressed;
746 if (inKind == kThemeArrowButton)
747 bdi.state = kThemeStateUnavailable; // these are always drawn as unavailable
748 else if (!isActive && (inKind == kThemeListHeaderButton || inKind == kThemePopupButton))
749 bdi.state = kThemeStateInactive;
751 bdi.state = kThemeStateActive;
754 if (inState & NS_EVENT_STATE_FOCUS && isActive)
755 bdi.adornment |= kThemeAdornmentFocus;
757 if (inIsDefault && !inDisabled)
758 bdi.adornment |= kThemeAdornmentDefault;
760 HIRect drawFrame = inBoxRect;
761 PRBool needsScaling = PR_FALSE;
762 int drawWidth = 0, drawHeight = 0;
764 if (inKind == kThemePopupButton) {
765 /* popup buttons draw outside their frame by 1 pixel on each side and
766 * two on the bottom but of the bottom two pixels one is a 'shadow'
767 * and not the frame itself. That extra pixel should be handled
768 * by GetWidgetOverflow, but we already extend each widget's overflow
769 * by 4px to handle a potential focus ring.
772 if (nsToolkit::OnLeopardOrLater()) {
773 /* Leopard will happily scale up for buttons that are sized 20px or higher,
774 * drawing 1px below the actual requested area. (So 20px == 21px.)
775 * but anything below that will be clamped:
776 * requested: 20 actual: 21 (handled above)
777 * requested: 19 actual: 18 <- note that there is no way to draw a dropdown that's exactly 20 px in size
778 * requested: 18 actual: 18
779 * requested: 17 actual: 18
780 * requested: 16 actual: 15 (min size)
781 * For those, draw to a buffer and scale
783 if (drawFrame.size.height != 18 && drawFrame.size.height != 15) {
784 if (drawFrame.size.height > 20) {
785 drawFrame.size.width -= 2;
786 drawFrame.origin.x += 1;
787 drawFrame.size.height -= 1;
790 // pick which native height to use for the small scale
791 float nativeHeight = 15.0f;
792 if (drawFrame.size.height > 16)
793 nativeHeight = 18.0f;
795 drawWidth = (int) drawFrame.size.width;
796 drawHeight = (int) nativeHeight;
798 needsScaling = PR_TRUE;
803 // leave things alone on Tiger
804 drawFrame.size.height -= 1;
806 } else if (inKind == kThemeListHeaderButton) {
807 CGContextClipToRect(cgContext, inBoxRect);
808 // Always remove the top border.
809 drawFrame.origin.y -= 1;
810 drawFrame.size.height += 1;
811 // Remove the left border in LTR mode and the right border in RTL mode.
812 drawFrame.size.width += 1;
813 PRBool isLast = IsLastTreeHeaderCell(aFrame);
815 drawFrame.size.width += 1; // Also remove the other border.
816 if (!IsFrameRTL(aFrame) || isLast)
817 drawFrame.origin.x -= 1;
820 // Fall back to no bitmap buffer (and no scaling) if the area of our button
821 // (in pixels^2) is too large.
822 if (!needsScaling || (drawWidth * drawHeight > BITMAP_MAX_AREA)) {
823 HIThemeDrawButton(&drawFrame, &bdi, cgContext, kHIThemeOrientationNormal, NULL);
825 int w = drawWidth + MAX_FOCUS_RING_WIDTH*2;
826 int h = drawHeight + MAX_FOCUS_RING_WIDTH*2;
828 CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
829 CGContextRef ctx = CGBitmapContextCreate(NULL, w, h, 8, w * 4,
830 rgb, kCGImageAlphaPremultipliedFirst);
831 CGColorSpaceRelease(rgb);
834 CGContextTranslateCTM(ctx, 0.0f, h);
835 CGContextScaleCTM(ctx, 1.0f, -1.0f);
837 // then draw the button (offset by the focus ring size
838 CGRect tmpFrame = CGRectMake(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, drawWidth, drawHeight);
839 HIThemeDrawButton(&tmpFrame, &bdi, ctx, kHIThemeOrientationNormal, NULL);
841 CGImageRef img = CGBitmapContextCreateImage(ctx);
842 CGRect imgRect = CGRectMake(drawFrame.origin.x - MAX_FOCUS_RING_WIDTH,
843 drawFrame.origin.y - MAX_FOCUS_RING_WIDTH,
844 drawFrame.size.width + MAX_FOCUS_RING_WIDTH * 2.0,
845 drawFrame.size.height + MAX_FOCUS_RING_WIDTH * 2.0);
847 // And then flip the main context here so that the image gets drawn right-side up
848 CGAffineTransform ctm = CGContextGetCTM (cgContext);
850 CGContextTranslateCTM (cgContext, imgRect.origin.x, imgRect.origin.y + imgRect.size.height);
851 CGContextScaleCTM (cgContext, 1.0, -1.0);
853 imgRect.origin.x = imgRect.origin.y = 0.0f;
855 // See comment about why we don't scale MAX_FOCUS_RING in DrawCellWithScaling
856 CGContextDrawImage(cgContext, imgRect, img);
858 CGContextSetCTM (cgContext, ctm);
861 CGContextRelease(ctx);
864 #if DRAW_IN_FRAME_DEBUG
865 CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
866 CGContextFillRect(cgContext, inBoxRect);
869 NS_OBJC_END_TRY_ABORT_BLOCK;
874 nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
875 const HIRect& inBoxRect, PRBool inDisabled,
876 ThemeDrawState inDrawState,
877 ThemeButtonAdornment inAdornment,
878 PRInt32 inState, nsIFrame* aFrame)
880 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
882 HIThemeButtonDrawInfo bdi;
885 bdi.value = kThemeButtonOff;
886 bdi.adornment = inAdornment;
889 bdi.state = kThemeStateUnavailable;
891 bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive;
893 HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL);
895 NS_OBJC_END_TRY_ABORT_BLOCK;
900 nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind,
901 const HIRect& inBoxRect, PRBool inIsDisabled, PRInt32 inState)
903 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
905 HIThemeFrameDrawInfo fdi;
909 // We don't ever set an inactive state for this because it doesn't
910 // look right (see other apps).
911 fdi.state = inIsDisabled ? kThemeStateUnavailable : kThemeStateActive;
913 // for some reason focus rings on listboxes draw incorrectly
914 if (inKind == kHIThemeFrameListBox)
917 fdi.isFocused = (inState & NS_EVENT_STATE_FOCUS) != 0;
919 // HIThemeDrawFrame takes the rect for the content area of the frame, not
920 // the bounding rect for the frame. Here we reduce the size of the rect we
921 // will pass to make it the size of the content.
922 HIRect drawRect = inBoxRect;
923 if (inKind == kHIThemeFrameTextFieldSquare) {
924 SInt32 frameOutset = 0;
925 ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
926 drawRect.origin.x += frameOutset;
927 drawRect.origin.y += frameOutset;
928 drawRect.size.width -= frameOutset * 2;
929 drawRect.size.height -= frameOutset * 2;
931 else if (inKind == kHIThemeFrameListBox) {
932 SInt32 frameOutset = 0;
933 ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
934 drawRect.origin.x += frameOutset;
935 drawRect.origin.y += frameOutset;
936 drawRect.size.width -= frameOutset * 2;
937 drawRect.size.height -= frameOutset * 2;
940 #if DRAW_IN_FRAME_DEBUG
941 CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
942 CGContextFillRect(cgContext, inBoxRect);
945 HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION);
947 NS_OBJC_END_TRY_ABORT_BLOCK;
952 nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect,
953 PRBool inIsIndeterminate, PRBool inIsHorizontal,
954 PRInt32 inValue, PRInt32 inMaxValue,
957 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
959 HIThemeTrackDrawInfo tdi;
961 PRInt32 stepsPerSecond = inIsIndeterminate ? 60 : 30;
962 PRInt32 milliSecondsPerStep = 1000 / stepsPerSecond;
965 tdi.kind = inIsIndeterminate ? kThemeMediumIndeterminateBar: kThemeMediumProgressBar;
966 tdi.bounds = inBoxRect;
968 tdi.max = inMaxValue;
970 tdi.attributes = inIsHorizontal ? kThemeTrackHorizontal : 0;
971 tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
972 tdi.trackInfo.progress.phase = PR_IntervalToMilliseconds(PR_IntervalNow()) /
973 milliSecondsPerStep % 16;
975 HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
977 NS_OBJC_END_TRY_ABORT_BLOCK;
982 nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect,
985 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
987 HIThemeTabPaneDrawInfo tpdi;
990 tpdi.state = FrameIsInActiveWindow(aFrame) ? kThemeStateActive : kThemeStateInactive;
991 tpdi.direction = kThemeTabNorth;
992 tpdi.size = kHIThemeTabSizeNormal;
993 tpdi.kind = kHIThemeTabKindNormal;
995 HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION);
997 NS_OBJC_END_TRY_ABORT_BLOCK;
1002 nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect,
1003 PRBool inIsDisabled, PRInt32 inState,
1004 PRBool inIsVertical, PRBool inIsReverse,
1005 PRInt32 inCurrentValue, PRInt32 inMinValue,
1006 PRInt32 inMaxValue, nsIFrame* aFrame)
1008 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
1010 HIThemeTrackDrawInfo tdi;
1013 tdi.kind = kThemeMediumSlider;
1014 tdi.bounds = inBoxRect;
1015 tdi.min = inMinValue;
1016 tdi.max = inMaxValue;
1017 tdi.value = inCurrentValue;
1018 tdi.attributes = kThemeTrackShowThumb;
1020 tdi.attributes |= kThemeTrackHorizontal;
1022 tdi.attributes |= kThemeTrackRightToLeft;
1023 if (inState & NS_EVENT_STATE_FOCUS)
1024 tdi.attributes |= kThemeTrackHasFocus;
1026 tdi.enableState = kThemeTrackDisabled;
1028 tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
1029 tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
1030 tdi.trackInfo.slider.pressState = 0;
1032 HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION);
1034 NS_OBJC_END_TRY_ABORT_BLOCK;
1038 #define NATURAL_MINI_TAB_BUTTON_HEIGHT 17
1039 #define NATURAL_SMALL_TAB_BUTTON_HEIGHT 20
1040 #define NATURAL_REGULAR_TAB_BUTTON_HEIGHT 23
1044 nsNativeThemeCocoa::DrawTab(CGContextRef cgContext, HIRect inBoxRect,
1045 PRInt32 inState, nsIFrame* aFrame)
1047 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
1049 HIThemeTabDrawInfo tdi;
1052 PRBool isSelected = IsSelectedTab(aFrame);
1053 PRBool isDisabled = IsDisabled(aFrame);
1056 tdi.style = kThemeTabFrontUnavailable;
1058 tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabFront : kThemeTabFrontInactive;
1061 tdi.style = kThemeTabNonFrontUnavailable;
1062 else if ((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))
1063 tdi.style = kThemeTabNonFrontPressed;
1065 tdi.style = FrameIsInActiveWindow(aFrame) ? kThemeTabNonFront : kThemeTabNonFrontInactive;
1068 tdi.direction = kThemeTabNorth;
1069 tdi.size = kHIThemeTabSizeNormal;
1070 if (inBoxRect.size.height < NATURAL_REGULAR_TAB_BUTTON_HEIGHT)
1071 tdi.size = kHIThemeTabSizeSmall;
1072 if (inBoxRect.size.height < NATURAL_SMALL_TAB_BUTTON_HEIGHT)
1073 tdi.size = kHIThemeTabSizeMini;
1075 PRBool isRTL = IsFrameRTL(aFrame);
1076 PRBool isFirst = isRTL ? IsLastTab(aFrame) : IsFirstTab(aFrame);
1077 PRBool isLast = isRTL ? IsFirstTab(aFrame) : IsLastTab(aFrame);
1079 if (isFirst && isLast)
1080 tdi.position = kHIThemeTabPositionOnly;
1082 tdi.position = kHIThemeTabPositionFirst;
1084 tdi.position = kHIThemeTabPositionLast;
1086 tdi.position = kHIThemeTabPositionMiddle;
1088 // Tab separator management:
1089 // Normal tabs only draw their left separator, in the leftmost pixel row of
1090 // their frame. Selected tabs additionally draw their right separator, outside
1091 // of their frame. To prevent overlapping, the tab to the right of the
1092 // selected tab shouldn't draw its left separator.
1093 tdi.adornment = kHIThemeTabAdornmentNone;
1094 if (isRTL ? IsBeforeSelectedTab(aFrame) : IsAfterSelectedTab(aFrame)) {
1095 if (nsToolkit::OnLeopardOrLater()) {
1096 // On Leopard, the tab's left edge must be shifted 1px to the right.
1097 // On Tiger, this happens automatically when no leading separator is drawn.
1098 inBoxRect.origin.x += 1;
1099 inBoxRect.size.width -= 1;
1103 tdi.adornment = kHIThemeTabAdornmentLeadingSeparator;
1106 if (isSelected && !isLast) {
1107 tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;
1108 if (nsToolkit::OnLeopardOrLater()) {
1109 // On Tiger, the right separator is drawn outside of the frame.
1110 // On Leopard, the right edge must be shifted 1px to the right.
1111 inBoxRect.size.width += 1;
1115 if (inState & NS_EVENT_STATE_FOCUS)
1116 tdi.adornment |= kThemeAdornmentFocus;
1118 HIThemeDrawTab(&inBoxRect, &tdi, cgContext, HITHEME_ORIENTATION, NULL);
1120 NS_OBJC_END_TRY_ABORT_BLOCK;
1125 ConvertToPressState(PRInt32 aButtonState, UInt8 aPressState)
1127 // If the button is pressed, return the press state passed in. Otherwise, return 0.
1128 return ((aButtonState & NS_EVENT_STATE_ACTIVE) && (aButtonState & NS_EVENT_STATE_HOVER)) ? aPressState : 0;
1133 nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame *aFrame, PRInt32 aButtonStates[])
1135 static nsIContent::AttrValuesArray attributeValues[] = {
1136 &nsWidgetAtoms::scrollbarUpTop,
1137 &nsWidgetAtoms::scrollbarDownTop,
1138 &nsWidgetAtoms::scrollbarUpBottom,
1139 &nsWidgetAtoms::scrollbarDownBottom,
1143 // Get the state of any scrollbar buttons in our child frames
1144 for (nsIFrame *childFrame = aFrame->GetFirstChild(nsnull);
1146 childFrame = childFrame->GetNextSibling()) {
1148 nsIContent *childContent = childFrame->GetContent();
1149 if (!childContent) continue;
1150 PRInt32 attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsWidgetAtoms::sbattr,
1151 attributeValues, eCaseMatters);
1152 if (attrIndex < 0) continue;
1154 PRInt32 currentState = GetContentState(childFrame, NS_THEME_BUTTON);
1155 aButtonStates[attrIndex] = currentState;
1160 // Both of the following sets of numbers were derived by loading the testcase in
1161 // bmo bug 380185 in Safari and observing its behavior for various heights of scrollbar.
1162 // These magic numbers are the minimum sizes we can draw a scrollbar and still
1163 // have room for everything to display, including the thumb
1164 #define MIN_SCROLLBAR_SIZE_WITH_THUMB 61
1165 #define MIN_SMALL_SCROLLBAR_SIZE_WITH_THUMB 49
1166 // And these are the minimum sizes if we don't draw the thumb
1167 #define MIN_SCROLLBAR_SIZE 56
1168 #define MIN_SMALL_SCROLLBAR_SIZE 46
1171 nsNativeThemeCocoa::GetScrollbarDrawInfo(HIThemeTrackDrawInfo& aTdi, nsIFrame *aFrame,
1172 const HIRect& aRect, PRBool aShouldGetButtonStates)
1174 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
1176 PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos, 0);
1177 PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos, 0);
1178 PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos, 100);
1179 PRInt32 thumbSize = CheckIntAttr(aFrame, nsWidgetAtoms::pageincrement, 10);
1181 PRBool isHorizontal = aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::orient,
1182 nsWidgetAtoms::horizontal, eCaseMatters);
1183 PRBool isSmall = aFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL;
1186 aTdi.kind = isSmall ? kThemeSmallScrollBar : kThemeMediumScrollBar;
1187 aTdi.bounds = aRect;
1190 aTdi.value = curpos;
1191 aTdi.attributes = 0;
1192 aTdi.enableState = kThemeTrackActive;
1194 aTdi.attributes |= kThemeTrackHorizontal;
1196 aTdi.trackInfo.scrollbar.viewsize = (SInt32)thumbSize;
1198 // This should be done early on so things like "kThemeTrackNothingToScroll" can
1199 // override the active enable state.
1200 aTdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive;
1202 /* Only display features if we have enough room for them.
1203 * Gecko still maintains the scrollbar info; this is just a visual issue (bug 380185).
1205 PRInt32 longSideLength = (PRInt32)(isHorizontal ? (aRect.size.width) : (aRect.size.height));
1206 if (longSideLength >= (isSmall ? MIN_SMALL_SCROLLBAR_SIZE_WITH_THUMB : MIN_SCROLLBAR_SIZE_WITH_THUMB)) {
1207 aTdi.attributes |= kThemeTrackShowThumb;
1209 else if (longSideLength < (isSmall ? MIN_SMALL_SCROLLBAR_SIZE : MIN_SCROLLBAR_SIZE)) {
1210 aTdi.enableState = kThemeTrackNothingToScroll;
1214 // Only go get these scrollbar button states if we need it. For example, there's no reaon to look up scrollbar button
1215 // states when we're only creating a TrackDrawInfo to determine the size of the thumb.
1216 if (aShouldGetButtonStates) {
1217 PRInt32 buttonStates[] = {0, 0, 0, 0};
1218 GetScrollbarPressStates(aFrame, buttonStates);
1219 ThemeScrollBarArrowStyle arrowStyle;
1220 ::GetThemeScrollBarArrowStyle(&arrowStyle);
1221 // If all four buttons are visible
1222 if (arrowStyle == kThemeScrollBarArrowsBoth) {
1223 aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
1224 ConvertToPressState(buttonStates[1], kThemeTopInsideArrowPressed) |
1225 ConvertToPressState(buttonStates[2], kThemeBottomInsideArrowPressed) |
1226 ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
1228 // It seems that unless all four buttons are showing, kThemeTopOutsideArrowPressed is the correct constant for
1229 // the up scrollbar button.
1230 aTdi.trackInfo.scrollbar.pressState = ConvertToPressState(buttonStates[0], kThemeTopOutsideArrowPressed) |
1231 ConvertToPressState(buttonStates[1], kThemeBottomOutsideArrowPressed) |
1232 ConvertToPressState(buttonStates[2], kThemeTopOutsideArrowPressed) |
1233 ConvertToPressState(buttonStates[3], kThemeBottomOutsideArrowPressed);
1237 NS_OBJC_END_TRY_ABORT_BLOCK;
1242 nsNativeThemeCocoa::DrawScrollbar(CGContextRef aCGContext, const HIRect& aBoxRect, nsIFrame *aFrame)
1244 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
1246 // HIThemeDrawTrack is buggy with rotations and scaling
1247 CGAffineTransform savedCTM = CGContextGetCTM(aCGContext);
1249 HIRect drawRect = aBoxRect;
1251 if (savedCTM.a == 1.0f && savedCTM.b == 0.0f &&
1252 savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f))
1256 drawRect.origin.x = drawRect.origin.y = 0.0f;
1260 HIThemeTrackDrawInfo tdi;
1261 GetScrollbarDrawInfo(tdi, aFrame, drawRect, PR_TRUE); //True means we want the press states
1263 // Fall back to no bitmap buffer if the area of our scrollbar (in pixels^2)
1265 if (drawDirect || (aBoxRect.size.width * aBoxRect.size.height > BITMAP_MAX_AREA)) {
1266 ::HIThemeDrawTrack(&tdi, NULL, aCGContext, HITHEME_ORIENTATION);
1268 // Note that NSScroller can draw transformed just fine, but HITheme can't.
1269 // However, we can't make NSScroller's parts light up easily (depressed buttons, etc.)
1270 // This is very frustrating.
1272 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1273 CGContextRef bitmapctx = CGBitmapContextCreate(NULL,
1274 (size_t) ceil(drawRect.size.width),
1275 (size_t) ceil(drawRect.size.height),
1277 (size_t) ceil(drawRect.size.width) * 4,
1279 kCGImageAlphaPremultipliedFirst);
1280 CGColorSpaceRelease(colorSpace);
1282 // HITheme always wants to draw into a flipped context, or things
1284 CGContextTranslateCTM(bitmapctx, 0.0f, aBoxRect.size.height);
1285 CGContextScaleCTM(bitmapctx, 1.0f, -1.0f);
1287 HIThemeDrawTrack(&tdi, NULL, bitmapctx, HITHEME_ORIENTATION);
1289 CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx);
1291 CGAffineTransform ctm = CGContextGetCTM(aCGContext);
1293 // We need to unflip, so that we can do a DrawImage without getting a flipped image.
1294 CGContextTranslateCTM(aCGContext, 0.0f, aBoxRect.size.height);
1295 CGContextScaleCTM(aCGContext, 1.0f, -1.0f);
1297 CGContextDrawImage(aCGContext, aBoxRect, bitmap);
1299 CGContextSetCTM(aCGContext, ctm);
1301 CGImageRelease(bitmap);
1302 CGContextRelease(bitmapctx);
1305 NS_OBJC_END_TRY_ABORT_BLOCK;
1310 nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame)
1312 // Walk our parents to find a scrollbar frame
1313 nsIFrame *scrollbarFrame = aFrame;
1315 if (scrollbarFrame->GetType() == nsWidgetAtoms::scrollbarFrame) break;
1316 } while ((scrollbarFrame = scrollbarFrame->GetParent()));
1318 // We return null if we can't find a parent scrollbar frame
1319 return scrollbarFrame;
1324 nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
1327 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
1329 float titlebarHeight = 0;
1331 NSWindow* win = NativeWindowForFrame(aFrame, &levelsUp);
1333 // If the toolbar is directly below the titlebar in the top level view of a ToolbarWindow
1334 if ([win isKindOfClass:[ToolbarWindow class]] && levelsUp == 0 &&
1335 inBoxRect.origin.y <= 0) {
1336 // Consider the titlebar height when calculating the gradient.
1337 titlebarHeight = [(ToolbarWindow*)win titlebarHeight];
1338 // Notify the window about the toolbar's height so that it can draw the
1339 // correct gradient in the titlebar.
1340 [(ToolbarWindow*)win setUnifiedToolbarHeight:inBoxRect.size.height];
1343 BOOL isMain = win ? [win isMainWindow] : YES;
1345 // Draw the gradient
1346 UnifiedGradientInfo info = { titlebarHeight, inBoxRect.size.height, isMain, NO };
1347 struct CGFunctionCallbacks callbacks = { 0, nsCocoaWindow::UnifiedShading, NULL };
1348 CGFunctionRef function = CGFunctionCreate(&info, 1, NULL, 4, NULL, &callbacks);
1349 float srcY = inBoxRect.origin.y;
1350 float dstY = srcY + inBoxRect.size.height - 1;
1351 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
1352 CGShadingRef shading = CGShadingCreateAxial(colorSpace,
1353 CGPointMake(0, srcY),
1354 CGPointMake(0, dstY), function,
1356 CGColorSpaceRelease(colorSpace);
1357 CGFunctionRelease(function);
1358 CGContextClipToRect(cgContext, inBoxRect);
1359 CGContextDrawShading(cgContext, shading);
1360 CGShadingRelease(shading);
1362 // Draw the border at the bottom of the toolbar.
1363 [NativeGreyColorAsNSColor(headerBorderGrey, isMain) set];
1364 NSRectFill(NSMakeRect(inBoxRect.origin.x, inBoxRect.origin.y +
1365 inBoxRect.size.height - 1.0f, inBoxRect.size.width, 1.0f));
1367 NS_OBJC_END_TRY_ABORT_BLOCK;
1372 nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
1373 PRUint8 aWidgetType, const nsRect& aRect,
1374 const nsRect& aDirtyRect)
1376 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
1378 // setup to draw into the correct port
1379 nsCOMPtr<nsIDeviceContext> dctx;
1380 aContext->GetDeviceContext(*getter_AddRefs(dctx));
1381 PRInt32 p2a = dctx->AppUnitsPerDevPixel();
1383 gfxRect nativeDirtyRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
1384 gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
1385 nativeWidgetRect.ScaleInverse(gfxFloat(p2a));
1386 nativeDirtyRect.ScaleInverse(gfxFloat(p2a));
1387 nativeWidgetRect.Round();
1388 if (nativeWidgetRect.IsEmpty())
1389 return NS_OK; // Don't attempt to draw invisible widgets.
1391 nsRefPtr<gfxContext> thebesCtx = aContext->ThebesContext();
1393 return NS_ERROR_FAILURE;
1395 gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeDirtyRect);
1397 CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
1398 if (cgContext == nsnull) {
1399 // The Quartz surface handles 0x0 surfaces by internally
1400 // making all operations no-ops; there's no cgcontext created for them.
1401 // Unfortunately, this means that callers that want to render
1402 // directly to the CGContext need to be aware of this quirk.
1407 if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) {
1408 fprintf(stderr, "Native theme drawing widget %d [%p] dis:%d in rect [%d %d %d %d]\n",
1409 aWidgetType, aFrame, IsDisabled(aFrame), aRect.x, aRect.y, aRect.width, aRect.height);
1410 fprintf(stderr, "Cairo matrix: [%f %f %f %f %f %f]\n",
1411 mat.xx, mat.yx, mat.xy, mat.yy, mat.x0, mat.y0);
1412 fprintf(stderr, "Native theme xform[0]: [%f %f %f %f %f %f]\n",
1413 mm0.a, mm0.b, mm0.c, mm0.d, mm0.tx, mm0.ty);
1414 CGAffineTransform mm = CGContextGetCTM(cgContext);
1415 fprintf(stderr, "Native theme xform[1]: [%f %f %f %f %f %f]\n",
1416 mm.a, mm.b, mm.c, mm.d, mm.tx, mm.ty);
1420 CGRect macRect = CGRectMake(nativeWidgetRect.X(), nativeWidgetRect.Y(),
1421 nativeWidgetRect.Width(), nativeWidgetRect.Height());
1424 fprintf(stderr, " --> macRect %f %f %f %f\n",
1425 macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height);
1426 CGRect bounds = CGContextGetClipBoundingBox(cgContext);
1427 fprintf(stderr, " --> clip bounds: %f %f %f %f\n",
1428 bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
1430 //CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1);
1431 //CGContextFillRect(cgContext, bounds);
1434 PRInt32 eventState = GetContentState(aFrame, aWidgetType);
1436 switch (aWidgetType) {
1437 case NS_THEME_DIALOG: {
1438 HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION);
1439 CGContextFillRect(cgContext, macRect);
1443 case NS_THEME_MENUPOPUP: {
1444 HIThemeMenuDrawInfo mdi = {
1446 menuType: IsDisabled(aFrame) ? kThemeMenuTypeInactive : kThemeMenuTypePopUp
1448 // The rounded corners draw outside the frame.
1449 CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4,
1450 macRect.size.width, macRect.size.height - 8);
1451 HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION);
1455 case NS_THEME_MENUITEM: {
1456 // Clear the background to get correct transparency.
1457 CGContextClearRect(cgContext, macRect);
1459 // maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
1460 HIThemeMenuItemDrawInfo drawInfo = {
1462 itemType: kThemeMenuItemPlain,
1463 state: (IsDisabled(aFrame) ? kThemeMenuDisabled :
1464 CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive) ? kThemeMenuSelected :
1468 // XXX pass in the menu rect instead of always using the item rect
1470 HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored);
1474 case NS_THEME_MENUSEPARATOR: {
1475 ThemeMenuState menuState;
1476 if (IsDisabled(aFrame)) {
1477 menuState = kThemeMenuDisabled;
1480 menuState = CheckBooleanAttr(aFrame, nsWidgetAtoms::mozmenuactive) ?
1481 kThemeMenuSelected : kThemeMenuActive;
1484 HIThemeMenuItemDrawInfo midi = { 0, kThemeMenuItemPlain, menuState };
1485 HIThemeDrawMenuSeparator(&macRect, &macRect, &midi, cgContext, HITHEME_ORIENTATION);
1489 case NS_THEME_TOOLTIP:
1490 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0.78, 1.0);
1491 CGContextFillRect(cgContext, macRect);
1494 case NS_THEME_CHECKBOX:
1495 case NS_THEME_RADIO: {
1496 PRBool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX);
1497 DrawCheckboxOrRadio(cgContext, isCheckbox, macRect, GetCheckedOrSelected(aFrame, !isCheckbox),
1498 IsDisabled(aFrame), eventState, aFrame);
1502 case NS_THEME_BUTTON:
1503 DrawPushButton(cgContext, macRect, IsDefaultButton(aFrame), IsDisabled(aFrame), eventState, aFrame);
1506 case NS_THEME_BUTTON_BEVEL:
1507 DrawButton(cgContext, kThemeMediumBevelButton, macRect,
1508 IsDefaultButton(aFrame), IsDisabled(aFrame),
1509 kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame);
1512 case NS_THEME_SPINNER: {
1513 ThemeDrawState state = kThemeStateActive;
1514 nsIContent* content = aFrame->GetContent();
1515 if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
1516 NS_LITERAL_STRING("up"), eCaseMatters)) {
1517 state = kThemeStatePressedUp;
1519 else if (content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::state,
1520 NS_LITERAL_STRING("down"), eCaseMatters)) {
1521 state = kThemeStatePressedDown;
1524 DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, IsDisabled(aFrame),
1525 state, kThemeAdornmentNone, eventState, aFrame);
1529 case NS_THEME_TOOLBAR_BUTTON:
1530 DrawButton(cgContext, kThemePushButton, macRect,
1531 IsDefaultButton(aFrame), IsDisabled(aFrame),
1532 kThemeButtonOn, kThemeAdornmentNone, eventState, aFrame);
1535 case NS_THEME_TOOLBAR_SEPARATOR: {
1536 HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive };
1537 HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION);
1541 case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
1542 DrawUnifiedToolbar(cgContext, macRect, aFrame);
1545 case NS_THEME_TOOLBAR: {
1546 BOOL isMain = [NativeWindowForFrame(aFrame) isMainWindow];
1549 [NativeGreyColorAsNSColor(toolbarTopBorderGrey, isMain) set];
1550 NSRectFill(NSMakeRect(macRect.origin.x, macRect.origin.y,
1551 macRect.size.width, 1.0f));
1554 [NativeGreyColorAsNSColor(headerEndGrey, isMain) set];
1555 NSRectFill(NSMakeRect(macRect.origin.x, macRect.origin.y + 1.0f,
1556 macRect.size.width, macRect.size.height - 2.0f));
1559 [NativeGreyColorAsNSColor(headerBorderGrey, isMain) set];
1560 NSRectFill(NSMakeRect(macRect.origin.x, macRect.origin.y +
1561 macRect.size.height - 1.0f, macRect.size.width, 1.0f));
1565 case NS_THEME_TOOLBOX:
1566 case NS_THEME_STATUSBAR: {
1567 HIThemeHeaderDrawInfo hdi = { 0, kThemeStateActive, kHIThemeHeaderKindWindow };
1568 HIThemeDrawHeader(&macRect, &hdi, cgContext, HITHEME_ORIENTATION);
1572 case NS_THEME_DROPDOWN:
1573 DrawButton(cgContext, kThemePopupButton, macRect,
1574 IsDefaultButton(aFrame), IsDisabled(aFrame),
1575 kThemeButtonOn, kThemeAdornmentNone, eventState, aFrame);
1578 case NS_THEME_DROPDOWN_BUTTON:
1579 DrawButton(cgContext, kThemeArrowButton, macRect, PR_FALSE,
1580 IsDisabled(aFrame), kThemeButtonOn,
1581 kThemeAdornmentArrowDownArrow, eventState, aFrame);
1584 case NS_THEME_GROUPBOX: {
1585 HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary };
1586 HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION);
1590 case NS_THEME_TEXTFIELD:
1591 // HIThemeSetFill is not available on 10.3
1592 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
1593 CGContextFillRect(cgContext, macRect);
1595 // XUL textboxes set the native appearance on the containing box, while
1596 // concrete focus is set on the html:input element within it. We can
1597 // though, check the focused attribute of xul textboxes in this case.
1598 if (aFrame->GetContent()->IsNodeOfType(nsINode::eXUL) &&
1599 IsFocused(aFrame)) {
1600 eventState |= NS_EVENT_STATE_FOCUS;
1603 DrawFrame(cgContext, kHIThemeFrameTextFieldSquare,
1604 macRect, (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
1607 case NS_THEME_SEARCHFIELD:
1608 DrawSearchField(cgContext, macRect, aFrame);
1611 case NS_THEME_PROGRESSBAR:
1612 DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
1613 PR_TRUE, GetProgressValue(aFrame),
1614 GetProgressMaxValue(aFrame), aFrame);
1617 case NS_THEME_PROGRESSBAR_VERTICAL:
1618 DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame),
1619 PR_FALSE, GetProgressValue(aFrame),
1620 GetProgressMaxValue(aFrame), aFrame);
1623 case NS_THEME_PROGRESSBAR_CHUNK:
1624 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
1625 // do nothing, covered by the progress bar cases above
1628 case NS_THEME_TREEVIEW_TWISTY:
1629 DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
1630 kThemeDisclosureRight, kThemeAdornmentNone, eventState, aFrame);
1633 case NS_THEME_TREEVIEW_TWISTY_OPEN:
1634 DrawButton(cgContext, kThemeDisclosureButton, macRect, PR_FALSE, IsDisabled(aFrame),
1635 kThemeDisclosureDown, kThemeAdornmentNone, eventState, aFrame);
1638 case NS_THEME_TREEVIEW_HEADER_CELL: {
1639 TreeSortDirection sortDirection = GetTreeSortDirection(aFrame);
1640 DrawButton(cgContext, kThemeListHeaderButton, macRect, PR_FALSE, IsDisabled(aFrame),
1641 sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn,
1642 sortDirection == eTreeSortDirection_Ascending ?
1643 kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState, aFrame);
1647 case NS_THEME_TREEVIEW_TREEITEM:
1648 case NS_THEME_TREEVIEW:
1649 // HIThemeSetFill is not available on 10.3
1650 // HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION);
1651 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
1652 CGContextFillRect(cgContext, macRect);
1655 case NS_THEME_TREEVIEW_HEADER:
1656 // do nothing, taken care of by individual header cells
1657 case NS_THEME_TREEVIEW_HEADER_SORTARROW:
1658 // do nothing, taken care of by treeview header
1659 case NS_THEME_TREEVIEW_LINE:
1660 // do nothing, these lines don't exist on macos
1663 case NS_THEME_SCALE_HORIZONTAL:
1664 case NS_THEME_SCALE_VERTICAL: {
1665 PRInt32 curpos = CheckIntAttr(aFrame, nsWidgetAtoms::curpos, 0);
1666 PRInt32 minpos = CheckIntAttr(aFrame, nsWidgetAtoms::minpos, 0);
1667 PRInt32 maxpos = CheckIntAttr(aFrame, nsWidgetAtoms::maxpos, 100);
1671 PRBool reverse = aFrame->GetContent()->
1672 AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::dir,
1673 NS_LITERAL_STRING("reverse"), eCaseMatters);
1674 DrawScale(cgContext, macRect, IsDisabled(aFrame), eventState,
1675 (aWidgetType == NS_THEME_SCALE_VERTICAL), reverse,
1676 curpos, minpos, maxpos, aFrame);
1680 case NS_THEME_SCALE_THUMB_HORIZONTAL:
1681 case NS_THEME_SCALE_THUMB_VERTICAL:
1682 // do nothing, drawn by scale
1685 case NS_THEME_SCROLLBAR_SMALL:
1686 case NS_THEME_SCROLLBAR: {
1687 DrawScrollbar(cgContext, macRect, aFrame);
1690 case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
1691 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
1692 #if SCROLLBARS_VISUAL_DEBUG
1693 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 0, 0.6);
1694 CGContextFillRect(cgContext, macRect);
1697 case NS_THEME_SCROLLBAR_BUTTON_UP:
1698 case NS_THEME_SCROLLBAR_BUTTON_LEFT:
1699 #if SCROLLBARS_VISUAL_DEBUG
1700 CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6);
1701 CGContextFillRect(cgContext, macRect);
1704 case NS_THEME_SCROLLBAR_BUTTON_DOWN:
1705 case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
1706 #if SCROLLBARS_VISUAL_DEBUG
1707 CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6);
1708 CGContextFillRect(cgContext, macRect);
1711 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
1712 case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
1713 // do nothing, drawn by scrollbar
1716 case NS_THEME_TEXTFIELD_MULTILINE: {
1717 // we have to draw this by hand because there is no HITheme value for it
1718 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
1720 CGContextFillRect(cgContext, macRect);
1722 CGContextSetLineWidth(cgContext, 1.0);
1723 CGContextSetShouldAntialias(cgContext, false);
1725 // stroke everything but the top line of the text area
1726 CGContextSetRGBStrokeColor(cgContext, 0.6, 0.6, 0.6, 1.0);
1727 CGContextBeginPath(cgContext);
1728 CGContextMoveToPoint(cgContext, macRect.origin.x, macRect.origin.y + 1);
1729 CGContextAddLineToPoint(cgContext, macRect.origin.x, macRect.origin.y + macRect.size.height);
1730 CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + macRect.size.height);
1731 CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + 1);
1732 CGContextStrokePath(cgContext);
1734 // stroke the line across the top of the text area
1735 CGContextSetRGBStrokeColor(cgContext, 0.4510, 0.4510, 0.4510, 1.0);
1736 CGContextBeginPath(cgContext);
1737 CGContextMoveToPoint(cgContext, macRect.origin.x, macRect.origin.y + 1);
1738 CGContextAddLineToPoint(cgContext, macRect.origin.x + macRect.size.width - 1, macRect.origin.y + 1);
1739 CGContextStrokePath(cgContext);
1741 // draw a focus ring
1742 if (eventState & NS_EVENT_STATE_FOCUS) {
1743 // We need to bring the rectangle in by 1 pixel on each side.
1744 CGRect cgr = CGRectMake(macRect.origin.x + 1,
1745 macRect.origin.y + 1,
1746 macRect.size.width - 2,
1747 macRect.size.height - 2);
1748 HIThemeDrawFocusRect(&cgr, true, cgContext, kHIThemeOrientationNormal);
1753 case NS_THEME_LISTBOX:
1754 // HIThemeSetFill is not available on 10.3
1755 CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
1756 CGContextFillRect(cgContext, macRect);
1757 DrawFrame(cgContext, kHIThemeFrameListBox, macRect,
1758 (IsDisabled(aFrame) || IsReadOnly(aFrame)), eventState);
1762 DrawTab(cgContext, macRect, eventState, aFrame);
1765 case NS_THEME_TAB_PANELS:
1766 DrawTabPanel(cgContext, macRect, aFrame);
1770 nativeDrawing.EndNativeDrawing();
1774 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
1778 static const int kAquaDropdownLeftBorder = 5;
1779 static const int kAquaDropdownRightBorder = 22;
1782 nsNativeThemeCocoa::GetWidgetBorder(nsIDeviceContext* aContext,
1784 PRUint8 aWidgetType,
1787 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
1789 aResult->SizeTo(0, 0, 0, 0);
1791 switch (aWidgetType) {
1792 case NS_THEME_BUTTON:
1794 aResult->SizeTo(7, 1, 7, 3);
1798 case NS_THEME_CHECKBOX:
1799 case NS_THEME_RADIO:
1801 // nsFormControlFrame::GetIntrinsicWidth and nsFormControlFrame::GetIntrinsicHeight
1802 // assume a border width of 2px.
1803 aResult->SizeTo(2, 2, 2, 2);
1807 case NS_THEME_DROPDOWN:
1808 case NS_THEME_DROPDOWN_BUTTON:
1809 aResult->SizeTo(kAquaDropdownLeftBorder, 2, kAquaDropdownRightBorder, 2);
1812 case NS_THEME_TEXTFIELD:
1814 SInt32 frameOutset = 0;
1815 ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset);
1817 SInt32 textPadding = 0;
1818 ::GetThemeMetric(kThemeMetricEditTextWhitespace, &textPadding);
1820 frameOutset += textPadding;
1822 aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
1826 case NS_THEME_TEXTFIELD_MULTILINE:
1827 aResult->SizeTo(1, 1, 1, 1);
1830 case NS_THEME_SEARCHFIELD:
1831 aResult->SizeTo(4, 2, 4, 2);
1834 case NS_THEME_LISTBOX:
1836 SInt32 frameOutset = 0;
1837 ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset);
1838 aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset);
1842 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
1843 case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
1845 // There's only an endcap to worry about when both arrows are on the bottom
1846 ThemeScrollBarArrowStyle arrowStyle;
1847 ::GetThemeScrollBarArrowStyle(&arrowStyle);
1848 if (arrowStyle == kThemeScrollBarArrowsLowerRight) {
1849 PRBool isHorizontal = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL);
1851 nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
1852 if (!scrollbarFrame) return NS_ERROR_FAILURE;
1853 PRBool isSmall = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL);
1855 // There isn't a metric for this, so just hardcode a best guess at the value.
1856 // This value is even less exact due to the fact that the endcap is partially concave.
1857 PRInt32 endcapSize = isSmall ? 5 : 6;
1860 aResult->SizeTo(endcapSize, 0, 0, 0);
1862 aResult->SizeTo(0, endcapSize, 0, 0);
1867 case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
1868 aResult->SizeTo(0, 0, 1, 0);
1874 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
1878 // Return PR_FALSE here to indicate that CSS padding values should be used. There is
1879 // no reason to make a distinction between padding and border values, just specify
1880 // whatever values you want in GetWidgetBorder and only use this to return PR_TRUE
1881 // if you want to override CSS padding values.
1883 nsNativeThemeCocoa::GetWidgetPadding(nsIDeviceContext* aContext,
1885 PRUint8 aWidgetType,
1888 // We don't want CSS padding being used for certain widgets.
1889 // See bug 381639 for an example of why.
1890 switch (aWidgetType) {
1891 case NS_THEME_BUTTON:
1892 // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
1893 // and have a meaningful baseline, so they can't have
1894 // author-specified padding.
1895 case NS_THEME_CHECKBOX:
1896 case NS_THEME_RADIO:
1897 aResult->SizeTo(0, 0, 0, 0);
1905 nsNativeThemeCocoa::GetWidgetOverflow(nsIDeviceContext* aContext, nsIFrame* aFrame,
1906 PRUint8 aWidgetType, nsRect* aOverflowRect)
1908 switch (aWidgetType) {
1909 case NS_THEME_BUTTON:
1910 case NS_THEME_TEXTFIELD:
1911 case NS_THEME_TEXTFIELD_MULTILINE:
1912 case NS_THEME_SEARCHFIELD:
1913 case NS_THEME_LISTBOX:
1914 case NS_THEME_DROPDOWN:
1915 case NS_THEME_DROPDOWN_BUTTON:
1916 case NS_THEME_CHECKBOX:
1917 case NS_THEME_RADIO:
1920 // We assume that the above widgets can draw a focus ring that will be less than
1921 // or equal to 4 pixels thick.
1922 nsIntMargin extraSize = nsIntMargin(MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH, MAX_FOCUS_RING_WIDTH);
1923 PRInt32 p2a = aContext->AppUnitsPerDevPixel();
1924 nsMargin m(NSIntPixelsToAppUnits(extraSize.left, p2a),
1925 NSIntPixelsToAppUnits(extraSize.top, p2a),
1926 NSIntPixelsToAppUnits(extraSize.right, p2a),
1927 NSIntPixelsToAppUnits(extraSize.bottom, p2a));
1928 aOverflowRect->Inflate(m);
1938 nsNativeThemeCocoa::GetMinimumWidgetSize(nsIRenderingContext* aContext,
1940 PRUint8 aWidgetType,
1942 PRBool* aIsOverridable)
1944 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
1946 aResult->SizeTo(0,0);
1947 *aIsOverridable = PR_TRUE;
1949 switch (aWidgetType) {
1950 case NS_THEME_BUTTON:
1952 aResult->SizeTo(NATURAL_MINI_ROUNDED_BUTTON_MIN_WIDTH, NATURAL_MINI_ROUNDED_BUTTON_HEIGHT);
1956 case NS_THEME_SPINNER:
1958 SInt32 buttonHeight = 0, buttonWidth = 0;
1959 ::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth);
1960 ::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight);
1961 aResult->SizeTo(buttonWidth, buttonHeight);
1962 *aIsOverridable = PR_FALSE;
1966 case NS_THEME_DROPDOWN:
1967 case NS_THEME_DROPDOWN_BUTTON:
1969 SInt32 popupHeight = 0;
1970 ::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight);
1971 aResult->SizeTo(0, popupHeight);
1975 case NS_THEME_TEXTFIELD:
1976 case NS_THEME_TEXTFIELD_MULTILINE:
1977 case NS_THEME_SEARCHFIELD:
1979 // at minimum, we should be tall enough for 9pt text.
1980 // I'm using hardcoded values here because the appearance manager
1981 // values for the frame size are incorrect.
1982 aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */);
1986 case NS_THEME_PROGRESSBAR:
1988 SInt32 barHeight = 0;
1989 ::GetThemeMetric(kThemeMetricNormalProgressBarThickness, &barHeight);
1990 aResult->SizeTo(0, barHeight);
1994 case NS_THEME_TREEVIEW_TWISTY:
1995 case NS_THEME_TREEVIEW_TWISTY_OPEN:
1997 SInt32 twistyHeight = 0, twistyWidth = 0;
1998 ::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth);
1999 ::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight);
2000 aResult->SizeTo(twistyWidth, twistyHeight);
2001 *aIsOverridable = PR_FALSE;
2005 case NS_THEME_TREEVIEW_HEADER:
2006 case NS_THEME_TREEVIEW_HEADER_CELL:
2008 SInt32 headerHeight = 0;
2009 ::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
2010 aResult->SizeTo(0, headerHeight - 1); // We don't need the top border.
2016 aResult->SizeTo(0, NATURAL_MINI_TAB_BUTTON_HEIGHT);
2020 case NS_THEME_SCALE_HORIZONTAL:
2022 SInt32 scaleHeight = 0;
2023 ::GetThemeMetric(kThemeMetricHSliderHeight, &scaleHeight);
2024 aResult->SizeTo(scaleHeight, scaleHeight);
2025 *aIsOverridable = PR_FALSE;
2029 case NS_THEME_SCALE_VERTICAL:
2031 SInt32 scaleWidth = 0;
2032 ::GetThemeMetric(kThemeMetricVSliderWidth, &scaleWidth);
2033 aResult->SizeTo(scaleWidth, scaleWidth);
2034 *aIsOverridable = PR_FALSE;
2038 case NS_THEME_SCROLLBAR_SMALL:
2040 SInt32 scrollbarWidth = 0;
2041 ::GetThemeMetric(kThemeMetricSmallScrollBarWidth, &scrollbarWidth);
2042 aResult->SizeTo(scrollbarWidth, scrollbarWidth);
2043 *aIsOverridable = PR_FALSE;
2047 // Get the rect of the thumb from HITheme, so we can return it to Gecko, which has different ideas about
2048 // how big the thumb should be. This is kind of a hack.
2049 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
2050 case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
2052 // Find our parent scrollbar frame. If we can't, abort.
2053 nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
2054 if (!scrollbarFrame) return NS_ERROR_FAILURE;
2056 nsRect scrollbarRect = scrollbarFrame->GetRect();
2057 *aIsOverridable = PR_FALSE;
2059 if (scrollbarRect.IsEmpty()) {
2060 // just return (0,0)
2064 // We need to get the device context to convert from app units :(
2065 nsCOMPtr<nsIDeviceContext> dctx;
2066 aContext->GetDeviceContext(*getter_AddRefs(dctx));
2067 PRInt32 p2a = dctx->AppUnitsPerDevPixel();
2068 CGRect macRect = CGRectMake(NSAppUnitsToIntPixels(scrollbarRect.x, p2a),
2069 NSAppUnitsToIntPixels(scrollbarRect.y, p2a),
2070 NSAppUnitsToIntPixels(scrollbarRect.width, p2a),
2071 NSAppUnitsToIntPixels(scrollbarRect.height, p2a));
2073 // False here means not to get scrollbar button state information.
2074 HIThemeTrackDrawInfo tdi;
2075 GetScrollbarDrawInfo(tdi, scrollbarFrame, macRect, PR_FALSE);
2078 ::HIThemeGetTrackPartBounds(&tdi, kControlIndicatorPart, &thumbRect);
2080 // HITheme is just lying to us, I guess...
2081 PRInt32 thumbAdjust = ((scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
2084 if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL)
2085 aResult->SizeTo(nscoord(thumbRect.size.width), nscoord(thumbRect.size.height - thumbAdjust));
2087 aResult->SizeTo(nscoord(thumbRect.size.width - thumbAdjust), nscoord(thumbRect.size.height));
2091 case NS_THEME_SCROLLBAR:
2092 case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
2093 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
2095 // yeah, i know i'm cheating a little here, but i figure that it
2096 // really doesn't matter if the scrollbar is vertical or horizontal
2097 // and the width metric is a really good metric for every piece
2098 // of the scrollbar.
2100 nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
2101 if (!scrollbarFrame) return NS_ERROR_FAILURE;
2103 PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
2104 kThemeMetricSmallScrollBarWidth :
2105 kThemeMetricScrollBarWidth;
2106 SInt32 scrollbarWidth = 0;
2107 ::GetThemeMetric(themeMetric, &scrollbarWidth);
2108 aResult->SizeTo(scrollbarWidth, scrollbarWidth);
2109 *aIsOverridable = PR_FALSE;
2113 case NS_THEME_SCROLLBAR_BUTTON_UP:
2114 case NS_THEME_SCROLLBAR_BUTTON_DOWN:
2115 case NS_THEME_SCROLLBAR_BUTTON_LEFT:
2116 case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
2118 nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame);
2119 if (!scrollbarFrame) return NS_ERROR_FAILURE;
2121 // Since there is no NS_THEME_SCROLLBAR_BUTTON_UP_SMALL we need to ask the parent what appearance style it has.
2122 PRInt32 themeMetric = (scrollbarFrame->GetStyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ?
2123 kThemeMetricSmallScrollBarWidth :
2124 kThemeMetricScrollBarWidth;
2125 SInt32 scrollbarWidth = 0;
2126 ::GetThemeMetric(themeMetric, &scrollbarWidth);
2128 // It seems that for both sizes of scrollbar, the buttons are one pixel "longer".
2129 if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT)
2130 aResult->SizeTo(scrollbarWidth+1, scrollbarWidth);
2132 aResult->SizeTo(scrollbarWidth, scrollbarWidth+1);
2134 *aIsOverridable = PR_FALSE;
2141 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
2146 nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType,
2147 nsIAtom* aAttribute, PRBool* aShouldRepaint)
2149 // Some widget types just never change state.
2150 switch (aWidgetType) {
2151 case NS_THEME_TOOLBOX:
2152 case NS_THEME_TOOLBAR:
2153 case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
2154 case NS_THEME_TOOLBAR_BUTTON:
2155 case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
2156 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
2157 case NS_THEME_STATUSBAR:
2158 case NS_THEME_STATUSBAR_PANEL:
2159 case NS_THEME_STATUSBAR_RESIZER_PANEL:
2160 case NS_THEME_TOOLTIP:
2161 case NS_THEME_TAB_PANELS:
2162 case NS_THEME_TAB_PANEL:
2163 case NS_THEME_DIALOG:
2164 case NS_THEME_MENUPOPUP:
2165 case NS_THEME_GROUPBOX:
2166 *aShouldRepaint = PR_FALSE;
2168 case NS_THEME_PROGRESSBAR_CHUNK:
2169 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
2170 case NS_THEME_PROGRESSBAR:
2171 case NS_THEME_PROGRESSBAR_VERTICAL:
2172 *aShouldRepaint = (aAttribute == nsWidgetAtoms::step);
2176 // XXXdwh Not sure what can really be done here. Can at least guess for
2177 // specific widgets that they're highly unlikely to have certain states.
2178 // For example, a toolbar doesn't care about any states.
2180 // Hover/focus/active changed. Always repaint.
2181 *aShouldRepaint = PR_TRUE;
2183 // Check the attribute to see if it's relevant.
2184 // disabled, checked, dlgtype, default, etc.
2185 *aShouldRepaint = PR_FALSE;
2186 if (aAttribute == nsWidgetAtoms::disabled ||
2187 aAttribute == nsWidgetAtoms::checked ||
2188 aAttribute == nsWidgetAtoms::selected ||
2189 aAttribute == nsWidgetAtoms::mozmenuactive ||
2190 aAttribute == nsWidgetAtoms::sortdirection ||
2191 aAttribute == nsWidgetAtoms::focused ||
2192 aAttribute == nsWidgetAtoms::_default)
2193 *aShouldRepaint = PR_TRUE;
2201 nsNativeThemeCocoa::ThemeChanged()
2203 // This is unimplemented because we don't care if gecko changes its theme
2204 // and Mac OS X doesn't have themes.
2210 nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
2211 PRUint8 aWidgetType)
2213 // We don't have CSS set up to render non-native scrollbars on Mac OS X so we
2214 // render natively even if native theme support is disabled.
2215 if (aWidgetType != NS_THEME_SCROLLBAR &&
2216 aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
2219 // if this is a dropdown button in a combobox the answer is always no
2220 if (aWidgetType == NS_THEME_DROPDOWN_BUTTON) {
2221 nsIFrame* parentFrame = aFrame->GetParent();
2222 if (parentFrame && (parentFrame->GetType() == nsWidgetAtoms::comboboxControlFrame))
2226 switch (aWidgetType) {
2227 case NS_THEME_LISTBOX:
2229 case NS_THEME_DIALOG:
2230 case NS_THEME_WINDOW:
2231 case NS_THEME_MENUPOPUP:
2232 case NS_THEME_MENUITEM:
2233 case NS_THEME_MENUSEPARATOR:
2234 case NS_THEME_TOOLTIP:
2236 case NS_THEME_CHECKBOX:
2237 case NS_THEME_CHECKBOX_CONTAINER:
2238 case NS_THEME_RADIO:
2239 case NS_THEME_RADIO_CONTAINER:
2240 case NS_THEME_GROUPBOX:
2241 case NS_THEME_BUTTON:
2242 case NS_THEME_BUTTON_BEVEL:
2243 case NS_THEME_SPINNER:
2244 case NS_THEME_TOOLBAR:
2245 case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
2246 case NS_THEME_STATUSBAR:
2247 case NS_THEME_TEXTFIELD:
2248 case NS_THEME_TEXTFIELD_MULTILINE:
2249 case NS_THEME_SEARCHFIELD:
2250 //case NS_THEME_TOOLBOX:
2251 //case NS_THEME_TOOLBAR_BUTTON:
2252 case NS_THEME_PROGRESSBAR:
2253 case NS_THEME_PROGRESSBAR_VERTICAL:
2254 case NS_THEME_PROGRESSBAR_CHUNK:
2255 case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
2256 case NS_THEME_TOOLBAR_SEPARATOR:
2258 case NS_THEME_TAB_PANELS:
2261 case NS_THEME_TREEVIEW_TWISTY:
2262 case NS_THEME_TREEVIEW_TWISTY_OPEN:
2263 case NS_THEME_TREEVIEW:
2264 case NS_THEME_TREEVIEW_HEADER:
2265 case NS_THEME_TREEVIEW_HEADER_CELL:
2266 case NS_THEME_TREEVIEW_HEADER_SORTARROW:
2267 case NS_THEME_TREEVIEW_TREEITEM:
2268 case NS_THEME_TREEVIEW_LINE:
2270 case NS_THEME_SCALE_HORIZONTAL:
2271 case NS_THEME_SCALE_THUMB_HORIZONTAL:
2272 case NS_THEME_SCALE_VERTICAL:
2273 case NS_THEME_SCALE_THUMB_VERTICAL:
2275 case NS_THEME_SCROLLBAR:
2276 case NS_THEME_SCROLLBAR_SMALL:
2277 case NS_THEME_SCROLLBAR_BUTTON_UP:
2278 case NS_THEME_SCROLLBAR_BUTTON_DOWN:
2279 case NS_THEME_SCROLLBAR_BUTTON_LEFT:
2280 case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
2281 case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
2282 case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
2283 case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
2284 case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
2286 case NS_THEME_DROPDOWN:
2287 case NS_THEME_DROPDOWN_BUTTON:
2288 case NS_THEME_DROPDOWN_TEXT:
2289 return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
2298 nsNativeThemeCocoa::WidgetIsContainer(PRUint8 aWidgetType)
2300 // flesh this out at some point
2301 switch (aWidgetType) {
2302 case NS_THEME_DROPDOWN_BUTTON:
2303 case NS_THEME_RADIO:
2304 case NS_THEME_CHECKBOX:
2305 case NS_THEME_PROGRESSBAR:
2314 nsNativeThemeCocoa::ThemeDrawsFocusForWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType)
2316 if (aWidgetType == NS_THEME_DROPDOWN ||
2317 aWidgetType == NS_THEME_BUTTON ||
2318 aWidgetType == NS_THEME_RADIO ||
2319 aWidgetType == NS_THEME_CHECKBOX)
2326 nsNativeThemeCocoa::ThemeNeedsComboboxDropmarker()
2332 nsNativeThemeCocoa::GetWidgetTransparency(PRUint8 aWidgetType)
2334 if (aWidgetType == NS_THEME_MENUPOPUP)
2335 return eTransparencyTransparent;
2337 return eTransparencyOpaque;