2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #import "RenderThemeMac.h"
23 #import "BitmapImage.h"
25 #import "CSSStyleSelector.h"
26 #import "CSSValueKeywords.h"
30 #import "GraphicsContext.h"
31 #import "HTMLInputElement.h"
32 #import "HTMLMediaElement.h"
35 #import "ImageBuffer.h"
36 #import "LocalCurrentGraphicsContext.h"
37 #import "MediaControlElements.h"
38 #import "RenderMedia.h"
39 #import "RenderSlider.h"
40 #import "RenderView.h"
41 #import "SharedBuffer.h"
42 #import "TimeRanges.h"
44 #import "WebCoreSystemInterface.h"
45 #import "UserAgentStyleSheets.h"
46 #import <Carbon/Carbon.h>
47 #import <Cocoa/Cocoa.h>
48 #import <wtf/RetainPtr.h>
49 #import <wtf/StdLibExtras.h>
52 #import "RenderProgress.h"
55 #include "RenderMeter.h"
56 #include "HTMLMeterElement.h"
59 #ifdef BUILDING_ON_TIGER
60 typedef int NSInteger;
61 typedef unsigned NSUInteger;
66 // The methods in this file are specific to the Mac OS X platform.
68 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari.
70 // We estimate the animation rate of a Mac OS X progress bar is 33 fps.
71 // Hard code the value here because we haven't found API for it.
72 const double progressAnimationFrameRate = 0.033;
74 // Mac OS X progress bar animation seems to have 256 frames.
75 const double progressAnimationNumFrames = 256;
77 @interface WebCoreRenderThemeNotificationObserver : NSObject
79 WebCore::RenderTheme *_theme;
82 - (id)initWithTheme:(WebCore::RenderTheme *)theme;
83 - (void)systemColorsDidChange:(NSNotification *)notification;
87 @implementation WebCoreRenderThemeNotificationObserver
89 - (id)initWithTheme:(WebCore::RenderTheme *)theme
97 - (void)systemColorsDidChange:(NSNotification *)unusedNotification
99 ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
100 _theme->platformColorsDidChange();
107 using namespace HTMLNames;
124 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
126 static RenderTheme* rt = RenderThemeMac::create().releaseRef();
131 PassRefPtr<RenderTheme> RenderThemeMac::create()
133 return adoptRef(new RenderThemeMac);
136 RenderThemeMac::RenderThemeMac()
137 : m_isSliderThumbHorizontalPressed(false)
138 , m_isSliderThumbVerticalPressed(false)
139 , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
141 [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
142 selector:@selector(systemColorsDidChange:)
143 name:NSSystemColorsDidChangeNotification
147 RenderThemeMac::~RenderThemeMac()
149 [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
152 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
154 NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
155 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
158 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
160 NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
161 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
164 Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const
166 NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
167 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
170 Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
175 Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
180 Color RenderThemeMac::platformFocusRingColor() const
182 if (usesTestModeFocusRingColor())
183 return oldAquaFocusRingColor();
185 return systemColor(CSSValueWebkitFocusRingColor);
188 Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
190 return platformInactiveSelectionBackgroundColor();
193 static FontWeight toFontWeight(NSInteger appKitFontWeight)
195 ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
196 if (appKitFontWeight > 14)
197 appKitFontWeight = 14;
198 else if (appKitFontWeight < 1)
199 appKitFontWeight = 1;
201 static FontWeight fontWeights[] = {
217 return fontWeights[appKitFontWeight - 1];
220 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
222 DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
223 DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
224 DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
225 DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
226 DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
227 DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
228 DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
230 FontDescription* cachedDesc;
232 switch (cssValueId) {
233 case CSSValueSmallCaption:
234 cachedDesc = &smallSystemFont;
235 if (!smallSystemFont.isAbsoluteSize())
236 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
239 cachedDesc = &menuFont;
240 if (!menuFont.isAbsoluteSize())
241 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
243 case CSSValueStatusBar:
244 cachedDesc = &labelFont;
245 if (!labelFont.isAbsoluteSize())
246 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
248 case CSSValueWebkitMiniControl:
249 cachedDesc = &miniControlFont;
250 if (!miniControlFont.isAbsoluteSize())
251 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
253 case CSSValueWebkitSmallControl:
254 cachedDesc = &smallControlFont;
255 if (!smallControlFont.isAbsoluteSize())
256 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
258 case CSSValueWebkitControl:
259 cachedDesc = &controlFont;
260 if (!controlFont.isAbsoluteSize())
261 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
264 cachedDesc = &systemFont;
265 if (!systemFont.isAbsoluteSize())
266 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
270 NSFontManager *fontManager = [NSFontManager sharedFontManager];
271 cachedDesc->setIsAbsoluteSize(true);
272 cachedDesc->setGenericFamily(FontDescription::NoFamily);
273 cachedDesc->firstFamily().setFamily([font familyName]);
274 cachedDesc->setSpecifiedSize([font pointSize]);
275 cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
276 cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
278 fontDescription = *cachedDesc;
281 static RGBA32 convertNSColorToColor(NSColor *color)
283 NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
284 if (colorInColorSpace) {
285 static const double scaleFactor = nextafter(256.0, 0.0);
286 return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
287 static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
288 static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
291 // This conversion above can fail if the NSColor in question is an NSPatternColor
292 // (as many system colors are). These colors are actually a repeating pattern
293 // not just a solid color. To work around this we simply draw a 1x1 image of
294 // the color and use that pixel's color. It might be better to use an average of
295 // the colors in the pattern instead.
296 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
303 colorSpaceName:NSDeviceRGBColorSpace
307 [NSGraphicsContext saveGraphicsState];
308 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
309 NSEraseRect(NSMakeRect(0, 0, 1, 1));
310 [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
311 [NSGraphicsContext restoreGraphicsState];
314 [offscreenRep getPixel:pixel atX:0 y:0];
316 [offscreenRep release];
318 return makeRGB(pixel[0], pixel[1], pixel[2]);
321 static RGBA32 menuBackgroundColor()
323 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
330 colorSpaceName:NSDeviceRGBColorSpace
334 CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
335 CGRect rect = CGRectMake(0, 0, 1, 1);
336 HIThemeMenuDrawInfo drawInfo;
337 drawInfo.version = 0;
338 drawInfo.menuType = kThemeMenuTypePopUp;
339 HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
342 [offscreenRep getPixel:pixel atX:0 y:0];
344 [offscreenRep release];
346 return makeRGB(pixel[0], pixel[1], pixel[2]);
349 void RenderThemeMac::platformColorsDidChange()
351 m_systemColorCache.clear();
352 RenderTheme::platformColorsDidChange();
355 Color RenderThemeMac::systemColor(int cssValueId) const
357 if (m_systemColorCache.contains(cssValueId))
358 return m_systemColorCache.get(cssValueId);
361 switch (cssValueId) {
362 case CSSValueActiveborder:
363 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
365 case CSSValueActivecaption:
366 color = convertNSColorToColor([NSColor windowFrameTextColor]);
368 case CSSValueAppworkspace:
369 color = convertNSColorToColor([NSColor headerColor]);
371 case CSSValueBackground:
372 // Use theme independent default
374 case CSSValueButtonface:
375 // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
376 // We may want to change this to use the NSColor in future.
379 case CSSValueButtonhighlight:
380 color = convertNSColorToColor([NSColor controlHighlightColor]);
382 case CSSValueButtonshadow:
383 color = convertNSColorToColor([NSColor controlShadowColor]);
385 case CSSValueButtontext:
386 color = convertNSColorToColor([NSColor controlTextColor]);
388 case CSSValueCaptiontext:
389 color = convertNSColorToColor([NSColor textColor]);
391 case CSSValueGraytext:
392 color = convertNSColorToColor([NSColor disabledControlTextColor]);
394 case CSSValueHighlight:
395 color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
397 case CSSValueHighlighttext:
398 color = convertNSColorToColor([NSColor selectedTextColor]);
400 case CSSValueInactiveborder:
401 color = convertNSColorToColor([NSColor controlBackgroundColor]);
403 case CSSValueInactivecaption:
404 color = convertNSColorToColor([NSColor controlBackgroundColor]);
406 case CSSValueInactivecaptiontext:
407 color = convertNSColorToColor([NSColor textColor]);
409 case CSSValueInfobackground:
410 // There is no corresponding NSColor for this so we use a hard coded value.
413 case CSSValueInfotext:
414 color = convertNSColorToColor([NSColor textColor]);
417 color = menuBackgroundColor();
419 case CSSValueMenutext:
420 color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
422 case CSSValueScrollbar:
423 color = convertNSColorToColor([NSColor scrollBarColor]);
426 color = convertNSColorToColor([NSColor textColor]);
428 case CSSValueThreeddarkshadow:
429 color = convertNSColorToColor([NSColor controlDarkShadowColor]);
431 case CSSValueThreedshadow:
432 color = convertNSColorToColor([NSColor shadowColor]);
434 case CSSValueThreedface:
435 // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
436 // We may want to change this to use the NSColor in future.
439 case CSSValueThreedhighlight:
440 color = convertNSColorToColor([NSColor highlightColor]);
442 case CSSValueThreedlightshadow:
443 color = convertNSColorToColor([NSColor controlLightHighlightColor]);
445 case CSSValueWebkitFocusRingColor:
446 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
449 color = convertNSColorToColor([NSColor windowBackgroundColor]);
451 case CSSValueWindowframe:
452 color = convertNSColorToColor([NSColor windowFrameColor]);
454 case CSSValueWindowtext:
455 color = convertNSColorToColor([NSColor windowFrameTextColor]);
459 if (!color.isValid())
460 color = RenderTheme::systemColor(cssValueId);
463 m_systemColorCache.set(cssValueId, color.rgb());
468 bool RenderThemeMac::usesTestModeFocusRingColor() const
470 return WebCore::usesTestModeFocusRingColor();
473 NSView* RenderThemeMac::documentViewFor(RenderObject* o) const
476 return ThemeMac::ensuredView(o->view()->frameView());
478 ASSERT_NOT_REACHED();
483 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
484 const FillLayer& background, const Color& backgroundColor) const
486 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
487 return style->border() != border;
489 // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
490 // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
491 // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming
492 // is in effect we treat it like the control is styled.
493 if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
496 return RenderTheme::isControlStyled(style, border, background, backgroundColor);
499 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
501 ControlPart part = o->style()->appearance();
508 case SquareButtonPart:
510 case DefaultButtonPart:
512 case OuterSpinButtonPart:
513 return RenderTheme::adjustRepaintRect(o, r);
519 float zoomLevel = o->style()->effectiveZoom();
521 if (part == MenulistPart) {
522 setPopupButtonCellState(o, r);
523 IntSize size = popupButtonSizes()[[popupButton() controlSize]];
524 size.setHeight(size.height() * zoomLevel);
525 size.setWidth(r.width());
526 r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
530 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
532 // Only do the inflation if the available width/height are too small. Otherwise try to
533 // fit the glow/check space into the available box's width/height.
534 int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
535 int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
537 if (widthDelta < 0) {
538 result.setX(result.x() - margins[leftMargin] * zoomLevel);
539 result.setWidth(result.width() - widthDelta);
541 if (heightDelta < 0) {
542 result.setY(result.y() - margins[topMargin] * zoomLevel);
543 result.setHeight(result.height() - heightDelta);
548 FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
550 FloatRect partRect(inputRect);
552 // Compute an offset between the part renderer and the input renderer
553 FloatSize offsetFromInputRenderer;
554 const RenderObject* renderer = partRenderer;
555 while (renderer && renderer != inputRenderer) {
556 RenderObject* containingRenderer = renderer->container();
557 offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint());
558 renderer = containingRenderer;
560 // If the input renderer was not a container, something went wrong
561 ASSERT(renderer == inputRenderer);
562 // Move the rect into partRenderer's coords
563 partRect.move(offsetFromInputRenderer);
564 // Account for the local drawing offset (tx, ty)
565 partRect.move(r.x(), r.y());
570 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
572 bool oldIndeterminate = [cell state] == NSMixedState;
573 bool indeterminate = isIndeterminate(o);
574 bool checked = isChecked(o);
576 if (oldIndeterminate != indeterminate) {
577 [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
581 bool oldChecked = [cell state] == NSOnState;
582 if (checked != oldChecked)
583 [cell setState:checked ? NSOnState : NSOffState];
586 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
588 bool oldEnabled = [cell isEnabled];
589 bool enabled = isEnabled(o);
590 if (enabled != oldEnabled)
591 [cell setEnabled:enabled];
594 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
596 bool oldFocused = [cell showsFirstResponder];
597 bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
598 if (focused != oldFocused)
599 [cell setShowsFirstResponder:focused];
602 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
604 bool oldPressed = [cell isHighlighted];
605 bool pressed = (o->node() && o->node()->active());
606 if (pressed != oldPressed)
607 [cell setHighlighted:pressed];
610 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
612 // An alternate way to implement this would be to get the appropriate cell object
613 // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
614 // that would be that we would match AppKit behavior more closely, but a disadvantage
615 // would be that we would rely on an AppKit SPI method.
620 // Checkboxes only have tint when checked.
621 if (o->style()->appearance() == CheckboxPart)
624 // For now assume other controls have tint if enabled.
628 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
630 int fontSize = style->fontSize();
632 return NSRegularControlSize;
634 return NSSmallControlSize;
635 return NSMiniControlSize;
638 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
641 if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
642 minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
643 size = NSRegularControlSize;
644 else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
645 minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
646 size = NSSmallControlSize;
648 size = NSMiniControlSize;
649 if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
650 [cell setControlSize:size];
653 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
655 if (style->effectiveZoom() != 1.0f) {
656 IntSize result = sizes[controlSizeForFont(style)];
657 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
659 return sizes[controlSizeForFont(style)];
662 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
664 if (style->effectiveZoom() != 1.0f) {
665 IntSize result = sizes[controlSizeForSystemFont(style)];
666 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
668 return sizes[controlSizeForSystemFont(style)];
671 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
673 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
674 IntSize size = sizeForFont(style, sizes);
675 if (style->width().isIntrinsicOrAuto() && size.width() > 0)
676 style->setWidth(Length(size.width(), Fixed));
677 if (style->height().isAuto() && size.height() > 0)
678 style->setHeight(Length(size.height(), Fixed));
681 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
683 FontDescription fontDescription;
684 fontDescription.setIsAbsoluteSize(true);
685 fontDescription.setGenericFamily(FontDescription::SerifFamily);
687 NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
688 fontDescription.firstFamily().setFamily([font familyName]);
689 fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
690 fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
693 style->setLineHeight(RenderStyle::initialLineHeight());
695 if (style->setFontDescription(fontDescription))
696 style->font().update(0);
699 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
701 int fontSize = style->fontSize();
702 if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
703 return NSRegularControlSize;
704 if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
705 return NSSmallControlSize;
706 return NSMiniControlSize;
709 bool RenderThemeMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
711 LocalCurrentGraphicsContext localContext(paintInfo.context);
712 wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
716 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
720 bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
722 if (paintInfo.context->paintingDisabled())
725 LocalCurrentGraphicsContext localContext(paintInfo.context);
726 wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
731 bool RenderThemeMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
733 LocalCurrentGraphicsContext localContext(paintInfo.context);
734 wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
738 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
742 const int* RenderThemeMac::popupButtonMargins() const
744 static const int margins[3][4] =
750 return margins[[popupButton() controlSize]];
753 const IntSize* RenderThemeMac::popupButtonSizes() const
755 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
759 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
761 static const int padding[3][4] =
767 return padding[size];
770 bool RenderThemeMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
772 LocalCurrentGraphicsContext localContext(paintInfo.context);
773 setPopupButtonCellState(o, r);
775 NSPopUpButtonCell* popupButton = this->popupButton();
777 float zoomLevel = o->style()->effectiveZoom();
778 IntSize size = popupButtonSizes()[[popupButton controlSize]];
779 size.setHeight(size.height() * zoomLevel);
780 size.setWidth(r.width());
782 // Now inflate it to account for the shadow.
783 IntRect inflatedRect = r;
784 if (r.width() >= minimumMenuListSize(o->style()))
785 inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
787 paintInfo.context->save();
789 #ifndef BUILDING_ON_TIGER
790 // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
791 paintInfo.context->clip(inflatedRect);
794 if (zoomLevel != 1.0f) {
795 inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
796 inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
797 paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
798 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
799 paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
802 [popupButton drawWithFrame:inflatedRect inView:documentViewFor(o)];
803 [popupButton setControlView:nil];
805 paintInfo.context->restore();
810 #if ENABLE(METER_TAG)
812 IntSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
814 if (NoControlPart == renderMeter->style()->appearance())
815 return bounds.size();
817 NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
818 // Makes enough room for cell's intrinsic size.
819 NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
820 return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
821 bounds.height() < cellSize.height ? cellSize.height : bounds.height());
824 bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
826 if (!renderObject->isMeter())
829 LocalCurrentGraphicsContext localContext(paintInfo.context);
831 // Becaue NSLevelIndicatorCell doesn't support vertical gauge, we use a portable version
832 if (rect.width() < rect.height())
833 return RenderTheme::paintMeter(renderObject, paintInfo, rect);
835 NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
836 paintInfo.context->save();
837 [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
838 [cell setControlView:nil];
839 paintInfo.context->restore();
844 bool RenderThemeMac::supportsMeter(ControlPart part, bool isHorizontal) const
847 case RelevancyLevelIndicatorPart:
848 case DiscreteCapacityLevelIndicatorPart:
849 case RatingLevelIndicatorPart:
851 case ContinuousCapacityLevelIndicatorPart:
858 NSLevelIndicatorStyle RenderThemeMac::levelIndicatorStyleFor(ControlPart part) const
861 case RelevancyLevelIndicatorPart:
862 return NSRelevancyLevelIndicatorStyle;
863 case DiscreteCapacityLevelIndicatorPart:
864 return NSDiscreteCapacityLevelIndicatorStyle;
865 case RatingLevelIndicatorPart:
866 return NSRatingLevelIndicatorStyle;
868 case ContinuousCapacityLevelIndicatorPart:
870 return NSContinuousCapacityLevelIndicatorStyle;
875 NSLevelIndicatorCell* RenderThemeMac::levelIndicatorFor(const RenderMeter* renderMeter) const
877 RenderStyle* style = renderMeter->style();
878 ASSERT(style->appearance() != NoControlPart);
880 if (!m_levelIndicator)
881 m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
882 NSLevelIndicatorCell* cell = m_levelIndicator.get();
884 HTMLMeterElement* element = static_cast<HTMLMeterElement*>(renderMeter->node());
885 double value = element->value();
887 // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
888 // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
889 switch (element->gaugeRegion()) {
890 case HTMLMeterElement::GaugeRegionOptimum:
891 // Make meter the green
892 [cell setWarningValue:value + 1];
893 [cell setCriticalValue:value + 2];
895 case HTMLMeterElement::GaugeRegionSuboptimal:
896 // Make the meter yellow
897 [cell setWarningValue:value - 1];
898 [cell setCriticalValue:value + 1];
900 case HTMLMeterElement::GaugeRegionEvenLessGood:
901 // Make the meter red
902 [cell setWarningValue:value - 2];
903 [cell setCriticalValue:value - 1];
907 [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
908 [cell setBaseWritingDirection:style->direction() == LTR ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
909 [cell setMinValue:element->min()];
910 [cell setMaxValue:element->max()];
911 RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
912 [cell setObjectValue:valueObject.get()];
919 #if ENABLE(PROGRESS_TAG)
921 double RenderThemeMac::animationRepeatIntervalForProgressBar(RenderProgress*) const
923 return progressAnimationFrameRate;
926 double RenderThemeMac::animationDurationForProgressBar(RenderProgress*) const
928 return progressAnimationNumFrames * progressAnimationFrameRate;
931 void RenderThemeMac::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
935 bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
937 if (!renderObject->isProgress())
940 RenderProgress* renderProgress = toRenderProgress(renderObject);
941 HIThemeTrackDrawInfo trackInfo;
942 trackInfo.version = 0;
943 trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
944 trackInfo.bounds = IntRect(IntPoint(), rect.size());
946 trackInfo.max = numeric_limits<SInt32>::max();
947 trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
948 trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
949 trackInfo.attributes = kThemeTrackHorizontal;
950 trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
951 trackInfo.reserved = 0;
952 trackInfo.filler1 = 0;
954 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(rect.size());
958 HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal);
960 paintInfo.context->save();
962 if (renderProgress->style()->direction() == RTL) {
963 paintInfo.context->translate(2 * rect.x() + rect.width(), 0);
964 paintInfo.context->scale(FloatSize(-1, 1));
966 paintInfo.context->drawImage(imageBuffer->image(), DeviceColorSpace, rect.location());
968 paintInfo.context->restore();
973 const float baseFontSize = 11.0f;
974 const float baseArrowHeight = 4.0f;
975 const float baseArrowWidth = 5.0f;
976 const float baseSpaceBetweenArrows = 2.0f;
977 const int arrowPaddingLeft = 6;
978 const int arrowPaddingRight = 6;
979 const int paddingBeforeSeparator = 4;
980 const int baseBorderRadius = 5;
981 const int styledPopupPaddingLeft = 8;
982 const int styledPopupPaddingTop = 1;
983 const int styledPopupPaddingBottom = 2;
985 static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
987 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
988 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
991 for (i = 0; i < 4; i++)
992 outData[i] = (1.0f - a) * dark[i] + a * light[i];
995 static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
997 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
998 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
1001 for (i = 0; i < 4; i++)
1002 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1005 static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1007 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
1008 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1009 float a = inData[0];
1011 for (i = 0; i < 4; i++)
1012 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1015 static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1017 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
1018 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
1019 float a = inData[0];
1021 for (i = 0; i < 4; i++)
1022 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1025 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1030 CGContextRef context = paintInfo.context->platformContext();
1032 paintInfo.context->save();
1034 IntSize topLeftRadius;
1035 IntSize topRightRadius;
1036 IntSize bottomLeftRadius;
1037 IntSize bottomRightRadius;
1039 o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
1041 int radius = topLeftRadius.width();
1043 RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1045 FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
1046 struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
1047 RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
1048 RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
1050 FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
1051 struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
1052 RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
1053 RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
1055 struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
1056 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1057 RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
1059 RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
1061 RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
1062 paintInfo.context->save();
1063 CGContextClipToRect(context, r);
1064 paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
1065 CGContextDrawShading(context, mainShading.get());
1066 paintInfo.context->restore();
1068 paintInfo.context->save();
1069 CGContextClipToRect(context, topGradient);
1070 paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize());
1071 CGContextDrawShading(context, topShading.get());
1072 paintInfo.context->restore();
1074 if (!bottomGradient.isEmpty()) {
1075 paintInfo.context->save();
1076 CGContextClipToRect(context, bottomGradient);
1077 paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius);
1078 CGContextDrawShading(context, bottomShading.get());
1079 paintInfo.context->restore();
1082 paintInfo.context->save();
1083 CGContextClipToRect(context, r);
1084 paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
1085 CGContextDrawShading(context, leftShading.get());
1086 CGContextDrawShading(context, rightShading.get());
1087 paintInfo.context->restore();
1089 paintInfo.context->restore();
1092 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1094 IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
1095 r.y() + o->style()->borderTopWidth(),
1096 r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
1097 r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
1098 // Draw the gradients to give the styled popup menu a button appearance
1099 paintMenuListButtonGradients(o, paintInfo, bounds);
1101 // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
1102 float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
1103 float centerY = bounds.y() + bounds.height() / 2.0f;
1104 float arrowHeight = baseArrowHeight * fontScale;
1105 float arrowWidth = baseArrowWidth * fontScale;
1106 float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
1107 float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
1109 if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
1112 paintInfo.context->save();
1114 paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace());
1115 paintInfo.context->setStrokeStyle(NoStroke);
1117 FloatPoint arrow1[3];
1118 arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
1119 arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
1120 arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
1122 // Draw the top arrow
1123 paintInfo.context->drawConvexPolygon(3, arrow1, true);
1125 FloatPoint arrow2[3];
1126 arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
1127 arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
1128 arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
1130 // Draw the bottom arrow
1131 paintInfo.context->drawConvexPolygon(3, arrow2, true);
1133 Color leftSeparatorColor(0, 0, 0, 40);
1134 Color rightSeparatorColor(255, 255, 255, 40);
1136 // FIXME: Should the separator thickness and space be scaled up by fontScale?
1137 int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
1138 int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
1140 // Draw the separator to the left of the arrows
1141 paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
1142 paintInfo.context->setStrokeStyle(SolidStroke);
1143 paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace);
1144 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
1145 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
1147 paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace);
1148 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
1149 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
1151 paintInfo.context->restore();
1155 static const IntSize* menuListButtonSizes()
1157 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
1161 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1163 NSControlSize controlSize = controlSizeForFont(style);
1165 style->resetBorder();
1166 style->resetPadding();
1168 // Height is locked to auto.
1169 style->setHeight(Length(Auto));
1171 // White-space is locked to pre
1172 style->setWhiteSpace(PRE);
1174 // Set the foreground color to black or gray when we have the aqua look.
1175 // Cast to RGB32 is to work around a compiler bug.
1176 style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
1178 // Set the button's vertical size.
1179 setSizeFromFont(style, menuListButtonSizes());
1181 // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
1182 // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
1183 // system font for the control size instead.
1184 setFontFromControlSize(selector, style, controlSize);
1186 style->setBoxShadow(0);
1189 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
1191 if (style->appearance() == MenulistPart)
1192 return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
1193 if (style->appearance() == MenulistButtonPart)
1194 return styledPopupPaddingLeft * style->effectiveZoom();
1198 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
1200 if (style->appearance() == MenulistPart)
1201 return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
1202 if (style->appearance() == MenulistButtonPart) {
1203 float fontScale = style->fontSize() / baseFontSize;
1204 float arrowWidth = baseArrowWidth * fontScale;
1205 return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
1210 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
1212 if (style->appearance() == MenulistPart)
1213 return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
1214 if (style->appearance() == MenulistButtonPart)
1215 return styledPopupPaddingTop * style->effectiveZoom();
1219 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
1221 if (style->appearance() == MenulistPart)
1222 return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
1223 if (style->appearance() == MenulistButtonPart)
1224 return styledPopupPaddingBottom * style->effectiveZoom();
1228 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1230 float fontScale = style->fontSize() / baseFontSize;
1232 style->resetPadding();
1233 style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1235 const int minHeight = 15;
1236 style->setMinHeight(Length(minHeight, Fixed));
1238 style->setLineHeight(RenderStyle::initialLineHeight());
1241 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1243 NSPopUpButtonCell* popupButton = this->popupButton();
1245 // Set the control size based off the rectangle we're painting into.
1246 setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
1248 // Update the various states we respond to.
1249 updateActiveState(popupButton, o);
1250 updateCheckedState(popupButton, o);
1251 updateEnabledState(popupButton, o);
1252 updatePressedState(popupButton, o);
1253 updateFocusedState(popupButton, o);
1256 const IntSize* RenderThemeMac::menuListSizes() const
1258 static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1262 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
1264 return sizeForSystemFont(style, menuListSizes()).width();
1267 const int trackWidth = 5;
1268 const int trackRadius = 2;
1270 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1272 style->setBoxShadow(0);
1275 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1278 float zoomLevel = o->style()->effectiveZoom();
1279 float zoomedTrackWidth = trackWidth * zoomLevel;
1281 if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) {
1282 bounds.setHeight(zoomedTrackWidth);
1283 bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
1284 } else if (o->style()->appearance() == SliderVerticalPart) {
1285 bounds.setWidth(zoomedTrackWidth);
1286 bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
1289 LocalCurrentGraphicsContext localContext(paintInfo.context);
1290 CGContextRef context = paintInfo.context->platformContext();
1291 RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1293 paintInfo.context->save();
1294 CGContextClipToRect(context, bounds);
1296 struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
1297 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1298 RetainPtr<CGShadingRef> mainShading;
1299 if (o->style()->appearance() == SliderVerticalPart)
1300 mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
1302 mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
1304 IntSize radius(trackRadius, trackRadius);
1305 paintInfo.context->addRoundedRectClip(bounds,
1308 CGContextDrawShading(context, mainShading.get());
1309 paintInfo.context->restore();
1314 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1316 style->setBoxShadow(0);
1319 const float verticalSliderHeightPadding = 0.1f;
1321 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1323 ASSERT(o->parent()->isSlider());
1325 NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
1326 ? sliderThumbVertical()
1327 : sliderThumbHorizontal();
1329 LocalCurrentGraphicsContext localContext(paintInfo.context);
1331 // Update the various states we respond to.
1332 updateActiveState(sliderThumbCell, o->parent());
1333 updateEnabledState(sliderThumbCell, o->parent());
1334 updateFocusedState(sliderThumbCell, o->parent());
1336 // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
1338 if (o->style()->appearance() == SliderThumbVerticalPart)
1339 oldPressed = m_isSliderThumbVerticalPressed;
1341 oldPressed = m_isSliderThumbHorizontalPressed;
1343 bool pressed = toRenderSlider(o->parent())->inDragMode();
1345 if (o->style()->appearance() == SliderThumbVerticalPart)
1346 m_isSliderThumbVerticalPressed = pressed;
1348 m_isSliderThumbHorizontalPressed = pressed;
1350 if (pressed != oldPressed) {
1352 [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
1354 [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
1357 FloatRect bounds = r;
1358 // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
1359 if (o->style()->appearance() == SliderThumbVerticalPart)
1360 bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
1362 paintInfo.context->save();
1363 float zoomLevel = o->style()->effectiveZoom();
1365 FloatRect unzoomedRect = bounds;
1366 if (zoomLevel != 1.0f) {
1367 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1368 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1369 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1370 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1371 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1374 [sliderThumbCell drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1375 [sliderThumbCell setControlView:nil];
1377 paintInfo.context->restore();
1382 bool RenderThemeMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1384 LocalCurrentGraphicsContext localContext(paintInfo.context);
1385 NSSearchFieldCell* search = this->search();
1387 setSearchCellState(o, r);
1389 paintInfo.context->save();
1391 float zoomLevel = o->style()->effectiveZoom();
1393 IntRect unzoomedRect = r;
1395 if (zoomLevel != 1.0f) {
1396 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1397 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1398 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1399 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1400 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1403 // Set the search button to nil before drawing. Then reset it so we can draw it later.
1404 [search setSearchButtonCell:nil];
1406 [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)];
1407 #ifdef BUILDING_ON_TIGER
1408 if ([search showsFirstResponder])
1409 wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
1412 [search setControlView:nil];
1413 [search resetSearchButtonCell];
1415 paintInfo.context->restore();
1420 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
1422 NSSearchFieldCell* search = this->search();
1424 [search setControlSize:controlSizeForFont(o->style())];
1426 // Update the various states we respond to.
1427 updateActiveState(search, o);
1428 updateEnabledState(search, o);
1429 updateFocusedState(search, o);
1432 const IntSize* RenderThemeMac::searchFieldSizes() const
1434 static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
1438 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
1440 // If the width and height are both specified, then we have nothing to do.
1441 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1444 // Use the font size to determine the intrinsic width of the control.
1445 setSizeFromFont(style, searchFieldSizes());
1448 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
1451 style->resetBorder();
1452 const short borderWidth = 2 * style->effectiveZoom();
1453 style->setBorderLeftWidth(borderWidth);
1454 style->setBorderLeftStyle(INSET);
1455 style->setBorderRightWidth(borderWidth);
1456 style->setBorderRightStyle(INSET);
1457 style->setBorderBottomWidth(borderWidth);
1458 style->setBorderBottomStyle(INSET);
1459 style->setBorderTopWidth(borderWidth);
1460 style->setBorderTopStyle(INSET);
1463 style->setHeight(Length(Auto));
1464 setSearchFieldSize(style);
1466 // Override padding size to match AppKit text positioning.
1467 const int padding = 1 * style->effectiveZoom();
1468 style->setPaddingLeft(Length(padding, Fixed));
1469 style->setPaddingRight(Length(padding, Fixed));
1470 style->setPaddingTop(Length(padding, Fixed));
1471 style->setPaddingBottom(Length(padding, Fixed));
1473 NSControlSize controlSize = controlSizeForFont(style);
1474 setFontFromControlSize(selector, style, controlSize);
1476 style->setBoxShadow(0);
1479 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1481 Node* input = o->node()->shadowAncestorNode();
1482 if (!input->renderer()->isBox())
1485 LocalCurrentGraphicsContext localContext(paintInfo.context);
1486 setSearchCellState(input->renderer(), r);
1488 NSSearchFieldCell* search = this->search();
1490 updateActiveState([search cancelButtonCell], o);
1491 updatePressedState([search cancelButtonCell], o);
1493 paintInfo.context->save();
1495 float zoomLevel = o->style()->effectiveZoom();
1497 FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1499 #if ENABLE(INPUT_SPEECH)
1500 // Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
1501 // when speech input is enabled for the input element.
1502 IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
1503 int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
1504 int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
1505 localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
1508 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1510 FloatRect unzoomedRect(localBounds);
1511 if (zoomLevel != 1.0f) {
1512 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1513 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1514 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1515 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1516 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1519 [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1520 [[search cancelButtonCell] setControlView:nil];
1522 paintInfo.context->restore();
1526 const IntSize* RenderThemeMac::cancelButtonSizes() const
1528 static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1532 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1534 IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1535 style->setWidth(Length(size.width(), Fixed));
1536 style->setHeight(Length(size.height(), Fixed));
1537 style->setBoxShadow(0);
1540 const IntSize* RenderThemeMac::resultsButtonSizes() const
1542 static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1546 const int emptyResultsOffset = 9;
1547 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1549 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1550 style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1551 style->setHeight(Length(size.height(), Fixed));
1552 style->setBoxShadow(0);
1555 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
1560 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1562 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1563 style->setWidth(Length(size.width(), Fixed));
1564 style->setHeight(Length(size.height(), Fixed));
1565 style->setBoxShadow(0);
1568 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo&, const IntRect& r)
1570 Node* input = o->node()->shadowAncestorNode();
1571 if (!input->renderer()->isBox())
1574 LocalCurrentGraphicsContext localContext(paintInfo.context);
1575 setSearchCellState(input->renderer(), r);
1577 NSSearchFieldCell* search = this->search();
1579 if ([search searchMenuTemplate] != nil)
1580 [search setSearchMenuTemplate:nil];
1582 updateActiveState([search searchButtonCell], o);
1584 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1585 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1587 [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
1588 [[search searchButtonCell] setControlView:nil];
1592 const int resultsArrowWidth = 5;
1593 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1595 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1596 style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1597 style->setHeight(Length(size.height(), Fixed));
1598 style->setBoxShadow(0);
1601 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1603 Node* input = o->node()->shadowAncestorNode();
1604 if (!input->renderer()->isBox())
1607 LocalCurrentGraphicsContext localContext(paintInfo.context);
1608 setSearchCellState(input->renderer(), r);
1610 NSSearchFieldCell* search = this->search();
1612 updateActiveState([search searchButtonCell], o);
1614 if (![search searchMenuTemplate])
1615 [search setSearchMenuTemplate:searchMenuTemplate()];
1617 paintInfo.context->save();
1619 float zoomLevel = o->style()->effectiveZoom();
1621 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1622 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1624 IntRect unzoomedRect(localBounds);
1625 if (zoomLevel != 1.0f) {
1626 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1627 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1628 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1629 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1630 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1633 [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1634 [[search searchButtonCell] setControlView:nil];
1636 paintInfo.context->restore();
1643 MediaControllerThemeClassic = 1,
1644 MediaControllerThemeQuickTime = 2
1645 } MediaControllerThemeStyle;
1647 static int mediaControllerTheme()
1649 static int controllerTheme = -1;
1651 if (controllerTheme != -1)
1652 return controllerTheme;
1654 controllerTheme = MediaControllerThemeClassic;
1657 Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
1659 #if !defined(BUILDING_ON_TIGER)
1660 if (validKey && !useQTMediaUIPref)
1661 return controllerTheme;
1663 if (!validKey || !useQTMediaUIPref)
1664 return controllerTheme;
1667 controllerTheme = MediaControllerThemeQuickTime;
1668 return controllerTheme;
1672 const int sliderThumbWidth = 15;
1673 const int sliderThumbHeight = 15;
1674 const int mediaSliderThumbWidth = 13;
1675 const int mediaSliderThumbHeight = 14;
1677 void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
1679 float zoomLevel = o->style()->effectiveZoom();
1680 if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
1681 o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
1682 o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
1686 adjustMediaSliderThumbSize(o);
1692 void RenderThemeMac::adjustMediaSliderThumbSize(RenderObject* o) const
1694 ControlPart part = o->style()->appearance();
1696 if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
1697 int width = mediaSliderThumbWidth;
1698 int height = mediaSliderThumbHeight;
1700 if (mediaControllerTheme() == MediaControllerThemeQuickTime) {
1703 wkMeasureMediaUIPart(part == MediaSliderThumbPart ? MediaSliderThumb : MediaVolumeSliderThumb, MediaControllerThemeQuickTime, NULL, &size);
1705 height = size.height;
1708 float zoomLevel = o->style()->effectiveZoom();
1709 o->style()->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
1710 o->style()->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
1714 enum WKMediaControllerThemeState {
1715 MediaUIPartDisabledFlag = 1 << 0,
1716 MediaUIPartPressedFlag = 1 << 1,
1717 MediaUIPartDrawEndCapsFlag = 1 << 3,
1720 static unsigned getMediaUIPartStateFlags(Node* node)
1724 if (node->disabled())
1725 flags |= MediaUIPartDisabledFlag;
1726 else if (node->active())
1727 flags |= MediaUIPartPressedFlag;
1731 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
1732 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect)
1734 float zoomLevel = o->style()->effectiveZoom();
1735 FloatRect unzoomedRect(originalRect);
1736 if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) {
1737 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1738 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1739 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1740 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1741 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1743 return unzoomedRect;
1747 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1749 Node* node = o->node();
1753 LocalCurrentGraphicsContext localContext(paintInfo.context);
1754 wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1758 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1760 Node* node = o->node();
1761 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1762 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1765 if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(node)) {
1766 LocalCurrentGraphicsContext localContext(paintInfo.context);
1767 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1773 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1775 Node* node = o->node();
1776 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1777 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1780 if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
1781 LocalCurrentGraphicsContext localContext(paintInfo.context);
1782 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1787 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1789 Node* node = o->node();
1793 LocalCurrentGraphicsContext localContext(paintInfo.context);
1794 wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1798 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1800 Node* node = o->node();
1804 LocalCurrentGraphicsContext localContext(paintInfo.context);
1805 wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1809 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1811 Node* node = o->node();
1812 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1813 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1816 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1820 RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
1821 ExceptionCode ignoredException;
1822 float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0;
1823 float currentTime = mediaElement->currentTime();
1824 float duration = mediaElement->duration();
1825 if (isnan(duration))
1828 paintInfo.context->save();
1829 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1830 wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect,
1831 timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
1833 paintInfo.context->restore();
1837 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1839 Node* node = o->node();
1843 LocalCurrentGraphicsContext localContext(paintInfo.context);
1844 wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1848 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1850 Node* node = o->node();
1854 LocalCurrentGraphicsContext localContext(paintInfo.context);
1855 wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1859 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1861 Node* node = o->node();
1865 LocalCurrentGraphicsContext localContext(paintInfo.context);
1866 wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1870 bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1872 HTMLInputElement* node = static_cast<HTMLInputElement*>(o->node());
1876 MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(node);
1880 LocalCurrentGraphicsContext localContext(paintInfo.context);
1881 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1886 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1888 Node* node = o->node();
1892 LocalCurrentGraphicsContext localContext(paintInfo.context);
1893 wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1897 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1899 Node* node = o->node();
1903 paintInfo.context->save();
1904 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1905 wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
1906 paintInfo.context->restore();
1910 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1912 Node* node = o->node();
1916 paintInfo.context->save();
1917 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1918 wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
1919 paintInfo.context->restore();
1923 bool RenderThemeMac::paintMediaVolumeSliderContainer(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1925 Node* node = o->node();
1929 LocalCurrentGraphicsContext localContext(paintInfo.context);
1930 wkDrawMediaUIPart(MediaVolumeSliderContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1934 bool RenderThemeMac::paintMediaVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1936 Node* node = o->node();
1940 LocalCurrentGraphicsContext localContext(paintInfo.context);
1941 wkDrawMediaUIPart(MediaVolumeSlider, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1945 bool RenderThemeMac::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1947 Node* node = o->node();
1951 LocalCurrentGraphicsContext localContext(paintInfo.context);
1952 wkDrawMediaUIPart(MediaVolumeSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1956 String RenderThemeMac::extraMediaControlsStyleSheet()
1959 if (mediaControllerTheme() == MediaControllerThemeQuickTime)
1960 return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
1964 ASSERT_NOT_REACHED();
1969 bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element)
1972 case MediaVolumeSliderContainerPart:
1973 case MediaVolumeSliderPart:
1974 case MediaVolumeSliderMuteButtonPart:
1975 case MediaVolumeSliderThumbPart: {
1976 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
1977 return mediaControllerTheme() == MediaControllerThemeQuickTime && mediaElement->hasAudio();
1979 case MediaToggleClosedCaptionsButtonPart:
1980 // We rely on QTKit to render captions so don't enable the button unless it will be able to do so.
1981 if (!element->hasTagName(videoTag))
1987 return RenderTheme::shouldRenderMediaControlPart(part, element);
1990 IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(Node* muteButton, const IntSize& size) const
1992 static const int xOffset = -4;
1993 static const int yOffset = 5;
1995 float zoomLevel = muteButton->renderer()->style()->effectiveZoom();
1996 int y = yOffset * zoomLevel + muteButton->renderBox()->offsetHeight() - size.height();
1997 FloatPoint absPoint = muteButton->renderer()->localToAbsolute(FloatPoint(muteButton->renderBox()->offsetLeft(), y), true, true);
1998 if (absPoint.y() < 0)
1999 y = muteButton->renderBox()->height();
2000 return IntPoint(xOffset * zoomLevel, y);
2003 #endif // ENABLE(VIDEO)
2005 NSPopUpButtonCell* RenderThemeMac::popupButton() const
2007 if (!m_popupButton) {
2008 m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
2009 [m_popupButton.get() setUsesItemFromMenu:NO];
2010 [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
2013 return m_popupButton.get();
2016 NSSearchFieldCell* RenderThemeMac::search() const
2019 m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
2020 [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
2021 [m_search.get() setBezeled:YES];
2022 [m_search.get() setEditable:YES];
2023 [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
2026 return m_search.get();
2029 NSMenu* RenderThemeMac::searchMenuTemplate() const
2031 if (!m_searchMenuTemplate)
2032 m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
2034 return m_searchMenuTemplate.get();
2037 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
2039 if (!m_sliderThumbHorizontal) {
2040 m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
2041 [m_sliderThumbHorizontal.get() setTitle:nil];
2042 [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
2043 [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
2044 [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
2047 return m_sliderThumbHorizontal.get();
2050 NSSliderCell* RenderThemeMac::sliderThumbVertical() const
2052 if (!m_sliderThumbVertical) {
2053 m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
2054 [m_sliderThumbVertical.get() setTitle:nil];
2055 [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
2056 [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
2057 [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
2060 return m_sliderThumbVertical.get();
2063 } // namespace WebCore