2009-07-10 Eric Carlson <eric.carlson@apple.com>
[WebKit.git] / WebCore / rendering / RenderThemeMac.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #import "config.h"
21 #import "RenderThemeMac.h"
22
23 #import "BitmapImage.h"
24 #import "ColorMac.h"
25 #import "CSSStyleSelector.h"
26 #import "CSSValueKeywords.h"
27 #import "Document.h"
28 #import "Element.h"
29 #import "FrameView.h"
30 #import "GraphicsContext.h"
31 #import "HTMLInputElement.h"
32 #import "HTMLMediaElement.h"
33 #import "HTMLNames.h"
34 #import "Image.h"
35 #import "LocalCurrentGraphicsContext.h"
36 #import "MediaControlElements.h"
37 #import "RenderMedia.h"
38 #import "RenderSlider.h"
39 #import "RenderView.h"
40 #import "SharedBuffer.h"
41 #import "WebCoreSystemInterface.h"
42 #import "UserAgentStyleSheets.h"
43 #import <Carbon/Carbon.h>
44 #import <Cocoa/Cocoa.h>
45 #import <wtf/RetainPtr.h>
46 #import <wtf/StdLibExtras.h>
47 #import <math.h>
48
49 #ifdef BUILDING_ON_TIGER
50 typedef int NSInteger;
51 typedef unsigned NSUInteger;
52 #endif
53
54 using std::min;
55
56 // The methods in this file are specific to the Mac OS X platform.
57
58 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. 
59
60 @interface WebCoreRenderThemeNotificationObserver : NSObject
61 {
62     WebCore::RenderTheme *_theme;
63 }
64
65 - (id)initWithTheme:(WebCore::RenderTheme *)theme;
66 - (void)systemColorsDidChange:(NSNotification *)notification;
67
68 @end
69
70 @implementation WebCoreRenderThemeNotificationObserver
71
72 - (id)initWithTheme:(WebCore::RenderTheme *)theme
73 {
74     [super init];
75     _theme = theme;
76     
77     return self;
78 }
79
80 - (void)systemColorsDidChange:(NSNotification *)unusedNotification
81 {
82     ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
83     _theme->platformColorsDidChange();
84 }
85
86 @end
87
88 namespace WebCore {
89
90 using namespace HTMLNames;
91
92 enum {
93     topMargin,
94     rightMargin,
95     bottomMargin,
96     leftMargin
97 };
98
99 enum {
100     topPadding,
101     rightPadding,
102     bottomPadding,
103     leftPadding
104 };
105
106 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
107 {
108     static RenderTheme* rt = RenderThemeMac::create().releaseRef();
109     return rt;
110 }
111
112 PassRefPtr<RenderTheme> RenderThemeMac::create()
113 {
114     return adoptRef(new RenderThemeMac);
115 }
116
117 RenderThemeMac::RenderThemeMac()
118     : m_isSliderThumbHorizontalPressed(false)
119     , m_isSliderThumbVerticalPressed(false)
120     , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
121 {
122     [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
123                                                         selector:@selector(systemColorsDidChange:)
124                                                             name:NSSystemColorsDidChangeNotification
125                                                           object:nil];
126 }
127
128 RenderThemeMac::~RenderThemeMac()
129 {
130     [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
131 }
132
133 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
134 {
135     NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
136     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
137 }
138
139 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
140 {
141     NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
142     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
143 }
144
145 Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const
146 {
147     NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
148     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
149 }
150
151 Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
152 {
153     return Color::white;
154 }
155
156 Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
157 {
158     return Color::black;
159 }
160
161 Color RenderThemeMac::platformFocusRingColor() const
162 {
163     if (usesTestModeFocusRingColor())
164         return oldAquaFocusRingColor();
165
166     return systemColor(CSSValueWebkitFocusRingColor);
167 }
168
169 Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
170 {
171     return platformInactiveSelectionBackgroundColor();
172 }
173
174 static FontWeight toFontWeight(NSInteger appKitFontWeight)
175 {
176     ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
177     if (appKitFontWeight > 14)
178         appKitFontWeight = 14;
179     else if (appKitFontWeight < 1)
180         appKitFontWeight = 1;
181
182     static FontWeight fontWeights[] = {
183         FontWeight100,
184         FontWeight100,
185         FontWeight200,
186         FontWeight300,
187         FontWeight400,
188         FontWeight500,
189         FontWeight600,
190         FontWeight600,
191         FontWeight700,
192         FontWeight800,
193         FontWeight800,
194         FontWeight900,
195         FontWeight900,
196         FontWeight900
197     };
198     return fontWeights[appKitFontWeight - 1];
199 }
200
201 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
202 {
203     DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
204     DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
205     DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
206     DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
207     DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
208     DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
209     DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
210
211     FontDescription* cachedDesc;
212     NSFont* font = nil;
213     switch (cssValueId) {
214         case CSSValueSmallCaption:
215             cachedDesc = &smallSystemFont;
216             if (!smallSystemFont.isAbsoluteSize())
217                 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
218             break;
219         case CSSValueMenu:
220             cachedDesc = &menuFont;
221             if (!menuFont.isAbsoluteSize())
222                 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
223             break;
224         case CSSValueStatusBar:
225             cachedDesc = &labelFont;
226             if (!labelFont.isAbsoluteSize())
227                 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
228             break;
229         case CSSValueWebkitMiniControl:
230             cachedDesc = &miniControlFont;
231             if (!miniControlFont.isAbsoluteSize())
232                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
233             break;
234         case CSSValueWebkitSmallControl:
235             cachedDesc = &smallControlFont;
236             if (!smallControlFont.isAbsoluteSize())
237                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
238             break;
239         case CSSValueWebkitControl:
240             cachedDesc = &controlFont;
241             if (!controlFont.isAbsoluteSize())
242                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
243             break;
244         default:
245             cachedDesc = &systemFont;
246             if (!systemFont.isAbsoluteSize())
247                 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
248     }
249
250     if (font) {
251         NSFontManager *fontManager = [NSFontManager sharedFontManager];
252         cachedDesc->setIsAbsoluteSize(true);
253         cachedDesc->setGenericFamily(FontDescription::NoFamily);
254         cachedDesc->firstFamily().setFamily([font familyName]);
255         cachedDesc->setSpecifiedSize([font pointSize]);
256         cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
257         cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
258     }
259     fontDescription = *cachedDesc;
260 }
261
262 static RGBA32 convertNSColorToColor(NSColor *color)
263 {
264     NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
265     if (colorInColorSpace) {
266         static const double scaleFactor = nextafter(256.0, 0.0);
267         return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
268             static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
269             static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
270     }
271
272     // This conversion above can fail if the NSColor in question is an NSPatternColor 
273     // (as many system colors are). These colors are actually a repeating pattern
274     // not just a solid color. To work around this we simply draw a 1x1 image of
275     // the color and use that pixel's color. It might be better to use an average of
276     // the colors in the pattern instead.
277     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
278                                                                              pixelsWide:1
279                                                                              pixelsHigh:1
280                                                                           bitsPerSample:8
281                                                                         samplesPerPixel:4
282                                                                                hasAlpha:YES
283                                                                                isPlanar:NO
284                                                                          colorSpaceName:NSDeviceRGBColorSpace
285                                                                             bytesPerRow:4
286                                                                            bitsPerPixel:32];
287
288     [NSGraphicsContext saveGraphicsState];
289     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
290     NSEraseRect(NSMakeRect(0, 0, 1, 1));
291     [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
292     [NSGraphicsContext restoreGraphicsState];
293
294     NSUInteger pixel[4];
295     [offscreenRep getPixel:pixel atX:0 y:0];
296
297     [offscreenRep release];
298
299     return makeRGB(pixel[0], pixel[1], pixel[2]);
300 }
301
302 static RGBA32 menuBackgroundColor()
303 {
304     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
305                                                                              pixelsWide:1
306                                                                              pixelsHigh:1
307                                                                           bitsPerSample:8
308                                                                         samplesPerPixel:4
309                                                                                hasAlpha:YES
310                                                                                isPlanar:NO
311                                                                          colorSpaceName:NSDeviceRGBColorSpace
312                                                                             bytesPerRow:4
313                                                                            bitsPerPixel:32];
314
315     CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
316     CGRect rect = CGRectMake(0, 0, 1, 1);
317     HIThemeMenuDrawInfo drawInfo;
318     drawInfo.version =  0;
319     drawInfo.menuType = kThemeMenuTypePopUp;
320     HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
321
322     NSUInteger pixel[4];
323     [offscreenRep getPixel:pixel atX:0 y:0];
324
325     [offscreenRep release];
326
327     return makeRGB(pixel[0], pixel[1], pixel[2]);
328 }
329
330 void RenderThemeMac::platformColorsDidChange()
331 {
332     m_systemColorCache.clear();
333     RenderTheme::platformColorsDidChange();
334 }
335
336 Color RenderThemeMac::systemColor(int cssValueId) const
337 {
338     if (m_systemColorCache.contains(cssValueId))
339         return m_systemColorCache.get(cssValueId);
340     
341     Color color;
342     switch (cssValueId) {
343         case CSSValueActiveborder:
344             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
345             break;
346         case CSSValueActivecaption:
347             color = convertNSColorToColor([NSColor windowFrameTextColor]);
348             break;
349         case CSSValueAppworkspace:
350             color = convertNSColorToColor([NSColor headerColor]);
351             break;
352         case CSSValueBackground:
353             // Use theme independent default
354             break;
355         case CSSValueButtonface:
356             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
357             // We may want to change this to use the NSColor in future.
358             color = 0xFFC0C0C0;
359             break;
360         case CSSValueButtonhighlight:
361             color = convertNSColorToColor([NSColor controlHighlightColor]);
362             break;
363         case CSSValueButtonshadow:
364             color = convertNSColorToColor([NSColor controlShadowColor]);
365             break;
366         case CSSValueButtontext:
367             color = convertNSColorToColor([NSColor controlTextColor]);
368             break;
369         case CSSValueCaptiontext:
370             color = convertNSColorToColor([NSColor textColor]);
371             break;
372         case CSSValueGraytext:
373             color = convertNSColorToColor([NSColor disabledControlTextColor]);
374             break;
375         case CSSValueHighlight:
376             color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
377             break;
378         case CSSValueHighlighttext:
379             color = convertNSColorToColor([NSColor selectedTextColor]);
380             break;
381         case CSSValueInactiveborder:
382             color = convertNSColorToColor([NSColor controlBackgroundColor]);
383             break;
384         case CSSValueInactivecaption:
385             color = convertNSColorToColor([NSColor controlBackgroundColor]);
386             break;
387         case CSSValueInactivecaptiontext:
388             color = convertNSColorToColor([NSColor textColor]);
389             break;
390         case CSSValueInfobackground:
391             // There is no corresponding NSColor for this so we use a hard coded value.
392             color = 0xFFFBFCC5;
393             break;
394         case CSSValueInfotext:
395             color = convertNSColorToColor([NSColor textColor]);
396             break;
397         case CSSValueMenu:
398             color = menuBackgroundColor();
399             break;
400         case CSSValueMenutext:
401             color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
402             break;
403         case CSSValueScrollbar:
404             color = convertNSColorToColor([NSColor scrollBarColor]);
405             break;
406         case CSSValueText:
407             color = convertNSColorToColor([NSColor textColor]);
408             break;
409         case CSSValueThreeddarkshadow:
410             color = convertNSColorToColor([NSColor controlDarkShadowColor]);
411             break;
412         case CSSValueThreedshadow:
413             color = convertNSColorToColor([NSColor shadowColor]);
414             break;
415         case CSSValueThreedface:
416             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
417             // We may want to change this to use the NSColor in future.
418             color = 0xFFC0C0C0;
419             break;
420         case CSSValueThreedhighlight:
421             color = convertNSColorToColor([NSColor highlightColor]);
422             break;
423         case CSSValueThreedlightshadow:
424             color = convertNSColorToColor([NSColor controlLightHighlightColor]);
425             break;
426         case CSSValueWebkitFocusRingColor:
427             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
428             break;
429         case CSSValueWindow:
430             color = convertNSColorToColor([NSColor windowBackgroundColor]);
431             break;
432         case CSSValueWindowframe:
433             color = convertNSColorToColor([NSColor windowFrameColor]);
434             break;
435         case CSSValueWindowtext:
436             color = convertNSColorToColor([NSColor windowFrameTextColor]);
437             break;
438     }
439
440     if (!color.isValid())
441         color = RenderTheme::systemColor(cssValueId);
442
443     if (color.isValid())
444         m_systemColorCache.set(cssValueId, color.rgb());
445
446     return color;
447 }
448
449 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
450                                      const FillLayer& background, const Color& backgroundColor) const
451 {
452     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
453         return style->border() != border;
454         
455     // FIXME: This is horrible, but there is not much else that can be done.  Menu lists cannot draw properly when
456     // scaled.  They can't really draw properly when transformed either.  We can't detect the transform case at style
457     // adjustment time so that will just have to stay broken.  We can however detect that we're zooming.  If zooming
458     // is in effect we treat it like the control is styled.
459     if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
460         return true;
461
462     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
463 }
464
465 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
466 {
467     ControlPart part = o->style()->appearance();
468     
469 #if USE(NEW_THEME)
470     switch (part) {
471         case CheckboxPart:
472         case RadioPart:
473         case PushButtonPart:
474         case SquareButtonPart:
475         case DefaultButtonPart:
476         case ButtonPart:
477             return RenderTheme::adjustRepaintRect(o, r);
478         default:
479             break;
480     }
481 #endif
482
483     float zoomLevel = o->style()->effectiveZoom();
484
485     if (part == MenulistPart) {
486         setPopupButtonCellState(o, r);
487         IntSize size = popupButtonSizes()[[popupButton() controlSize]];
488         size.setHeight(size.height() * zoomLevel);
489         size.setWidth(r.width());
490         r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
491     }
492 }
493
494 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
495 {
496     // Only do the inflation if the available width/height are too small.  Otherwise try to
497     // fit the glow/check space into the available box's width/height.
498     int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
499     int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
500     IntRect result(r);
501     if (widthDelta < 0) {
502         result.setX(result.x() - margins[leftMargin] * zoomLevel);
503         result.setWidth(result.width() - widthDelta);
504     }
505     if (heightDelta < 0) {
506         result.setY(result.y() - margins[topMargin] * zoomLevel);
507         result.setHeight(result.height() - heightDelta);
508     }
509     return result;
510 }
511
512 FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
513 {
514     FloatRect partRect(inputRect);
515     
516     // Compute an offset between the part renderer and the input renderer
517     FloatSize offsetFromInputRenderer;
518     const RenderObject* renderer = partRenderer;
519     while (renderer && renderer != inputRenderer) {
520         RenderObject* containingRenderer = renderer->container();
521         offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer);
522         renderer = containingRenderer;
523     }
524     // If the input renderer was not a container, something went wrong
525     ASSERT(renderer == inputRenderer);
526     // Move the rect into partRenderer's coords
527     partRect.move(offsetFromInputRenderer);
528     // Account for the local drawing offset (tx, ty)
529     partRect.move(r.x(), r.y());
530
531     return partRect;
532 }
533
534 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
535 {
536     bool oldIndeterminate = [cell state] == NSMixedState;
537     bool indeterminate = isIndeterminate(o);
538     bool checked = isChecked(o);
539
540     if (oldIndeterminate != indeterminate) {
541         [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
542         return;
543     }
544
545     bool oldChecked = [cell state] == NSOnState;
546     if (checked != oldChecked)
547         [cell setState:checked ? NSOnState : NSOffState];
548 }
549
550 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
551 {
552     bool oldEnabled = [cell isEnabled];
553     bool enabled = isEnabled(o);
554     if (enabled != oldEnabled)
555         [cell setEnabled:enabled];
556 }
557
558 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
559 {
560     bool oldFocused = [cell showsFirstResponder];
561     bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
562     if (focused != oldFocused)
563         [cell setShowsFirstResponder:focused];
564 }
565
566 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
567 {
568     bool oldPressed = [cell isHighlighted];
569     bool pressed = (o->node() && o->node()->active());
570     if (pressed != oldPressed)
571         [cell setHighlighted:pressed];
572 }
573
574 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
575 {
576     // An alternate way to implement this would be to get the appropriate cell object
577     // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
578     // that would be that we would match AppKit behavior more closely, but a disadvantage
579     // would be that we would rely on an AppKit SPI method.
580
581     if (!isEnabled(o))
582         return false;
583
584     // Checkboxes only have tint when checked.
585     if (o->style()->appearance() == CheckboxPart)
586         return isChecked(o);
587
588     // For now assume other controls have tint if enabled.
589     return true;
590 }
591
592 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
593 {
594     int fontSize = style->fontSize();
595     if (fontSize >= 16)
596         return NSRegularControlSize;
597     if (fontSize >= 11)
598         return NSSmallControlSize;
599     return NSMiniControlSize;
600 }
601
602 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
603 {
604     NSControlSize size;
605     if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
606         minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
607         size = NSRegularControlSize;
608     else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
609              minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
610         size = NSSmallControlSize;
611     else
612         size = NSMiniControlSize;
613     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
614         [cell setControlSize:size];
615 }
616
617 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
618 {
619     if (style->effectiveZoom() != 1.0f) {
620         IntSize result = sizes[controlSizeForFont(style)];
621         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
622     }
623     return sizes[controlSizeForFont(style)];
624 }
625
626 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
627 {
628     if (style->effectiveZoom() != 1.0f) {
629         IntSize result = sizes[controlSizeForSystemFont(style)];
630         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
631     }
632     return sizes[controlSizeForSystemFont(style)];
633 }
634
635 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
636 {
637     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
638     IntSize size = sizeForFont(style, sizes);
639     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
640         style->setWidth(Length(size.width(), Fixed));
641     if (style->height().isAuto() && size.height() > 0)
642         style->setHeight(Length(size.height(), Fixed));
643 }
644
645 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
646 {
647     FontDescription fontDescription;
648     fontDescription.setIsAbsoluteSize(true);
649     fontDescription.setGenericFamily(FontDescription::SerifFamily);
650
651     NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
652     fontDescription.firstFamily().setFamily([font familyName]);
653     fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
654     fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
655
656     // Reset line height
657     style->setLineHeight(RenderStyle::initialLineHeight());
658
659     if (style->setFontDescription(fontDescription))
660         style->font().update(0);
661 }
662
663 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
664 {
665     int fontSize = style->fontSize();
666     if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
667         return NSRegularControlSize;
668     if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
669         return NSSmallControlSize;
670     return NSMiniControlSize;
671 }
672
673 bool RenderThemeMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
674 {
675     LocalCurrentGraphicsContext localContext(paintInfo.context);
676     wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
677     return false;
678 }
679
680 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
681 {
682 }
683
684 bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
685 {
686     if (paintInfo.context->paintingDisabled())
687         return true;
688
689     LocalCurrentGraphicsContext localContext(paintInfo.context);
690     wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
691     
692     return false;
693 }
694
695 bool RenderThemeMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
696 {
697     LocalCurrentGraphicsContext localContext(paintInfo.context);
698     wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
699     return false;
700 }
701
702 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
703 {
704 }
705
706 const int* RenderThemeMac::popupButtonMargins() const
707 {
708     static const int margins[3][4] =
709     {
710         { 0, 3, 1, 3 },
711         { 0, 3, 2, 3 },
712         { 0, 1, 0, 1 }
713     };
714     return margins[[popupButton() controlSize]];
715 }
716
717 const IntSize* RenderThemeMac::popupButtonSizes() const
718 {
719     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
720     return sizes;
721 }
722
723 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
724 {
725     static const int padding[3][4] =
726     {
727         { 2, 26, 3, 8 },
728         { 2, 23, 3, 8 },
729         { 2, 22, 3, 10 }
730     };
731     return padding[size];
732 }
733
734 bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
735 {
736     setPopupButtonCellState(o, r);
737
738     NSPopUpButtonCell* popupButton = this->popupButton();
739
740     float zoomLevel = o->style()->effectiveZoom();
741     IntSize size = popupButtonSizes()[[popupButton controlSize]];
742     size.setHeight(size.height() * zoomLevel);
743     size.setWidth(r.width());
744
745     // Now inflate it to account for the shadow.
746     IntRect inflatedRect = r;
747     if (r.width() >= minimumMenuListSize(o->style()))
748         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
749
750     paintInfo.context->save();
751     
752 #ifndef BUILDING_ON_TIGER
753     // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
754     paintInfo.context->clip(inflatedRect);
755 #endif
756
757     if (zoomLevel != 1.0f) {
758         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
759         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
760         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
761         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
762         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
763     }
764
765     [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->documentView()];
766     [popupButton setControlView:nil];
767
768     paintInfo.context->restore();
769
770     return false;
771 }
772
773 const float baseFontSize = 11.0f;
774 const float baseArrowHeight = 4.0f;
775 const float baseArrowWidth = 5.0f;
776 const float baseSpaceBetweenArrows = 2.0f;
777 const int arrowPaddingLeft = 6;
778 const int arrowPaddingRight = 6;
779 const int paddingBeforeSeparator = 4;
780 const int baseBorderRadius = 5;
781 const int styledPopupPaddingLeft = 8;
782 const int styledPopupPaddingTop = 1;
783 const int styledPopupPaddingBottom = 2;
784
785 static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
786 {
787     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
788     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
789     float a = inData[0];
790     int i = 0;
791     for (i = 0; i < 4; i++)
792         outData[i] = (1.0f - a) * dark[i] + a * light[i];
793 }
794
795 static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
796 {
797     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
798     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
799     float a = inData[0];
800     int i = 0;
801     for (i = 0; i < 4; i++)
802         outData[i] = (1.0f - a) * dark[i] + a * light[i];
803 }
804
805 static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
806 {
807     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
808     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
809     float a = inData[0];
810     int i = 0;
811     for (i = 0; i < 4; i++)
812         outData[i] = (1.0f - a) * dark[i] + a * light[i];
813 }
814
815 static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
816 {
817     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
818     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
819     float a = inData[0];
820     int i = 0;
821     for (i = 0; i < 4; i++)
822         outData[i] = (1.0f - a) * dark[i] + a * light[i];
823 }
824
825 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
826 {
827     CGContextRef context = paintInfo.context->platformContext();
828
829     paintInfo.context->save();
830
831     int radius = o->style()->borderTopLeftRadius().width();
832
833     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
834
835     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
836     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
837     RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
838     RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
839
840     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
841     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
842     RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
843     RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
844
845     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
846     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
847     RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
848
849     RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
850
851     RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
852     paintInfo.context->save();
853     CGContextClipToRect(context, r);
854     paintInfo.context->addRoundedRectClip(r,
855         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
856         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
857     CGContextDrawShading(context, mainShading.get());
858     paintInfo.context->restore();
859
860     paintInfo.context->save();
861     CGContextClipToRect(context, topGradient);
862     paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
863         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
864         IntSize(), IntSize());
865     CGContextDrawShading(context, topShading.get());
866     paintInfo.context->restore();
867
868     paintInfo.context->save();
869     CGContextClipToRect(context, bottomGradient);
870     paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
871         IntSize(), IntSize(),
872         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
873     CGContextDrawShading(context, bottomShading.get());
874     paintInfo.context->restore();
875
876     paintInfo.context->save();
877     CGContextClipToRect(context, r);
878     paintInfo.context->addRoundedRectClip(r,
879         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
880         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
881     CGContextDrawShading(context, leftShading.get());
882     CGContextDrawShading(context, rightShading.get());
883     paintInfo.context->restore();
884
885     paintInfo.context->restore();
886 }
887
888 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
889 {
890     paintInfo.context->save();
891
892     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
893                              r.y() + o->style()->borderTopWidth(),
894                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
895                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
896     // Draw the gradients to give the styled popup menu a button appearance
897     paintMenuListButtonGradients(o, paintInfo, bounds);
898
899     // 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
900     float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
901     float centerY = bounds.y() + bounds.height() / 2.0f;
902     float arrowHeight = baseArrowHeight * fontScale;
903     float arrowWidth = baseArrowWidth * fontScale;
904     float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
905     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
906
907     if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
908         return false;
909     
910     paintInfo.context->setFillColor(o->style()->color());
911     paintInfo.context->setStrokeStyle(NoStroke);
912
913     FloatPoint arrow1[3];
914     arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
915     arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
916     arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
917
918     // Draw the top arrow
919     paintInfo.context->drawConvexPolygon(3, arrow1, true);
920
921     FloatPoint arrow2[3];
922     arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
923     arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
924     arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
925
926     // Draw the bottom arrow
927     paintInfo.context->drawConvexPolygon(3, arrow2, true);
928
929     Color leftSeparatorColor(0, 0, 0, 40);
930     Color rightSeparatorColor(255, 255, 255, 40);
931
932     // FIXME: Should the separator thickness and space be scaled up by fontScale?
933     int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
934     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
935
936     // Draw the separator to the left of the arrows
937     paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
938     paintInfo.context->setStrokeStyle(SolidStroke);
939     paintInfo.context->setStrokeColor(leftSeparatorColor);
940     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
941                                 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
942
943     paintInfo.context->setStrokeColor(rightSeparatorColor);
944     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
945                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
946
947     paintInfo.context->restore();
948     return false;
949 }
950
951 static const IntSize* menuListButtonSizes()
952 {
953     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
954     return sizes;
955 }
956
957 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
958 {
959     NSControlSize controlSize = controlSizeForFont(style);
960
961     style->resetBorder();
962     style->resetPadding();
963     
964     // Height is locked to auto.
965     style->setHeight(Length(Auto));
966
967     // White-space is locked to pre
968     style->setWhiteSpace(PRE);
969
970     // Set the foreground color to black or gray when we have the aqua look.
971     // Cast to RGB32 is to work around a compiler bug.
972     style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
973
974     // Set the button's vertical size.
975     setSizeFromFont(style, menuListButtonSizes());
976
977     // 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
978     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
979     // system font for the control size instead.
980     setFontFromControlSize(selector, style, controlSize);
981
982     style->setBoxShadow(0);
983 }
984
985 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
986 {
987     if (style->appearance() == MenulistPart)
988         return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
989     if (style->appearance() == MenulistButtonPart)
990         return styledPopupPaddingLeft * style->effectiveZoom();
991     return 0;
992 }
993
994 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
995 {
996     if (style->appearance() == MenulistPart)
997         return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
998     if (style->appearance() == MenulistButtonPart) {
999         float fontScale = style->fontSize() / baseFontSize;
1000         float arrowWidth = baseArrowWidth * fontScale;
1001         return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
1002     }
1003     return 0;
1004 }
1005
1006 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
1007 {
1008     if (style->appearance() == MenulistPart)
1009         return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
1010     if (style->appearance() == MenulistButtonPart)
1011         return styledPopupPaddingTop * style->effectiveZoom();
1012     return 0;
1013 }
1014
1015 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
1016 {
1017     if (style->appearance() == MenulistPart)
1018         return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
1019     if (style->appearance() == MenulistButtonPart)
1020         return styledPopupPaddingBottom * style->effectiveZoom();
1021     return 0;
1022 }
1023
1024 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1025 {
1026     float fontScale = style->fontSize() / baseFontSize;
1027
1028     style->resetPadding();
1029     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1030
1031     const int minHeight = 15;
1032     style->setMinHeight(Length(minHeight, Fixed));
1033     
1034     style->setLineHeight(RenderStyle::initialLineHeight());
1035 }
1036
1037 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1038 {
1039     NSPopUpButtonCell* popupButton = this->popupButton();
1040
1041     // Set the control size based off the rectangle we're painting into.
1042     setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
1043
1044     // Update the various states we respond to.
1045     updateCheckedState(popupButton, o);
1046     updateEnabledState(popupButton, o);
1047     updatePressedState(popupButton, o);
1048     updateFocusedState(popupButton, o);
1049 }
1050
1051 const IntSize* RenderThemeMac::menuListSizes() const
1052 {
1053     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1054     return sizes;
1055 }
1056
1057 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
1058 {
1059     return sizeForSystemFont(style, menuListSizes()).width();
1060 }
1061
1062 const int trackWidth = 5;
1063 const int trackRadius = 2;
1064
1065 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1066 {
1067     style->setBoxShadow(0);
1068 }
1069
1070 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1071 {
1072     IntRect bounds = r;
1073     float zoomLevel = o->style()->effectiveZoom();
1074     float zoomedTrackWidth = trackWidth * zoomLevel;
1075
1076     if (o->style()->appearance() ==  SliderHorizontalPart || o->style()->appearance() ==  MediaSliderPart) {
1077         bounds.setHeight(zoomedTrackWidth);
1078         bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
1079     } else if (o->style()->appearance() == SliderVerticalPart) {
1080         bounds.setWidth(zoomedTrackWidth);
1081         bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
1082     }
1083
1084     LocalCurrentGraphicsContext localContext(paintInfo.context);
1085     CGContextRef context = paintInfo.context->platformContext();
1086     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1087
1088     paintInfo.context->save();
1089     CGContextClipToRect(context, bounds);
1090
1091     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
1092     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1093     RetainPtr<CGShadingRef> mainShading;
1094     if (o->style()->appearance() == SliderVerticalPart)
1095         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
1096     else
1097         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
1098
1099     IntSize radius(trackRadius, trackRadius);
1100     paintInfo.context->addRoundedRectClip(bounds,
1101         radius, radius,
1102         radius, radius);
1103     CGContextDrawShading(context, mainShading.get());
1104     paintInfo.context->restore();
1105     
1106     return false;
1107 }
1108
1109 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1110 {
1111     style->setBoxShadow(0);
1112 }
1113
1114 const float verticalSliderHeightPadding = 0.1f;
1115
1116 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1117 {
1118     ASSERT(o->parent()->isSlider());
1119
1120     NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
1121         ? sliderThumbVertical()
1122         : sliderThumbHorizontal();
1123
1124     LocalCurrentGraphicsContext localContext(paintInfo.context);
1125
1126     // Update the various states we respond to.
1127     updateEnabledState(sliderThumbCell, o->parent());
1128     updateFocusedState(sliderThumbCell, o->parent());
1129
1130     // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
1131     bool oldPressed;
1132     if (o->style()->appearance() == SliderThumbVerticalPart)
1133         oldPressed = m_isSliderThumbVerticalPressed;
1134     else
1135         oldPressed = m_isSliderThumbHorizontalPressed;
1136
1137     bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
1138
1139     if (o->style()->appearance() == SliderThumbVerticalPart)
1140         m_isSliderThumbVerticalPressed = pressed;
1141     else
1142         m_isSliderThumbHorizontalPressed = pressed;
1143
1144     if (pressed != oldPressed) {
1145         if (pressed)
1146             [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
1147         else
1148             [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
1149     }
1150
1151     FloatRect bounds = r;
1152     // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
1153     if (o->style()->appearance() == SliderThumbVerticalPart)
1154         bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
1155
1156     paintInfo.context->save();
1157     float zoomLevel = o->style()->effectiveZoom();
1158     
1159     FloatRect unzoomedRect = bounds;
1160     if (zoomLevel != 1.0f) {
1161         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1162         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1163         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1164         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1165         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1166     }
1167
1168     [sliderThumbCell drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
1169     [sliderThumbCell setControlView:nil];
1170
1171     paintInfo.context->restore();
1172
1173     return false;
1174 }
1175
1176 bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1177 {
1178     NSSearchFieldCell* search = this->search();
1179     LocalCurrentGraphicsContext localContext(paintInfo.context);
1180
1181     setSearchCellState(o, r);
1182
1183     paintInfo.context->save();
1184
1185     float zoomLevel = o->style()->effectiveZoom();
1186
1187     IntRect unzoomedRect = r;
1188     
1189     if (zoomLevel != 1.0f) {
1190         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1191         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1192         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1193         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1194         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1195     }
1196
1197     // Set the search button to nil before drawing.  Then reset it so we can draw it later.
1198     [search setSearchButtonCell:nil];
1199
1200     [search drawWithFrame:NSRect(unzoomedRect) inView:o->view()->frameView()->documentView()];
1201 #ifdef BUILDING_ON_TIGER
1202     if ([search showsFirstResponder])
1203         wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
1204 #endif
1205
1206     [search setControlView:nil];
1207     [search resetSearchButtonCell];
1208
1209     paintInfo.context->restore();
1210
1211     return false;
1212 }
1213
1214 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
1215 {
1216     NSSearchFieldCell* search = this->search();
1217
1218     [search setControlSize:controlSizeForFont(o->style())];
1219
1220     // Update the various states we respond to.
1221     updateEnabledState(search, o);
1222     updateFocusedState(search, o);
1223 }
1224
1225 const IntSize* RenderThemeMac::searchFieldSizes() const
1226 {
1227     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
1228     return sizes;
1229 }
1230
1231 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
1232 {
1233     // If the width and height are both specified, then we have nothing to do.
1234     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1235         return;
1236     
1237     // Use the font size to determine the intrinsic width of the control.
1238     setSizeFromFont(style, searchFieldSizes());
1239 }
1240
1241 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
1242 {
1243     // Override border.
1244     style->resetBorder();
1245     const short borderWidth = 2 * style->effectiveZoom();
1246     style->setBorderLeftWidth(borderWidth);
1247     style->setBorderLeftStyle(INSET);
1248     style->setBorderRightWidth(borderWidth);
1249     style->setBorderRightStyle(INSET);
1250     style->setBorderBottomWidth(borderWidth);
1251     style->setBorderBottomStyle(INSET);
1252     style->setBorderTopWidth(borderWidth);
1253     style->setBorderTopStyle(INSET);    
1254     
1255     // Override height.
1256     style->setHeight(Length(Auto));
1257     setSearchFieldSize(style);
1258     
1259     // Override padding size to match AppKit text positioning.
1260     const int padding = 1 * style->effectiveZoom();
1261     style->setPaddingLeft(Length(padding, Fixed));
1262     style->setPaddingRight(Length(padding, Fixed));
1263     style->setPaddingTop(Length(padding, Fixed));
1264     style->setPaddingBottom(Length(padding, Fixed));
1265     
1266     NSControlSize controlSize = controlSizeForFont(style);
1267     setFontFromControlSize(selector, style, controlSize);
1268
1269     style->setBoxShadow(0);
1270 }
1271
1272 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1273 {
1274     Node* input = o->node()->shadowAncestorNode();
1275     if (!input->renderer()->isBox())
1276         return false;
1277
1278     setSearchCellState(input->renderer(), r);
1279
1280     NSSearchFieldCell* search = this->search();
1281
1282     updatePressedState([search cancelButtonCell], o);
1283
1284     paintInfo.context->save();
1285
1286     float zoomLevel = o->style()->effectiveZoom();
1287
1288     FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1289     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1290
1291     FloatRect unzoomedRect(localBounds);
1292     if (zoomLevel != 1.0f) {
1293         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1294         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1295         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1296         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1297         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1298     }
1299
1300     [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
1301     [[search cancelButtonCell] setControlView:nil];
1302
1303     paintInfo.context->restore();
1304     return false;
1305 }
1306
1307 const IntSize* RenderThemeMac::cancelButtonSizes() const
1308 {
1309     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1310     return sizes;
1311 }
1312
1313 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1314 {
1315     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1316     style->setWidth(Length(size.width(), Fixed));
1317     style->setHeight(Length(size.height(), Fixed));
1318     style->setBoxShadow(0);
1319 }
1320
1321 const IntSize* RenderThemeMac::resultsButtonSizes() const
1322 {
1323     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1324     return sizes;
1325 }
1326
1327 const int emptyResultsOffset = 9;
1328 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1329 {
1330     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1331     style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1332     style->setHeight(Length(size.height(), Fixed));
1333     style->setBoxShadow(0);
1334 }
1335
1336 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&)
1337 {
1338     return false;
1339 }
1340
1341 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1342 {
1343     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1344     style->setWidth(Length(size.width(), Fixed));
1345     style->setHeight(Length(size.height(), Fixed));
1346     style->setBoxShadow(0);
1347 }
1348
1349 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
1350 {
1351     Node* input = o->node()->shadowAncestorNode();
1352     if (!input->renderer()->isBox())
1353         return false;
1354
1355     setSearchCellState(input->renderer(), r);
1356
1357     NSSearchFieldCell* search = this->search();
1358
1359     if ([search searchMenuTemplate] != nil)
1360         [search setSearchMenuTemplate:nil];
1361
1362     FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1363     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1364
1365     [[search searchButtonCell] drawWithFrame:localBounds inView:o->view()->frameView()->documentView()];
1366     [[search searchButtonCell] setControlView:nil];
1367     return false;
1368 }
1369
1370 const int resultsArrowWidth = 5;
1371 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
1372 {
1373     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1374     style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1375     style->setHeight(Length(size.height(), Fixed));
1376     style->setBoxShadow(0);
1377 }
1378
1379 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1380 {
1381     Node* input = o->node()->shadowAncestorNode();
1382     if (!input->renderer()->isBox())
1383         return false;
1384
1385     setSearchCellState(input->renderer(), r);
1386
1387     NSSearchFieldCell* search = this->search();
1388
1389     if (![search searchMenuTemplate])
1390         [search setSearchMenuTemplate:searchMenuTemplate()];
1391
1392     paintInfo.context->save();
1393
1394     float zoomLevel = o->style()->effectiveZoom();
1395
1396     FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
1397     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
1398     
1399     IntRect unzoomedRect(localBounds);
1400     if (zoomLevel != 1.0f) {
1401         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1402         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1403         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1404         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1405         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1406     }
1407
1408     [[search searchButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
1409     [[search searchButtonCell] setControlView:nil];
1410     
1411     paintInfo.context->restore();
1412
1413     return false;
1414 }
1415
1416 #if ENABLE(VIDEO)
1417 typedef enum {
1418     MediaControllerThemeClassic   = 1,
1419     MediaControllerThemeQT        = 2
1420 } MediaControllerThemeStyle;
1421
1422 static int mediaControllerTheme()
1423 {
1424     static const long minimumQuickTimeVersion = 0x07630000; // 7.6.3
1425     static SInt32 quickTimeVersion = 0;
1426     static int controllerTheme = -1;
1427     
1428     if (controllerTheme != -1)
1429         return controllerTheme;
1430
1431     controllerTheme = MediaControllerThemeClassic;
1432
1433     if (!quickTimeVersion) {
1434         OSErr err;
1435         err = Gestalt(gestaltQuickTime, &quickTimeVersion);
1436         if (err != noErr)
1437             return controllerTheme;
1438     }
1439     if (quickTimeVersion < minimumQuickTimeVersion)
1440         return controllerTheme;
1441
1442     Boolean validKey;
1443     Boolean useQTMediaUI = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
1444
1445 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
1446     if (validKey && !useQTMediaUI)
1447         return controllerTheme;
1448 #else
1449     if (!validKey || !useQTMediaUI)
1450         return controllerTheme;
1451 #endif
1452
1453     controllerTheme = MediaControllerThemeQT;
1454     return controllerTheme;
1455 }
1456 #endif
1457
1458 const int sliderThumbWidth = 15;
1459 const int sliderThumbHeight = 15;
1460 const int mediaSliderThumbWidth = 13;
1461 const int mediaSliderThumbHeight = 14;
1462
1463 void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
1464 {
1465     float zoomLevel = o->style()->effectiveZoom();
1466     if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
1467         o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
1468         o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
1469     } 
1470
1471 #if ENABLE(VIDEO)
1472     else if (o->style()->appearance() == MediaSliderThumbPart) {
1473         int width = mediaSliderThumbWidth;
1474         int height = mediaSliderThumbHeight;
1475         
1476         if (mediaControllerTheme() == MediaControllerThemeQT) {
1477             CGSize  size;
1478             
1479             wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQT, NULL, &size);
1480             width = size.width;
1481             height = size.height;
1482         }
1483
1484         o->style()->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
1485         o->style()->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
1486     }
1487 #endif
1488 }
1489
1490
1491 #if ENABLE(VIDEO)
1492
1493 enum WKMediaControllerThemeState { 
1494     MediaUIPartDisabledFlag = 1 << 0,
1495     MediaUIPartPressedFlag = 1 << 1,
1496     MediaUIPartDrawEndCapsFlag = 1 << 3,
1497 };
1498
1499 static unsigned getMediaUIPartStateFlags(Node* node)
1500 {
1501     unsigned flags = 0;
1502
1503     if (node->active())
1504         flags |= MediaUIPartPressedFlag;
1505     return flags;
1506 }
1507
1508 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
1509 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect &originalRect)
1510 {
1511     float zoomLevel = o->style()->effectiveZoom();
1512     FloatRect unzoomedRect(originalRect);
1513     if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQT) {
1514         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1515         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1516         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1517         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1518         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1519     }
1520     return unzoomedRect;
1521 }
1522
1523
1524 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1525 {
1526     Node* node = o->node();
1527     if (!node)
1528         return false;
1529
1530     LocalCurrentGraphicsContext localContext(paintInfo.context);
1531     wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1532     return false;
1533 }
1534
1535 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1536 {
1537     Node* node = o->node();
1538     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1539     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1540         return false;
1541
1542     if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
1543         LocalCurrentGraphicsContext localContext(paintInfo.context);
1544         wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1545
1546     }
1547     return false;
1548 }
1549
1550 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1551 {
1552     Node* node = o->node();
1553     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1554     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1555         return false;
1556
1557     if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
1558         LocalCurrentGraphicsContext localContext(paintInfo.context);
1559         wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1560     }
1561     return false;
1562 }
1563
1564 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1565 {
1566     Node* node = o->node();
1567     if (!node)
1568         return false;
1569
1570     LocalCurrentGraphicsContext localContext(paintInfo.context);
1571     wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1572     return false;
1573 }
1574
1575 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1576 {
1577     Node* node = o->node();
1578     if (!node)
1579         return false;
1580
1581     LocalCurrentGraphicsContext localContext(paintInfo.context);
1582     wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1583     return false;
1584 }
1585
1586 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1587 {
1588     Node* node = o->node();
1589     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1590     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1591         return false;
1592
1593     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1594     if (!mediaElement)
1595         return false;
1596
1597     float timeLoaded = 0;
1598     float currentTime = 0;
1599     float duration = 0;
1600     if (MediaPlayer* player = mediaElement->player()) {
1601         duration = player->duration();
1602         timeLoaded = player->maxTimeBuffered();
1603         currentTime = player->currentTime();
1604     }
1605  
1606     paintInfo.context->save();
1607     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1608     wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, 
1609         timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
1610     
1611     paintInfo.context->restore();
1612     return false;
1613 }
1614
1615 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1616 {
1617     Node* node = o->node();
1618     if (!node)
1619         return false;
1620
1621     LocalCurrentGraphicsContext localContext(paintInfo.context);
1622     wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1623     return false;
1624 }
1625     
1626 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1627 {
1628     Node* node = o->node();
1629     if (!node)
1630         return false;
1631     
1632     LocalCurrentGraphicsContext localContext(paintInfo.context);
1633     wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1634     return false;
1635 }
1636
1637 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1638 {
1639     Node* node = o->node();
1640     if (!node)
1641         return false;
1642     
1643     LocalCurrentGraphicsContext localContext(paintInfo.context);
1644     wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1645     return false;
1646 }
1647
1648
1649 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1650 {
1651     Node* node = o->node();
1652     if (!node)
1653         return false;
1654
1655     LocalCurrentGraphicsContext localContext(paintInfo.context);
1656     wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
1657     return false;
1658 }
1659
1660 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1661 {
1662     Node* node = o->node();
1663     if (!node)
1664         return false;
1665
1666     paintInfo.context->save();
1667     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1668     wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
1669     paintInfo.context->restore();
1670     return false;
1671 }
1672
1673 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1674 {
1675     Node* node = o->node();
1676     if (!node)
1677         return false;
1678
1679     paintInfo.context->save();
1680     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
1681     wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
1682     paintInfo.context->restore();
1683     return false;
1684 }
1685
1686 String RenderThemeMac::extraMediaControlsStyleSheet()
1687 {
1688     if (mediaControllerTheme() == MediaControllerThemeQT) 
1689         return String(mediaControlsQTUserAgentStyleSheet, sizeof(mediaControlsQTUserAgentStyleSheet));
1690     else
1691         return String();
1692 }
1693 #endif
1694
1695 NSPopUpButtonCell* RenderThemeMac::popupButton() const
1696 {
1697     if (!m_popupButton) {
1698         m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
1699         [m_popupButton.get() setUsesItemFromMenu:NO];
1700         [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
1701     }
1702     
1703     return m_popupButton.get();
1704 }
1705
1706 NSSearchFieldCell* RenderThemeMac::search() const
1707 {
1708     if (!m_search) {
1709         m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
1710         [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
1711         [m_search.get() setBezeled:YES];
1712         [m_search.get() setEditable:YES];
1713         [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
1714     }
1715
1716     return m_search.get();
1717 }
1718
1719 NSMenu* RenderThemeMac::searchMenuTemplate() const
1720 {
1721     if (!m_searchMenuTemplate)
1722         m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
1723
1724     return m_searchMenuTemplate.get();
1725 }
1726
1727 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
1728 {
1729     if (!m_sliderThumbHorizontal) {
1730         m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
1731         [m_sliderThumbHorizontal.get() setTitle:nil];
1732         [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
1733         [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
1734         [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
1735     }
1736     
1737     return m_sliderThumbHorizontal.get();
1738 }
1739
1740 NSSliderCell* RenderThemeMac::sliderThumbVertical() const
1741 {
1742     if (!m_sliderThumbVertical) {
1743         m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
1744         [m_sliderThumbVertical.get() setTitle:nil];
1745         [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
1746         [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
1747         [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
1748     }
1749     
1750     return m_sliderThumbVertical.get();
1751 }
1752
1753 } // namespace WebCore