2 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 "GraphicsContextCG.h"
31 #import "HTMLInputElement.h"
32 #import "HTMLMediaElement.h"
35 #import "ImageBuffer.h"
36 #import "LocalCurrentGraphicsContext.h"
37 #import "LocalizedStrings.h"
38 #import "MediaControlElements.h"
40 #import "RenderMedia.h"
41 #import "RenderMediaControls.h"
42 #import "RenderSlider.h"
43 #import "RenderView.h"
44 #import "SharedBuffer.h"
45 #import "StringTruncator.h"
46 #import "TimeRanges.h"
48 #import "WebCoreSystemInterface.h"
49 #import "UserAgentStyleSheets.h"
50 #import <Carbon/Carbon.h>
51 #import <Cocoa/Cocoa.h>
52 #import <wtf/RetainPtr.h>
53 #import <wtf/StdLibExtras.h>
56 #import "RenderProgress.h"
59 #include "RenderMeter.h"
60 #include "HTMLMeterElement.h"
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
91 if (!(self = [super init]))
98 - (void)systemColorsDidChange:(NSNotification *)unusedNotification
100 ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
101 _theme->platformColorsDidChange();
108 using namespace HTMLNames;
125 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
127 static RenderTheme* rt = RenderThemeMac::create().leakRef();
132 PassRefPtr<RenderTheme> RenderThemeMac::create()
134 return adoptRef(new RenderThemeMac);
137 RenderThemeMac::RenderThemeMac()
138 : m_isSliderThumbHorizontalPressed(false)
139 , m_isSliderThumbVerticalPressed(false)
140 , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
142 [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
143 selector:@selector(systemColorsDidChange:)
144 name:NSSystemColorsDidChangeNotification
148 RenderThemeMac::~RenderThemeMac()
150 [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
153 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
155 NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
156 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
159 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
161 NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
162 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
165 Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const
167 NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
168 return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
171 Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
176 Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
181 Color RenderThemeMac::platformFocusRingColor() const
183 if (usesTestModeFocusRingColor())
184 return oldAquaFocusRingColor();
186 return systemColor(CSSValueWebkitFocusRingColor);
189 Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
191 return platformInactiveSelectionBackgroundColor();
194 static FontWeight toFontWeight(NSInteger appKitFontWeight)
196 ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
197 if (appKitFontWeight > 14)
198 appKitFontWeight = 14;
199 else if (appKitFontWeight < 1)
200 appKitFontWeight = 1;
202 static FontWeight fontWeights[] = {
218 return fontWeights[appKitFontWeight - 1];
221 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
223 DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
224 DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
225 DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
226 DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
227 DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
228 DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
229 DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
231 FontDescription* cachedDesc;
233 switch (cssValueId) {
234 case CSSValueSmallCaption:
235 cachedDesc = &smallSystemFont;
236 if (!smallSystemFont.isAbsoluteSize())
237 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
240 cachedDesc = &menuFont;
241 if (!menuFont.isAbsoluteSize())
242 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
244 case CSSValueStatusBar:
245 cachedDesc = &labelFont;
246 if (!labelFont.isAbsoluteSize())
247 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
249 case CSSValueWebkitMiniControl:
250 cachedDesc = &miniControlFont;
251 if (!miniControlFont.isAbsoluteSize())
252 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
254 case CSSValueWebkitSmallControl:
255 cachedDesc = &smallControlFont;
256 if (!smallControlFont.isAbsoluteSize())
257 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
259 case CSSValueWebkitControl:
260 cachedDesc = &controlFont;
261 if (!controlFont.isAbsoluteSize())
262 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
265 cachedDesc = &systemFont;
266 if (!systemFont.isAbsoluteSize())
267 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
271 NSFontManager *fontManager = [NSFontManager sharedFontManager];
272 cachedDesc->setIsAbsoluteSize(true);
273 cachedDesc->setGenericFamily(FontDescription::NoFamily);
274 cachedDesc->firstFamily().setFamily([font familyName]);
275 cachedDesc->setSpecifiedSize([font pointSize]);
276 cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
277 cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
279 fontDescription = *cachedDesc;
282 static RGBA32 convertNSColorToColor(NSColor *color)
284 NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
285 if (colorInColorSpace) {
286 static const double scaleFactor = nextafter(256.0, 0.0);
287 return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
288 static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
289 static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
292 // This conversion above can fail if the NSColor in question is an NSPatternColor
293 // (as many system colors are). These colors are actually a repeating pattern
294 // not just a solid color. To work around this we simply draw a 1x1 image of
295 // the color and use that pixel's color. It might be better to use an average of
296 // the colors in the pattern instead.
297 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
304 colorSpaceName:NSDeviceRGBColorSpace
308 [NSGraphicsContext saveGraphicsState];
309 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
310 NSEraseRect(NSMakeRect(0, 0, 1, 1));
311 [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
312 [NSGraphicsContext restoreGraphicsState];
315 [offscreenRep getPixel:pixel atX:0 y:0];
317 [offscreenRep release];
319 return makeRGB(pixel[0], pixel[1], pixel[2]);
322 static RGBA32 menuBackgroundColor()
324 NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
331 colorSpaceName:NSDeviceRGBColorSpace
335 CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
336 CGRect rect = CGRectMake(0, 0, 1, 1);
337 HIThemeMenuDrawInfo drawInfo;
338 drawInfo.version = 0;
339 drawInfo.menuType = kThemeMenuTypePopUp;
340 HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
343 [offscreenRep getPixel:pixel atX:0 y:0];
345 [offscreenRep release];
347 return makeRGB(pixel[0], pixel[1], pixel[2]);
350 void RenderThemeMac::platformColorsDidChange()
352 m_systemColorCache.clear();
353 RenderTheme::platformColorsDidChange();
356 Color RenderThemeMac::systemColor(int cssValueId) const
358 if (m_systemColorCache.contains(cssValueId))
359 return m_systemColorCache.get(cssValueId);
362 switch (cssValueId) {
363 case CSSValueActiveborder:
364 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
366 case CSSValueActivecaption:
367 color = convertNSColorToColor([NSColor windowFrameTextColor]);
369 case CSSValueAppworkspace:
370 color = convertNSColorToColor([NSColor headerColor]);
372 case CSSValueBackground:
373 // Use theme independent default
375 case CSSValueButtonface:
376 // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
377 // We may want to change this to use the NSColor in future.
380 case CSSValueButtonhighlight:
381 color = convertNSColorToColor([NSColor controlHighlightColor]);
383 case CSSValueButtonshadow:
384 color = convertNSColorToColor([NSColor controlShadowColor]);
386 case CSSValueButtontext:
387 color = convertNSColorToColor([NSColor controlTextColor]);
389 case CSSValueCaptiontext:
390 color = convertNSColorToColor([NSColor textColor]);
392 case CSSValueGraytext:
393 color = convertNSColorToColor([NSColor disabledControlTextColor]);
395 case CSSValueHighlight:
396 color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
398 case CSSValueHighlighttext:
399 color = convertNSColorToColor([NSColor selectedTextColor]);
401 case CSSValueInactiveborder:
402 color = convertNSColorToColor([NSColor controlBackgroundColor]);
404 case CSSValueInactivecaption:
405 color = convertNSColorToColor([NSColor controlBackgroundColor]);
407 case CSSValueInactivecaptiontext:
408 color = convertNSColorToColor([NSColor textColor]);
410 case CSSValueInfobackground:
411 // There is no corresponding NSColor for this so we use a hard coded value.
414 case CSSValueInfotext:
415 color = convertNSColorToColor([NSColor textColor]);
418 color = menuBackgroundColor();
420 case CSSValueMenutext:
421 color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
423 case CSSValueScrollbar:
424 color = convertNSColorToColor([NSColor scrollBarColor]);
427 color = convertNSColorToColor([NSColor textColor]);
429 case CSSValueThreeddarkshadow:
430 color = convertNSColorToColor([NSColor controlDarkShadowColor]);
432 case CSSValueThreedshadow:
433 color = convertNSColorToColor([NSColor shadowColor]);
435 case CSSValueThreedface:
436 // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
437 // We may want to change this to use the NSColor in future.
440 case CSSValueThreedhighlight:
441 color = convertNSColorToColor([NSColor highlightColor]);
443 case CSSValueThreedlightshadow:
444 color = convertNSColorToColor([NSColor controlLightHighlightColor]);
446 case CSSValueWebkitFocusRingColor:
447 color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
450 color = convertNSColorToColor([NSColor windowBackgroundColor]);
452 case CSSValueWindowframe:
453 color = convertNSColorToColor([NSColor windowFrameColor]);
455 case CSSValueWindowtext:
456 color = convertNSColorToColor([NSColor windowFrameTextColor]);
460 if (!color.isValid())
461 color = RenderTheme::systemColor(cssValueId);
464 m_systemColorCache.set(cssValueId, color.rgb());
469 bool RenderThemeMac::usesTestModeFocusRingColor() const
471 return WebCore::usesTestModeFocusRingColor();
474 NSView* RenderThemeMac::documentViewFor(RenderObject* o) const
477 return ThemeMac::ensuredView(o->view()->frameView());
479 ASSERT_NOT_REACHED();
484 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
485 const FillLayer& background, const Color& backgroundColor) const
487 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
488 return style->border() != border;
490 // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
491 // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
492 // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming
493 // is in effect we treat it like the control is styled.
494 if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
497 return RenderTheme::isControlStyled(style, border, background, backgroundColor);
500 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
502 ControlPart part = o->style()->appearance();
509 case SquareButtonPart:
511 case DefaultButtonPart:
513 case InnerSpinButtonPart:
514 return RenderTheme::adjustRepaintRect(o, r);
520 float zoomLevel = o->style()->effectiveZoom();
522 if (part == MenulistPart) {
523 setPopupButtonCellState(o, r);
524 IntSize size = popupButtonSizes()[[popupButton() controlSize]];
525 size.setHeight(size.height() * zoomLevel);
526 size.setWidth(r.width());
527 r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
531 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
533 // Only do the inflation if the available width/height are too small. Otherwise try to
534 // fit the glow/check space into the available box's width/height.
535 int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
536 int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
538 if (widthDelta < 0) {
539 result.setX(result.x() - margins[leftMargin] * zoomLevel);
540 result.setWidth(result.width() - widthDelta);
542 if (heightDelta < 0) {
543 result.setY(result.y() - margins[topMargin] * zoomLevel);
544 result.setHeight(result.height() - heightDelta);
549 FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
551 FloatRect partRect(inputRect);
553 // Compute an offset between the part renderer and the input renderer
554 FloatSize offsetFromInputRenderer;
555 const RenderObject* renderer = partRenderer;
556 while (renderer && renderer != inputRenderer) {
557 RenderObject* containingRenderer = renderer->container();
558 offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, LayoutPoint());
559 renderer = containingRenderer;
561 // If the input renderer was not a container, something went wrong
562 ASSERT(renderer == inputRenderer);
563 // Move the rect into partRenderer's coords
564 partRect.move(offsetFromInputRenderer);
565 // Account for the local drawing offset (tx, ty)
566 partRect.move(r.x(), r.y());
571 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
573 bool oldIndeterminate = [cell state] == NSMixedState;
574 bool indeterminate = isIndeterminate(o);
575 bool checked = isChecked(o);
577 if (oldIndeterminate != indeterminate) {
578 [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
582 bool oldChecked = [cell state] == NSOnState;
583 if (checked != oldChecked)
584 [cell setState:checked ? NSOnState : NSOffState];
587 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
589 bool oldEnabled = [cell isEnabled];
590 bool enabled = isEnabled(o);
591 if (enabled != oldEnabled)
592 [cell setEnabled:enabled];
595 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
597 bool oldFocused = [cell showsFirstResponder];
598 bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
599 if (focused != oldFocused)
600 [cell setShowsFirstResponder:focused];
603 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
605 bool oldPressed = [cell isHighlighted];
606 bool pressed = (o->node() && o->node()->active());
607 if (pressed != oldPressed)
608 [cell setHighlighted:pressed];
611 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
613 // An alternate way to implement this would be to get the appropriate cell object
614 // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
615 // that would be that we would match AppKit behavior more closely, but a disadvantage
616 // would be that we would rely on an AppKit SPI method.
621 // Checkboxes only have tint when checked.
622 if (o->style()->appearance() == CheckboxPart)
625 // For now assume other controls have tint if enabled.
629 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
631 int fontSize = style->fontSize();
633 return NSRegularControlSize;
635 return NSSmallControlSize;
636 return NSMiniControlSize;
639 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
642 if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
643 minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
644 size = NSRegularControlSize;
645 else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
646 minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
647 size = NSSmallControlSize;
649 size = NSMiniControlSize;
650 if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
651 [cell setControlSize:size];
654 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
656 if (style->effectiveZoom() != 1.0f) {
657 IntSize result = sizes[controlSizeForFont(style)];
658 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
660 return sizes[controlSizeForFont(style)];
663 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
665 if (style->effectiveZoom() != 1.0f) {
666 IntSize result = sizes[controlSizeForSystemFont(style)];
667 return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
669 return sizes[controlSizeForSystemFont(style)];
672 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
674 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
675 IntSize size = sizeForFont(style, sizes);
676 if (style->width().isIntrinsicOrAuto() && size.width() > 0)
677 style->setWidth(Length(size.width(), Fixed));
678 if (style->height().isAuto() && size.height() > 0)
679 style->setHeight(Length(size.height(), Fixed));
682 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
684 FontDescription fontDescription;
685 fontDescription.setIsAbsoluteSize(true);
686 fontDescription.setGenericFamily(FontDescription::SerifFamily);
688 NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
689 fontDescription.firstFamily().setFamily([font familyName]);
690 fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
691 fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
694 style->setLineHeight(RenderStyle::initialLineHeight());
696 if (style->setFontDescription(fontDescription))
697 style->font().update(0);
700 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
702 int fontSize = style->fontSize();
703 if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
704 return NSRegularControlSize;
705 if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
706 return NSSmallControlSize;
707 return NSMiniControlSize;
710 bool RenderThemeMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
712 LocalCurrentGraphicsContext localContext(paintInfo.context);
713 wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
717 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
721 bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
723 if (paintInfo.context->paintingDisabled())
726 LocalCurrentGraphicsContext localContext(paintInfo.context);
727 wkDrawCapsLockIndicator(localContext.cgContext(), r);
732 bool RenderThemeMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
734 LocalCurrentGraphicsContext localContext(paintInfo.context);
735 wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
739 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
743 const int* RenderThemeMac::popupButtonMargins() const
745 static const int margins[3][4] =
751 return margins[[popupButton() controlSize]];
754 const IntSize* RenderThemeMac::popupButtonSizes() const
756 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
760 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
762 static const int padding[3][4] =
768 return padding[size];
771 bool RenderThemeMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
773 LocalCurrentGraphicsContext localContext(paintInfo.context);
774 setPopupButtonCellState(o, r);
776 NSPopUpButtonCell* popupButton = this->popupButton();
778 float zoomLevel = o->style()->effectiveZoom();
779 IntSize size = popupButtonSizes()[[popupButton controlSize]];
780 size.setHeight(size.height() * zoomLevel);
781 size.setWidth(r.width());
783 // Now inflate it to account for the shadow.
784 IntRect inflatedRect = r;
785 if (r.width() >= minimumMenuListSize(o->style()))
786 inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
788 GraphicsContextStateSaver stateSaver(*paintInfo.context);
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);
793 if (zoomLevel != 1.0f) {
794 inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
795 inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
796 paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
797 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
798 paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
801 [popupButton drawWithFrame:inflatedRect inView:documentViewFor(o)];
802 [popupButton setControlView:nil];
807 #if ENABLE(METER_TAG)
809 IntSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
811 if (NoControlPart == renderMeter->style()->appearance())
812 return bounds.size();
814 NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
815 // Makes enough room for cell's intrinsic size.
816 NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
817 return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
818 bounds.height() < cellSize.height ? cellSize.height : bounds.height());
821 bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
823 if (!renderObject->isMeter())
826 LocalCurrentGraphicsContext localContext(paintInfo.context);
828 NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
829 GraphicsContextStateSaver stateSaver(*paintInfo.context);
831 [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
832 [cell setControlView:nil];
836 bool RenderThemeMac::supportsMeter(ControlPart part) const
839 case RelevancyLevelIndicatorPart:
840 case DiscreteCapacityLevelIndicatorPart:
841 case RatingLevelIndicatorPart:
843 case ContinuousCapacityLevelIndicatorPart:
850 NSLevelIndicatorStyle RenderThemeMac::levelIndicatorStyleFor(ControlPart part) const
853 case RelevancyLevelIndicatorPart:
854 return NSRelevancyLevelIndicatorStyle;
855 case DiscreteCapacityLevelIndicatorPart:
856 return NSDiscreteCapacityLevelIndicatorStyle;
857 case RatingLevelIndicatorPart:
858 return NSRatingLevelIndicatorStyle;
860 case ContinuousCapacityLevelIndicatorPart:
862 return NSContinuousCapacityLevelIndicatorStyle;
867 NSLevelIndicatorCell* RenderThemeMac::levelIndicatorFor(const RenderMeter* renderMeter) const
869 RenderStyle* style = renderMeter->style();
870 ASSERT(style->appearance() != NoControlPart);
872 if (!m_levelIndicator)
873 m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
874 NSLevelIndicatorCell* cell = m_levelIndicator.get();
876 HTMLMeterElement* element = static_cast<HTMLMeterElement*>(renderMeter->node());
877 double value = element->value();
879 // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
880 // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
881 switch (element->gaugeRegion()) {
882 case HTMLMeterElement::GaugeRegionOptimum:
883 // Make meter the green
884 [cell setWarningValue:value + 1];
885 [cell setCriticalValue:value + 2];
887 case HTMLMeterElement::GaugeRegionSuboptimal:
888 // Make the meter yellow
889 [cell setWarningValue:value - 1];
890 [cell setCriticalValue:value + 1];
892 case HTMLMeterElement::GaugeRegionEvenLessGood:
893 // Make the meter red
894 [cell setWarningValue:value - 2];
895 [cell setCriticalValue:value - 1];
899 [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
900 [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
901 [cell setMinValue:element->min()];
902 [cell setMaxValue:element->max()];
903 RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
904 [cell setObjectValue:valueObject.get()];
911 #if ENABLE(PROGRESS_TAG)
912 const IntSize* RenderThemeMac::progressBarSizes() const
914 static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) };
918 const int* RenderThemeMac::progressBarMargins(NSControlSize controlSize) const
920 static const int margins[3][4] =
926 return margins[controlSize];
929 int RenderThemeMac::minimumProgressBarHeight(RenderStyle* style) const
931 return sizeForSystemFont(style, progressBarSizes()).height();
934 double RenderThemeMac::animationRepeatIntervalForProgressBar(RenderProgress*) const
936 return progressAnimationFrameRate;
939 double RenderThemeMac::animationDurationForProgressBar(RenderProgress*) const
941 return progressAnimationNumFrames * progressAnimationFrameRate;
944 void RenderThemeMac::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
948 bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
950 if (!renderObject->isProgress())
953 float zoomLevel = renderObject->style()->effectiveZoom();
954 int controlSize = controlSizeForFont(renderObject->style());
955 IntSize size = progressBarSizes()[controlSize];
956 size.setHeight(size.height() * zoomLevel);
957 size.setWidth(rect.width());
959 // Now inflate it to account for the shadow.
960 IntRect inflatedRect = rect;
961 if (rect.height() <= minimumProgressBarHeight(renderObject->style()))
962 inflatedRect = inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel);
964 RenderProgress* renderProgress = toRenderProgress(renderObject);
965 HIThemeTrackDrawInfo trackInfo;
966 trackInfo.version = 0;
967 if (controlSize == NSRegularControlSize)
968 trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
970 trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar;
972 trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size());
974 trackInfo.max = numeric_limits<SInt32>::max();
975 trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
976 trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
977 trackInfo.attributes = kThemeTrackHorizontal;
978 trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
979 trackInfo.reserved = 0;
980 trackInfo.filler1 = 0;
982 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size());
986 ContextContainer cgContextContainer(imageBuffer->context());
987 CGContextRef cgContext = cgContextContainer.context();
988 HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
990 GraphicsContextStateSaver stateSaver(*paintInfo.context);
992 if (!renderProgress->style()->isLeftToRightDirection()) {
993 paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
994 paintInfo.context->scale(FloatSize(-1, 1));
997 paintInfo.context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location());
1002 const float baseFontSize = 11.0f;
1003 const float baseArrowHeight = 4.0f;
1004 const float baseArrowWidth = 5.0f;
1005 const float baseSpaceBetweenArrows = 2.0f;
1006 const int arrowPaddingLeft = 6;
1007 const int arrowPaddingRight = 6;
1008 const int paddingBeforeSeparator = 4;
1009 const int baseBorderRadius = 5;
1010 const int styledPopupPaddingLeft = 8;
1011 const int styledPopupPaddingTop = 1;
1012 const int styledPopupPaddingBottom = 2;
1014 static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1016 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
1017 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
1018 float a = inData[0];
1020 for (i = 0; i < 4; i++)
1021 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1024 static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1026 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
1027 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
1028 float a = inData[0];
1030 for (i = 0; i < 4; i++)
1031 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1034 static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1036 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
1037 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1038 float a = inData[0];
1040 for (i = 0; i < 4; i++)
1041 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1044 static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
1046 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
1047 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
1048 float a = inData[0];
1050 for (i = 0; i < 4; i++)
1051 outData[i] = (1.0f - a) * dark[i] + a * light[i];
1054 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1059 ContextContainer cgContextContainer(paintInfo.context);
1060 CGContextRef context = cgContextContainer.context();
1062 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1064 RoundedRect border = o->style()->getRoundedBorderFor(r);
1065 int radius = border.radii().topLeft().width();
1067 CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
1069 FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
1070 struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
1071 RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
1072 RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false));
1074 FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
1075 struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
1076 RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
1077 RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false));
1079 struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
1080 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1081 RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
1083 RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
1085 RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.maxX(), r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
1088 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1089 CGContextClipToRect(context, r);
1090 paintInfo.context->addRoundedRectClip(border);
1091 context = cgContextContainer.context();
1092 CGContextDrawShading(context, mainShading.get());
1096 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1097 CGContextClipToRect(context, topGradient);
1098 paintInfo.context->addRoundedRectClip(RoundedRect(enclosingLayoutRect(topGradient), border.radii().topLeft(), border.radii().topRight(), IntSize(), IntSize()));
1099 context = cgContextContainer.context();
1100 CGContextDrawShading(context, topShading.get());
1103 if (!bottomGradient.isEmpty()) {
1104 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1105 CGContextClipToRect(context, bottomGradient);
1106 paintInfo.context->addRoundedRectClip(RoundedRect(enclosingLayoutRect(bottomGradient), IntSize(), IntSize(), border.radii().bottomLeft(), border.radii().bottomRight()));
1107 context = cgContextContainer.context();
1108 CGContextDrawShading(context, bottomShading.get());
1112 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1113 CGContextClipToRect(context, r);
1114 paintInfo.context->addRoundedRectClip(border);
1115 context = cgContextContainer.context();
1116 CGContextDrawShading(context, leftShading.get());
1117 CGContextDrawShading(context, rightShading.get());
1121 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1123 IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
1124 r.y() + o->style()->borderTopWidth(),
1125 r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
1126 r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
1127 // Draw the gradients to give the styled popup menu a button appearance
1128 paintMenuListButtonGradients(o, paintInfo, bounds);
1130 // 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
1131 float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
1132 float centerY = bounds.y() + bounds.height() / 2.0f;
1133 float arrowHeight = baseArrowHeight * fontScale;
1134 float arrowWidth = baseArrowWidth * fontScale;
1135 float leftEdge = bounds.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
1136 float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
1138 if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
1141 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1143 paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace());
1144 paintInfo.context->setStrokeStyle(NoStroke);
1146 FloatPoint arrow1[3];
1147 arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
1148 arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
1149 arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
1151 // Draw the top arrow
1152 paintInfo.context->drawConvexPolygon(3, arrow1, true);
1154 FloatPoint arrow2[3];
1155 arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
1156 arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
1157 arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
1159 // Draw the bottom arrow
1160 paintInfo.context->drawConvexPolygon(3, arrow2, true);
1162 Color leftSeparatorColor(0, 0, 0, 40);
1163 Color rightSeparatorColor(255, 255, 255, 40);
1165 // FIXME: Should the separator thickness and space be scaled up by fontScale?
1166 int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
1167 int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
1169 // Draw the separator to the left of the arrows
1170 paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
1171 paintInfo.context->setStrokeStyle(SolidStroke);
1172 paintInfo.context->setStrokeColor(leftSeparatorColor, ColorSpaceDeviceRGB);
1173 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
1174 IntPoint(leftEdgeOfSeparator, bounds.maxY()));
1176 paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB);
1177 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
1178 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
1182 static const IntSize* menuListButtonSizes()
1184 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
1188 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1190 NSControlSize controlSize = controlSizeForFont(style);
1192 style->resetBorder();
1193 style->resetPadding();
1195 // Height is locked to auto.
1196 style->setHeight(Length(Auto));
1198 // White-space is locked to pre
1199 style->setWhiteSpace(PRE);
1201 // Set the foreground color to black or gray when we have the aqua look.
1202 // Cast to RGB32 is to work around a compiler bug.
1203 style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
1205 // Set the button's vertical size.
1206 setSizeFromFont(style, menuListButtonSizes());
1208 // 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
1209 // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
1210 // system font for the control size instead.
1211 setFontFromControlSize(selector, style, controlSize);
1213 style->setBoxShadow(nullptr);
1216 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
1218 if (style->appearance() == MenulistPart)
1219 return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
1220 if (style->appearance() == MenulistButtonPart)
1221 return styledPopupPaddingLeft * style->effectiveZoom();
1225 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
1227 if (style->appearance() == MenulistPart)
1228 return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
1229 if (style->appearance() == MenulistButtonPart) {
1230 float fontScale = style->fontSize() / baseFontSize;
1231 float arrowWidth = baseArrowWidth * fontScale;
1232 return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
1237 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
1239 if (style->appearance() == MenulistPart)
1240 return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
1241 if (style->appearance() == MenulistButtonPart)
1242 return styledPopupPaddingTop * style->effectiveZoom();
1246 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
1248 if (style->appearance() == MenulistPart)
1249 return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
1250 if (style->appearance() == MenulistButtonPart)
1251 return styledPopupPaddingBottom * style->effectiveZoom();
1255 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1257 float fontScale = style->fontSize() / baseFontSize;
1259 style->resetPadding();
1260 style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1262 const int minHeight = 15;
1263 style->setMinHeight(Length(minHeight, Fixed));
1265 style->setLineHeight(RenderStyle::initialLineHeight());
1268 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1270 NSPopUpButtonCell* popupButton = this->popupButton();
1272 // Set the control size based off the rectangle we're painting into.
1273 setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
1275 // Update the various states we respond to.
1276 updateActiveState(popupButton, o);
1277 updateCheckedState(popupButton, o);
1278 updateEnabledState(popupButton, o);
1279 updatePressedState(popupButton, o);
1280 updateFocusedState(popupButton, o);
1283 const IntSize* RenderThemeMac::menuListSizes() const
1285 static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1289 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
1291 return sizeForSystemFont(style, menuListSizes()).width();
1294 const int trackWidth = 5;
1295 const int trackRadius = 2;
1297 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1299 style->setBoxShadow(nullptr);
1302 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1305 float zoomLevel = o->style()->effectiveZoom();
1306 float zoomedTrackWidth = trackWidth * zoomLevel;
1308 if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) {
1309 bounds.setHeight(zoomedTrackWidth);
1310 bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
1311 } else if (o->style()->appearance() == SliderVerticalPart) {
1312 bounds.setWidth(zoomedTrackWidth);
1313 bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
1316 LocalCurrentGraphicsContext localContext(paintInfo.context);
1317 CGContextRef context = localContext.cgContext();
1318 CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
1320 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1321 CGContextClipToRect(context, bounds);
1323 struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
1324 RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1325 RetainPtr<CGShadingRef> mainShading;
1326 if (o->style()->appearance() == SliderVerticalPart)
1327 mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.maxY()), CGPointMake(bounds.maxX(), bounds.maxY()), mainFunction.get(), false, false));
1329 mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.maxY()), mainFunction.get(), false, false));
1331 IntSize radius(trackRadius, trackRadius);
1332 paintInfo.context->addRoundedRectClip(RoundedRect(bounds, radius, radius, radius, radius));
1333 context = localContext.cgContext();
1334 CGContextDrawShading(context, mainShading.get());
1339 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
1341 RenderTheme::adjustSliderThumbStyle(selector, style, element);
1342 style->setBoxShadow(nullptr);
1345 const float verticalSliderHeightPadding = 0.1f;
1347 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1349 NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
1350 ? sliderThumbVertical()
1351 : sliderThumbHorizontal();
1353 LocalCurrentGraphicsContext localContext(paintInfo.context);
1355 // Update the various states we respond to.
1356 updateActiveState(sliderThumbCell, o);
1357 updateEnabledState(sliderThumbCell, o);
1358 updateFocusedState(sliderThumbCell, (o->node() && o->node()->focusDelegate()->renderer()) ? o->node()->focusDelegate()->renderer() : o);
1360 // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
1362 if (o->style()->appearance() == SliderThumbVerticalPart)
1363 oldPressed = m_isSliderThumbVerticalPressed;
1365 oldPressed = m_isSliderThumbHorizontalPressed;
1367 bool pressed = isPressed(o);
1369 if (o->style()->appearance() == SliderThumbVerticalPart)
1370 m_isSliderThumbVerticalPressed = pressed;
1372 m_isSliderThumbHorizontalPressed = pressed;
1374 if (pressed != oldPressed) {
1376 [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
1378 [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
1381 FloatRect bounds = r;
1382 // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
1383 if (o->style()->appearance() == SliderThumbVerticalPart)
1384 bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
1386 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1387 float zoomLevel = o->style()->effectiveZoom();
1389 FloatRect unzoomedRect = bounds;
1390 if (zoomLevel != 1.0f) {
1391 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1392 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1393 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1394 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1395 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1399 // Workaround for <rdar://problem/9421781>.
1400 if (!o->view()->frameView()->documentView()) {
1401 paintInfo.context->translate(0, unzoomedRect.y());
1402 paintInfo.context->scale(FloatSize(1, -1));
1403 paintInfo.context->translate(0, -(unzoomedRect.y() + unzoomedRect.height()));
1405 #elif PLATFORM(CHROMIUM)
1406 paintInfo.context->translate(0, unzoomedRect.y());
1407 paintInfo.context->scale(FloatSize(1, -1));
1408 paintInfo.context->translate(0, -(unzoomedRect.y() + unzoomedRect.height()));
1411 [sliderThumbCell drawInteriorWithFrame:unzoomedRect inView:documentViewFor(o)];
1412 [sliderThumbCell setControlView:nil];
1417 bool RenderThemeMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1419 LocalCurrentGraphicsContext localContext(paintInfo.context);
1420 NSSearchFieldCell* search = this->search();
1422 setSearchCellState(o, r);
1424 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1426 float zoomLevel = o->style()->effectiveZoom();
1428 IntRect unzoomedRect = r;
1430 if (zoomLevel != 1.0f) {
1431 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1432 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1433 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1434 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1435 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1438 // Set the search button to nil before drawing. Then reset it so we can draw it later.
1439 [search setSearchButtonCell:nil];
1441 [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)];
1443 [search setControlView:nil];
1444 [search resetSearchButtonCell];
1449 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
1451 NSSearchFieldCell* search = this->search();
1453 [search setControlSize:controlSizeForFont(o->style())];
1455 // Update the various states we respond to.
1456 updateActiveState(search, o);
1457 updateEnabledState(search, o);
1458 updateFocusedState(search, o);
1461 const IntSize* RenderThemeMac::searchFieldSizes() const
1463 static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
1467 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
1469 // If the width and height are both specified, then we have nothing to do.
1470 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1473 // Use the font size to determine the intrinsic width of the control.
1474 setSizeFromFont(style, searchFieldSizes());
1477 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
1480 style->resetBorder();
1481 const short borderWidth = 2 * style->effectiveZoom();
1482 style->setBorderLeftWidth(borderWidth);
1483 style->setBorderLeftStyle(INSET);
1484 style->setBorderRightWidth(borderWidth);
1485 style->setBorderRightStyle(INSET);
1486 style->setBorderBottomWidth(borderWidth);
1487 style->setBorderBottomStyle(INSET);
1488 style->setBorderTopWidth(borderWidth);
1489 style->setBorderTopStyle(INSET);
1492 style->setHeight(Length(Auto));
1493 setSearchFieldSize(style);
1495 // Override padding size to match AppKit text positioning.
1496 const int padding = 1 * style->effectiveZoom();
1497 style->setPaddingLeft(Length(padding, Fixed));
1498 style->setPaddingRight(Length(padding, Fixed));
1499 style->setPaddingTop(Length(padding, Fixed));
1500 style->setPaddingBottom(Length(padding, Fixed));
1502 NSControlSize controlSize = controlSizeForFont(style);
1503 setFontFromControlSize(selector, style, controlSize);
1505 style->setBoxShadow(nullptr);
1508 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1510 Node* input = o->node()->shadowAncestorNode();
1511 if (!input->renderer()->isBox())
1514 LocalCurrentGraphicsContext localContext(paintInfo.context);
1515 setSearchCellState(input->renderer(), r);
1517 NSSearchFieldCell* search = this->search();
1519 updateActiveState([search cancelButtonCell], o);
1520 updatePressedState([search cancelButtonCell], o);
1522 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1524 float zoomLevel = o->style()->effectiveZoom();
1526 FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1528 #if ENABLE(INPUT_SPEECH)
1529 // Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
1530 // when speech input is enabled for the input element.
1531 IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
1532 int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
1533 int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
1534 localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
1537 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1539 FloatRect unzoomedRect(localBounds);
1540 if (zoomLevel != 1.0f) {
1541 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1542 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1543 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1544 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1545 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1548 [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1549 [[search cancelButtonCell] setControlView:nil];
1553 const IntSize* RenderThemeMac::cancelButtonSizes() const
1555 static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1559 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1561 IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1562 style->setWidth(Length(size.width(), Fixed));
1563 style->setHeight(Length(size.height(), Fixed));
1564 style->setBoxShadow(nullptr);
1567 const IntSize* RenderThemeMac::resultsButtonSizes() const
1569 static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1573 const int emptyResultsOffset = 9;
1574 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1576 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1577 style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1578 style->setHeight(Length(size.height(), Fixed));
1579 style->setBoxShadow(nullptr);
1582 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
1587 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1589 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1590 style->setWidth(Length(size.width(), Fixed));
1591 style->setHeight(Length(size.height(), Fixed));
1592 style->setBoxShadow(nullptr);
1595 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1597 Node* input = o->node()->shadowAncestorNode();
1598 if (!input->renderer()->isBox())
1601 LocalCurrentGraphicsContext localContext(paintInfo.context);
1602 setSearchCellState(input->renderer(), r);
1604 NSSearchFieldCell* search = this->search();
1606 if ([search searchMenuTemplate] != nil)
1607 [search setSearchMenuTemplate:nil];
1609 updateActiveState([search searchButtonCell], o);
1611 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1612 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1614 [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
1615 [[search searchButtonCell] setControlView:nil];
1619 const int resultsArrowWidth = 5;
1620 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1622 IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1623 style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1624 style->setHeight(Length(size.height(), Fixed));
1625 style->setBoxShadow(nullptr);
1628 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1630 Node* input = o->node()->shadowAncestorNode();
1631 if (!input->renderer()->isBox())
1634 LocalCurrentGraphicsContext localContext(paintInfo.context);
1635 setSearchCellState(input->renderer(), r);
1637 NSSearchFieldCell* search = this->search();
1639 updateActiveState([search searchButtonCell], o);
1641 if (![search searchMenuTemplate])
1642 [search setSearchMenuTemplate:searchMenuTemplate()];
1644 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1645 float zoomLevel = o->style()->effectiveZoom();
1647 FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1648 localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1650 IntRect unzoomedRect(localBounds);
1651 if (zoomLevel != 1.0f) {
1652 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1653 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1654 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1655 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1656 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1659 [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1660 [[search searchButtonCell] setControlView:nil];
1667 MediaControllerThemeClassic = 1,
1668 MediaControllerThemeQuickTime = 2
1669 } MediaControllerThemeStyle;
1671 static int mediaControllerTheme()
1673 static int controllerTheme = -1;
1675 if (controllerTheme != -1)
1676 return controllerTheme;
1678 controllerTheme = MediaControllerThemeClassic;
1681 Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
1683 if (validKey && !useQTMediaUIPref)
1684 return controllerTheme;
1686 controllerTheme = MediaControllerThemeQuickTime;
1687 return controllerTheme;
1691 const int sliderThumbWidth = 15;
1692 const int sliderThumbHeight = 15;
1693 const int mediaSliderThumbWidth = 13;
1694 const int mediaSliderThumbHeight = 14;
1696 void RenderThemeMac::adjustSliderThumbSize(RenderStyle* style) const
1698 float zoomLevel = style->effectiveZoom();
1699 if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) {
1700 style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
1701 style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
1705 adjustMediaSliderThumbSize(style);
1711 void RenderThemeMac::adjustMediaSliderThumbSize(RenderStyle* style) const
1713 ControlPart part = style->appearance();
1715 if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart) {
1716 int width = mediaSliderThumbWidth;
1717 int height = mediaSliderThumbHeight;
1719 if (mediaControllerTheme() == MediaControllerThemeQuickTime) {
1722 wkMeasureMediaUIPart(part == MediaSliderThumbPart ? MediaSliderThumb : MediaVolumeSliderThumb, MediaControllerThemeQuickTime, NULL, &size);
1724 height = size.height;
1727 float zoomLevel = style->effectiveZoom();
1728 style->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
1729 style->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
1733 enum WKMediaControllerThemeState {
1734 MediaUIPartDisabledFlag = 1 << 0,
1735 MediaUIPartPressedFlag = 1 << 1,
1736 MediaUIPartDrawEndCapsFlag = 1 << 3,
1739 static unsigned getMediaUIPartStateFlags(Node* node)
1743 if (node->disabled())
1744 flags |= MediaUIPartDisabledFlag;
1745 else if (node->active())
1746 flags |= MediaUIPartPressedFlag;
1750 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
1751 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect)
1753 float zoomLevel = o->style()->effectiveZoom();
1754 FloatRect unzoomedRect(originalRect);
1755 if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) {
1756 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1757 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1758 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1759 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1760 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1762 return unzoomedRect;
1766 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1768 Node* node = o->node();
1772 LocalCurrentGraphicsContext localContext(paintInfo.context);
1773 wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1777 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1779 Node* node = o->node();
1780 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1781 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1784 if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(node)) {
1785 LocalCurrentGraphicsContext localContext(paintInfo.context);
1786 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1792 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1794 Node* node = o->node();
1795 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1796 if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1799 if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
1800 LocalCurrentGraphicsContext localContext(paintInfo.context);
1801 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1806 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1808 Node* node = o->node();
1812 LocalCurrentGraphicsContext localContext(paintInfo.context);
1813 wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1817 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1819 Node* node = o->node();
1823 LocalCurrentGraphicsContext localContext(paintInfo.context);
1824 wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1828 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1830 Node* node = o->node();
1831 Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1832 if (!mediaNode || !mediaNode->isElementNode() || !static_cast<Element*>(mediaNode)->isMediaElement())
1835 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1839 RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
1840 ExceptionCode ignoredException;
1841 float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0;
1842 float currentTime = mediaElement->currentTime();
1843 float duration = mediaElement->duration();
1844 if (isnan(duration))
1847 ContextContainer cgContextContainer(paintInfo.context);
1848 CGContextRef context = cgContextContainer.context();
1849 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1850 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1851 wkDrawMediaSliderTrack(mediaControllerTheme(), context, unzoomedRect,
1852 timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
1856 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1858 Node* node = o->node();
1862 LocalCurrentGraphicsContext localContext(paintInfo.context);
1863 wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1867 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1869 Node* node = o->node();
1873 LocalCurrentGraphicsContext localContext(paintInfo.context);
1874 wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1878 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1880 Node* node = o->node();
1884 LocalCurrentGraphicsContext localContext(paintInfo.context);
1885 wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1889 bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1891 HTMLInputElement* node = static_cast<HTMLInputElement*>(o->node());
1895 MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(node);
1899 LocalCurrentGraphicsContext localContext(paintInfo.context);
1900 wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1905 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1907 Node* node = o->node();
1911 LocalCurrentGraphicsContext localContext(paintInfo.context);
1912 wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1916 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1918 Node* node = o->node();
1922 ContextContainer cgContextContainer(paintInfo.context);
1923 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1924 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1925 wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node));
1929 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1931 Node* node = o->node();
1935 ContextContainer cgContextContainer(paintInfo.context);
1936 GraphicsContextStateSaver stateSaver(*paintInfo.context);
1937 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1938 wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), cgContextContainer.context(), unzoomedRect, getMediaUIPartStateFlags(node));
1942 bool RenderThemeMac::paintMediaVolumeSliderContainer(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1944 Node* node = o->node();
1948 LocalCurrentGraphicsContext localContext(paintInfo.context);
1949 wkDrawMediaUIPart(MediaVolumeSliderContainer, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1953 bool RenderThemeMac::paintMediaVolumeSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1955 Node* node = o->node();
1959 LocalCurrentGraphicsContext localContext(paintInfo.context);
1960 wkDrawMediaUIPart(MediaVolumeSlider, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1964 bool RenderThemeMac::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1966 Node* node = o->node();
1970 LocalCurrentGraphicsContext localContext(paintInfo.context);
1971 wkDrawMediaUIPart(MediaVolumeSliderThumb, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
1975 String RenderThemeMac::extraMediaControlsStyleSheet()
1978 if (mediaControllerTheme() == MediaControllerThemeQuickTime)
1979 return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
1983 ASSERT_NOT_REACHED();
1988 #if ENABLE(FULLSCREEN_API)
1989 String RenderThemeMac::extraFullScreenStyleSheet()
1992 if (mediaControllerTheme() == MediaControllerThemeQuickTime)
1993 return String(fullscreenQuickTimeUserAgentStyleSheet, sizeof(fullscreenQuickTimeUserAgentStyleSheet));
1997 ASSERT_NOT_REACHED();
2003 bool RenderThemeMac::hasOwnDisabledStateHandlingFor(ControlPart part) const
2005 if (part == MediaMuteButtonPart)
2008 return mediaControllerTheme() == MediaControllerThemeClassic;
2011 bool RenderThemeMac::usesMediaControlStatusDisplay()
2013 return mediaControllerTheme() == MediaControllerThemeQuickTime;
2016 bool RenderThemeMac::usesMediaControlVolumeSlider() const
2018 return mediaControllerTheme() == MediaControllerThemeQuickTime;
2021 IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
2023 return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
2026 bool RenderThemeMac::shouldShowPlaceholderWhenFocused() const
2028 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
2035 #endif // ENABLE(VIDEO)
2037 NSPopUpButtonCell* RenderThemeMac::popupButton() const
2039 if (!m_popupButton) {
2040 m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
2041 [m_popupButton.get() setUsesItemFromMenu:NO];
2042 [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
2045 return m_popupButton.get();
2048 NSSearchFieldCell* RenderThemeMac::search() const
2051 m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
2052 [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
2053 [m_search.get() setBezeled:YES];
2054 [m_search.get() setEditable:YES];
2055 [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
2058 return m_search.get();
2061 NSMenu* RenderThemeMac::searchMenuTemplate() const
2063 if (!m_searchMenuTemplate)
2064 m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
2066 return m_searchMenuTemplate.get();
2069 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
2071 if (!m_sliderThumbHorizontal) {
2072 m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
2073 [m_sliderThumbHorizontal.get() setTitle:nil];
2074 [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
2075 [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
2076 [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
2079 return m_sliderThumbHorizontal.get();
2082 NSSliderCell* RenderThemeMac::sliderThumbVertical() const
2084 if (!m_sliderThumbVertical) {
2085 m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
2086 [m_sliderThumbVertical.get() setTitle:nil];
2087 [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
2088 [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
2089 [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
2092 return m_sliderThumbVertical.get();
2095 String RenderThemeMac::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width)
2100 String strToTruncate;
2101 if (filenames.isEmpty())
2102 strToTruncate = fileButtonNoFileSelectedLabel();
2103 else if (filenames.size() == 1)
2104 strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(filenames[0])];
2106 return StringTruncator::rightTruncate(multipleFileUploadText(filenames.size()), width, font, StringTruncator::EnableRoundingHacks);
2108 return StringTruncator::centerTruncate(strToTruncate, width, font, StringTruncator::EnableRoundingHacks);
2111 } // namespace WebCore