1a3ccf5af37c648b9fad8ff14f8c647283b5c224
[WebKit.git] / WebCore / rendering / RenderThemeChromiumMac.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008, 2009 Google, Inc.
4  * Copyright (C) 2009 Kenneth Rohde Christiansen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 // FIXME: we still need to figure out if passing a null view to the cell
23 // drawing routines will work. I expect not, and if that's the case we'll have
24 // to figure out something else. For now, at least leave the lines commented
25 // in, but the procurement of the view if 0'd.
26
27 #import "config.h"
28 #import "RenderThemeChromiumMac.h"
29
30 #import <Carbon/Carbon.h>
31 #import <Cocoa/Cocoa.h>
32 #import <math.h>
33
34 #import "BitmapImage.h"
35 #import "ChromiumBridge.h"
36 #import "ColorMac.h"
37 #import "CSSStyleSelector.h"
38 #import "CSSValueKeywords.h"
39 #import "Element.h"
40 #import "FoundationExtras.h"
41 #import "FrameView.h"
42 #import "Gradient.h"
43 #import "GraphicsContext.h"
44 #import "HTMLInputElement.h"
45 #import "HTMLMediaElement.h"
46 #import "HTMLNames.h"
47 #import "Image.h"
48 #import "LocalCurrentGraphicsContext.h"
49 #import "MediaControlElements.h"
50 #import "RenderMedia.h"
51 #import "RenderSlider.h"
52 #import "RenderView.h"
53 #import "SharedBuffer.h"
54 #import "TimeRanges.h"
55 #import "UserAgentStyleSheets.h"
56 #import "WebCoreSystemInterface.h"
57 #import <wtf/RetainPtr.h>
58
59 #ifdef BUILDING_ON_TIGER
60 typedef int NSInteger;
61 typedef unsigned NSUInteger;
62 #endif
63
64 using std::min;
65
66 // The methods in this file are specific to the Mac OS X platform.
67
68 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. 
69
70 @interface WebCoreRenderThemeNotificationObserver : NSObject
71 {
72     WebCore::RenderTheme *_theme;
73 }
74
75 - (id)initWithTheme:(WebCore::RenderTheme *)theme;
76 - (void)systemColorsDidChange:(NSNotification *)notification;
77
78 @end
79
80 @implementation WebCoreRenderThemeNotificationObserver
81
82 - (id)initWithTheme:(WebCore::RenderTheme *)theme
83 {
84     [super init];
85     _theme = theme;
86     
87     return self;
88 }
89
90 - (void)systemColorsDidChange:(NSNotification *)notification
91 {
92     ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]);
93     _theme->platformColorsDidChange();
94 }
95
96 @end
97
98 namespace WebCore {
99
100 using namespace HTMLNames;
101
102 enum {
103     TopMargin,
104     RightMargin,
105     BottomMargin,
106     LeftMargin
107 };
108
109 enum {
110     TopPadding,
111     RightPadding,
112     BottomPadding,
113     LeftPadding
114 };
115
116 #if ENABLE(VIDEO)
117 // Attempt to retrieve a HTMLMediaElement from a Node. Returns 0 if one cannot be found.
118 static HTMLMediaElement* mediaElementParent(Node* node)
119 {
120     if (!node)
121         return 0;
122     Node* mediaNode = node->shadowAncestorNode();
123     if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
124         return 0;
125
126     return static_cast<HTMLMediaElement*>(mediaNode);
127 }
128 #endif
129
130 // In our Mac port, we don't define PLATFORM(MAC) and thus don't pick up the
131 // |operator NSRect()| on WebCore::IntRect and FloatRect. This substitues for
132 // that missing conversion operator.
133 NSRect IntRectToNSRect(const IntRect & rect)
134 {
135     return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
136 }
137
138 NSRect FloatRectToNSRect(const FloatRect & rect)
139 {
140     return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
141 }
142
143 IntRect NSRectToIntRect(const NSRect & rect)
144 {
145     return IntRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
146 }
147
148 PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
149 {
150     return adoptRef(new RenderThemeChromiumMac);
151 }
152
153 #if ENABLE(VIDEO)
154 String RenderThemeChromiumMac::extraMediaControlsStyleSheet()
155 {
156     return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
157 }
158 #endif
159
160 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
161 {
162     static RenderTheme* rt = RenderThemeChromiumMac::create().releaseRef();
163     return rt;
164 }
165
166 RenderThemeChromiumMac::RenderThemeChromiumMac()
167     : m_isSliderThumbHorizontalPressed(false)
168     , m_isSliderThumbVerticalPressed(false)
169     , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
170 {
171     [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
172                                                         selector:@selector(systemColorsDidChange:)
173                                                             name:NSSystemColorsDidChangeNotification
174                                                           object:nil];
175 }
176
177 RenderThemeChromiumMac::~RenderThemeChromiumMac()
178 {
179     [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
180 }
181
182 Color RenderThemeChromiumMac::platformActiveSelectionBackgroundColor() const
183 {
184     NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
185     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
186 }
187
188 Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const
189 {
190     NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
191     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
192 }
193
194 Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() const
195 {
196     NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
197     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
198 }
199
200 Color RenderThemeChromiumMac::platformFocusRingColor() const
201 {
202     if (ChromiumBridge::layoutTestMode())
203         return oldAquaFocusRingColor();
204
205     return systemColor(CSSValueWebkitFocusRingColor);
206 }
207
208 static FontWeight toFontWeight(NSInteger appKitFontWeight)
209 {
210     ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
211     if (appKitFontWeight > 14)
212         appKitFontWeight = 14;
213     else if (appKitFontWeight < 1)
214         appKitFontWeight = 1;
215
216     static FontWeight fontWeights[] = {
217         FontWeight100,
218         FontWeight100,
219         FontWeight200,
220         FontWeight300,
221         FontWeight400,
222         FontWeight500,
223         FontWeight600,
224         FontWeight600,
225         FontWeight700,
226         FontWeight800,
227         FontWeight800,
228         FontWeight900,
229         FontWeight900,
230         FontWeight900
231     };
232     return fontWeights[appKitFontWeight - 1];
233 }
234
235 void RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDescription) const
236 {
237     static FontDescription systemFont;
238     static FontDescription smallSystemFont;
239     static FontDescription menuFont;
240     static FontDescription labelFont;
241     static FontDescription miniControlFont;
242     static FontDescription smallControlFont;
243     static FontDescription controlFont;
244
245     FontDescription* cachedDesc;
246     NSFont* font = nil;
247     switch (cssValueId) {
248     case CSSValueSmallCaption:
249         cachedDesc = &smallSystemFont;
250         if (!smallSystemFont.isAbsoluteSize())
251             font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
252         break;
253     case CSSValueMenu:
254         cachedDesc = &menuFont;
255         if (!menuFont.isAbsoluteSize())
256             font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
257         break;
258     case CSSValueStatusBar:
259         cachedDesc = &labelFont;
260         if (!labelFont.isAbsoluteSize())
261             font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
262         break;
263     case CSSValueWebkitMiniControl:
264         cachedDesc = &miniControlFont;
265         if (!miniControlFont.isAbsoluteSize())
266             font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
267         break;
268     case CSSValueWebkitSmallControl:
269         cachedDesc = &smallControlFont;
270         if (!smallControlFont.isAbsoluteSize())
271             font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
272         break;
273     case CSSValueWebkitControl:
274         cachedDesc = &controlFont;
275         if (!controlFont.isAbsoluteSize())
276             font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
277         break;
278     default:
279         cachedDesc = &systemFont;
280         if (!systemFont.isAbsoluteSize())
281             font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
282     }
283
284     if (font) {
285         NSFontManager *fontManager = [NSFontManager sharedFontManager];
286         cachedDesc->setIsAbsoluteSize(true);
287         cachedDesc->setGenericFamily(FontDescription::NoFamily);
288         cachedDesc->firstFamily().setFamily([font familyName]);
289         cachedDesc->setSpecifiedSize([font pointSize]);
290         cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
291         cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
292     }
293     fontDescription = *cachedDesc;
294 }
295
296 static RGBA32 convertNSColorToColor(NSColor *color)
297 {
298     NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
299     if (colorInColorSpace) {
300         static const double scaleFactor = nextafter(256.0, 0.0);
301         return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
302             static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
303             static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
304     }
305
306     // This conversion above can fail if the NSColor in question is an NSPatternColor 
307     // (as many system colors are). These colors are actually a repeating pattern
308     // not just a solid color. To work around this we simply draw a 1x1 image of
309     // the color and use that pixel's color. It might be better to use an average of
310     // the colors in the pattern instead.
311     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
312                                                                              pixelsWide:1
313                                                                              pixelsHigh:1
314                                                                           bitsPerSample:8
315                                                                         samplesPerPixel:4
316                                                                                hasAlpha:YES
317                                                                                isPlanar:NO
318                                                                          colorSpaceName:NSCalibratedRGBColorSpace
319                                                                             bytesPerRow:4
320                                                                            bitsPerPixel:32];
321
322     [NSGraphicsContext saveGraphicsState];
323     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
324     NSEraseRect(NSMakeRect(0, 0, 1, 1));
325     [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
326     [NSGraphicsContext restoreGraphicsState];
327
328     NSUInteger pixel[4];
329     [offscreenRep getPixel:pixel atX:0 y:0];
330
331     [offscreenRep release];
332
333     return makeRGB(pixel[0], pixel[1], pixel[2]);
334 }
335
336 static RGBA32 menuBackgroundColor()
337 {
338     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
339                                                                              pixelsWide:1
340                                                                              pixelsHigh:1
341                                                                           bitsPerSample:8
342                                                                         samplesPerPixel:4
343                                                                                hasAlpha:YES
344                                                                                isPlanar:NO
345                                                                          colorSpaceName:NSCalibratedRGBColorSpace
346                                                                             bytesPerRow:4
347                                                                            bitsPerPixel:32];
348
349     CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
350     CGRect rect = CGRectMake(0, 0, 1, 1);
351     HIThemeMenuDrawInfo drawInfo;
352     drawInfo.version =  0;
353     drawInfo.menuType = kThemeMenuTypePopUp;
354     HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
355
356     NSUInteger pixel[4];
357     [offscreenRep getPixel:pixel atX:0 y:0];
358
359     [offscreenRep release];
360
361     return makeRGB(pixel[0], pixel[1], pixel[2]);
362 }
363
364 void RenderThemeChromiumMac::platformColorsDidChange()
365 {
366     m_systemColorCache.clear();
367     RenderTheme::platformColorsDidChange();
368 }
369
370 Color RenderThemeChromiumMac::systemColor(int cssValueId) const
371 {
372     if (m_systemColorCache.contains(cssValueId))
373         return m_systemColorCache.get(cssValueId);
374     
375     Color color;
376     switch (cssValueId) {
377     case CSSValueActiveborder:
378         color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
379         break;
380     case CSSValueActivecaption:
381         color = convertNSColorToColor([NSColor windowFrameTextColor]);
382         break;
383     case CSSValueAppworkspace:
384         color = convertNSColorToColor([NSColor headerColor]);
385         break;
386     case CSSValueBackground:
387         // Use theme independent default
388         break;
389     case CSSValueButtonface:
390         // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
391         // We may want to change this to use the NSColor in future.
392         color = 0xFFC0C0C0;
393         break;
394     case CSSValueButtonhighlight:
395         color = convertNSColorToColor([NSColor controlHighlightColor]);
396         break;
397     case CSSValueButtonshadow:
398         color = convertNSColorToColor([NSColor controlShadowColor]);
399         break;
400     case CSSValueButtontext:
401         color = convertNSColorToColor([NSColor controlTextColor]);
402         break;
403     case CSSValueCaptiontext:
404         color = convertNSColorToColor([NSColor textColor]);
405         break;
406     case CSSValueGraytext:
407         color = convertNSColorToColor([NSColor disabledControlTextColor]);
408         break;
409     case CSSValueHighlight:
410         color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
411         break;
412     case CSSValueHighlighttext:
413         color = convertNSColorToColor([NSColor selectedTextColor]);
414         break;
415     case CSSValueInactiveborder:
416         color = convertNSColorToColor([NSColor controlBackgroundColor]);
417         break;
418     case CSSValueInactivecaption:
419         color = convertNSColorToColor([NSColor controlBackgroundColor]);
420         break;
421     case CSSValueInactivecaptiontext:
422         color = convertNSColorToColor([NSColor textColor]);
423         break;
424     case CSSValueInfobackground:
425         // There is no corresponding NSColor for this so we use a hard coded value.
426         color = 0xFFFBFCC5;
427         break;
428     case CSSValueInfotext:
429         color = convertNSColorToColor([NSColor textColor]);
430         break;
431     case CSSValueMenu:
432         color = menuBackgroundColor();
433         break;
434     case CSSValueMenutext:
435         color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
436         break;
437     case CSSValueScrollbar:
438         color = convertNSColorToColor([NSColor scrollBarColor]);
439         break;
440     case CSSValueText:
441         color = convertNSColorToColor([NSColor textColor]);
442         break;
443     case CSSValueThreeddarkshadow:
444         color = convertNSColorToColor([NSColor controlDarkShadowColor]);
445         break;
446     case CSSValueThreedshadow:
447         color = convertNSColorToColor([NSColor shadowColor]);
448         break;
449     case CSSValueThreedface:
450         // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
451         // We may want to change this to use the NSColor in future.
452         color = 0xFFC0C0C0;
453         break;
454     case CSSValueThreedhighlight:
455         color = convertNSColorToColor([NSColor highlightColor]);
456         break;
457     case CSSValueThreedlightshadow:
458         color = convertNSColorToColor([NSColor controlLightHighlightColor]);
459         break;
460     case CSSValueWebkitFocusRingColor:
461         color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
462         break;
463     case CSSValueWindow:
464         color = convertNSColorToColor([NSColor windowBackgroundColor]);
465         break;
466     case CSSValueWindowframe:
467         color = convertNSColorToColor([NSColor windowFrameColor]);
468         break;
469     case CSSValueWindowtext:
470         color = convertNSColorToColor([NSColor windowFrameTextColor]);
471         break;
472     }
473
474     if (!color.isValid())
475         color = RenderTheme::systemColor(cssValueId);
476
477     if (color.isValid())
478         m_systemColorCache.set(cssValueId, color.rgb());
479
480     return color;
481 }
482
483 bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const BorderData& border,
484                                              const FillLayer& background, const Color& backgroundColor) const
485 {
486     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
487         return style->border() != border;
488         
489     // FIXME: This is horrible, but there is not much else that can be done.  Menu lists cannot draw properly when
490     // scaled.  They can't really draw properly when transformed either.  We can't detect the transform case at style
491     // adjustment time so that will just have to stay broken.  We can however detect that we're zooming.  If zooming
492     // is in effect we treat it like the control is styled.
493     if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
494         return true;
495
496     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
497 }
498
499 // FIXME: Use the code from the old upstream version, before it was converted to the new theme API in r37731.
500 void RenderThemeChromiumMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
501 {
502     float zoomLevel = o->style()->effectiveZoom();
503
504     switch (o->style()->appearance()) {
505     case CheckboxPart: {
506         // Since we query the prototype cell, we need to update its state to match.
507         setCheckboxCellState(o, r);
508
509         // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
510         // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
511         IntSize size = checkboxSizes()[[checkbox() controlSize]];
512         size.setHeight(size.height() * zoomLevel);
513         size.setWidth(size.width() * zoomLevel);
514         r = inflateRect(r, size, checkboxMargins(), zoomLevel);
515         break;
516     }
517     case RadioPart: {
518         // Since we query the prototype cell, we need to update its state to match.
519         setRadioCellState(o, r);
520
521         // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
522         // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
523         IntSize size = radioSizes()[[radio() controlSize]];
524         size.setHeight(size.height() * zoomLevel);
525         size.setWidth(size.width() * zoomLevel);
526         r = inflateRect(r, size, radioMargins(), zoomLevel);
527         break;
528     }
529     case PushButtonPart:
530     case DefaultButtonPart:
531     case ButtonPart: {
532         // Since we query the prototype cell, we need to update its state to match.
533         setButtonCellState(o, r);
534
535         // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
536         // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
537         if ([button() bezelStyle] == NSRoundedBezelStyle) {
538             IntSize size = buttonSizes()[[button() controlSize]];
539             size.setHeight(size.height() * zoomLevel);
540             size.setWidth(r.width());
541             r = inflateRect(r, size, buttonMargins(), zoomLevel);
542         }
543         break;
544     }
545     case MenulistPart: {
546         setPopupButtonCellState(o, r);
547         IntSize size = popupButtonSizes()[[popupButton() controlSize]];
548         size.setHeight(size.height() * zoomLevel);
549         size.setWidth(r.width());
550         r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
551         break;
552     }
553     default:
554         break;
555     }
556 }
557
558 IntRect RenderThemeChromiumMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
559 {
560     // Only do the inflation if the available width/height are too small.  Otherwise try to
561     // fit the glow/check space into the available box's width/height.
562     int widthDelta = r.width() - (size.width() + margins[LeftMargin] * zoomLevel + margins[RightMargin] * zoomLevel);
563     int heightDelta = r.height() - (size.height() + margins[TopMargin] * zoomLevel + margins[BottomMargin] * zoomLevel);
564     IntRect result(r);
565     if (widthDelta < 0) {
566         result.setX(result.x() - margins[LeftMargin] * zoomLevel);
567         result.setWidth(result.width() - widthDelta);
568     }
569     if (heightDelta < 0) {
570         result.setY(result.y() - margins[TopMargin] * zoomLevel);
571         result.setHeight(result.height() - heightDelta);
572     }
573     return result;
574 }
575
576 // Updates the control tint (a.k.a. active state) of |cell| (from |o|).
577 // In the Chromium port, the renderer runs as a background process and controls'
578 // NSCell(s) lack a parent NSView. Therefore controls don't have their tint
579 // color updated correctly when the application is activated/deactivated.
580 // FocusController's setActive() is called when the application is
581 // activated/deactivated, which causes a repaint at which time this code is
582 // called.
583 // This function should be called before drawing any NSCell-derived controls,
584 // unless you're sure it isn't needed.
585 void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* o)
586 {
587     NSControlTint oldTint = [cell controlTint];
588     NSControlTint tint = isActive(o) ? [NSColor currentControlTint] :
589                                        NSClearControlTint;
590
591     if (tint != oldTint)
592         [cell setControlTint:tint];
593 }
594
595 void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o)
596 {
597     bool oldIndeterminate = [cell state] == NSMixedState;
598     bool indeterminate = isIndeterminate(o);
599     bool checked = isChecked(o);
600
601     if (oldIndeterminate != indeterminate) {
602         [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
603         return;
604     }
605
606     bool oldChecked = [cell state] == NSOnState;
607     if (checked != oldChecked)
608         [cell setState:checked ? NSOnState : NSOffState];
609 }
610
611 void RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o)
612 {
613     bool oldEnabled = [cell isEnabled];
614     bool enabled = isEnabled(o);
615     if (enabled != oldEnabled)
616         [cell setEnabled:enabled];
617 }
618
619 void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o)
620 {
621     bool oldFocused = [cell showsFirstResponder];
622     bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
623     if (focused != oldFocused)
624         [cell setShowsFirstResponder:focused];
625 }
626
627 void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o)
628 {
629     bool oldPressed = [cell isHighlighted];
630     bool pressed = (o->node() && o->node()->active());
631     if (pressed != oldPressed)
632         [cell setHighlighted:pressed];
633 }
634
635 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
636 int RenderThemeChromiumMac::baselinePosition(const RenderObject* o) const
637 {
638     if (!o->isBox())
639         return 0;
640
641     if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) {
642         const RenderBox* box = toRenderBox(o);
643         return box->marginTop() + box->height() - 2 * o->style()->effectiveZoom(); // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
644     }
645     return RenderTheme::baselinePosition(o);
646 }
647
648 bool RenderThemeChromiumMac::controlSupportsTints(const RenderObject* o) const
649 {
650     // An alternate way to implement this would be to get the appropriate cell object
651     // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
652     // that would be that we would match AppKit behavior more closely, but a disadvantage
653     // would be that we would rely on an AppKit SPI method.
654
655     if (!isEnabled(o))
656         return false;
657
658     // Checkboxes only have tint when checked.
659     if (o->style()->appearance() == CheckboxPart)
660         return isChecked(o);
661
662     // For now assume other controls have tint if enabled.
663     return true;
664 }
665
666 NSControlSize RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const
667 {
668     int fontSize = style->fontSize();
669     if (fontSize >= 16)
670         return NSRegularControlSize;
671     if (fontSize >= 11)
672         return NSSmallControlSize;
673     return NSMiniControlSize;
674 }
675
676 void RenderThemeChromiumMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
677 {
678     NSControlSize size;
679     if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
680         minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
681         size = NSRegularControlSize;
682     else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
683              minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
684         size = NSSmallControlSize;
685     else
686         size = NSMiniControlSize;
687     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
688         [cell setControlSize:size];
689 }
690
691 IntSize RenderThemeChromiumMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
692 {
693     if (style->effectiveZoom() != 1.0f) {
694         IntSize result = sizes[controlSizeForFont(style)];
695         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
696     }
697     return sizes[controlSizeForFont(style)];
698 }
699
700 IntSize RenderThemeChromiumMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
701 {
702     if (style->effectiveZoom() != 1.0f) {
703         IntSize result = sizes[controlSizeForSystemFont(style)];
704         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
705     }
706     return sizes[controlSizeForSystemFont(style)];
707 }
708
709 void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
710 {
711     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
712     IntSize size = sizeForFont(style, sizes);
713     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
714         style->setWidth(Length(size.width(), Fixed));
715     if (style->height().isAuto() && size.height() > 0)
716         style->setHeight(Length(size.height(), Fixed));
717 }
718
719 void RenderThemeChromiumMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
720 {
721     FontDescription fontDescription;
722     fontDescription.setIsAbsoluteSize(true);
723     fontDescription.setGenericFamily(FontDescription::SerifFamily);
724
725     NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
726     fontDescription.firstFamily().setFamily([font familyName]);
727     fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
728     fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
729
730     // Reset line height
731     style->setLineHeight(RenderStyle::initialLineHeight());
732
733     if (style->setFontDescription(fontDescription))
734         style->font().update(0);
735 }
736
737 NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const
738 {
739     int fontSize = style->fontSize();
740     if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
741         return NSRegularControlSize;
742     if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
743         return NSSmallControlSize;
744     return NSMiniControlSize;
745 }
746
747 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
748 bool RenderThemeChromiumMac::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
749 {
750     LocalCurrentGraphicsContext localContext(paintInfo.context);
751
752     // Determine the width and height needed for the control and prepare the cell for painting.
753     setCheckboxCellState(o, r);
754
755     paintInfo.context->save();
756
757     float zoomLevel = o->style()->effectiveZoom();
758
759     // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
760     // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
761     NSButtonCell* checkbox = this->checkbox();
762     IntSize size = checkboxSizes()[[checkbox controlSize]];
763     size.setWidth(size.width() * zoomLevel);
764     size.setHeight(size.height() * zoomLevel);
765     IntRect inflatedRect = inflateRect(r, size, checkboxMargins(), zoomLevel);
766     
767     if (zoomLevel != 1.0f) {
768         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
769         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
770         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
771         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
772         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
773     }
774     
775     [checkbox drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil];
776     [checkbox setControlView:nil];
777
778     paintInfo.context->restore();
779
780     return false;
781 }
782
783 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
784 const IntSize* RenderThemeChromiumMac::checkboxSizes() const
785 {
786     static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
787     return sizes;
788 }
789
790 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
791 const int* RenderThemeChromiumMac::checkboxMargins() const
792 {
793     static const int margins[3][4] =
794     {
795         { 3, 4, 4, 2 },
796         { 4, 3, 3, 3 },
797         { 4, 3, 3, 3 },
798     };
799     return margins[[checkbox() controlSize]];
800 }
801
802 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
803 void RenderThemeChromiumMac::setCheckboxCellState(const RenderObject* o, const IntRect& r)
804 {
805     NSButtonCell* checkbox = this->checkbox();
806
807     // Set the control size based off the rectangle we're painting into.
808     setControlSize(checkbox, checkboxSizes(), r.size(), o->style()->effectiveZoom());
809
810     // Update the various states we respond to.
811     updateActiveState(checkbox, o);
812     updateCheckedState(checkbox, o);
813     updateEnabledState(checkbox, o);
814     updatePressedState(checkbox, o);
815     updateFocusedState(checkbox, o);
816 }
817
818 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
819 void RenderThemeChromiumMac::setCheckboxSize(RenderStyle* style) const
820 {
821     // If the width and height are both specified, then we have nothing to do.
822     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
823         return;
824
825     // Use the font size to determine the intrinsic width of the control.
826     setSizeFromFont(style, checkboxSizes());
827 }
828
829 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
830 bool RenderThemeChromiumMac::paintRadio(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
831 {
832     LocalCurrentGraphicsContext localContext(paintInfo.context);
833
834     // Determine the width and height needed for the control and prepare the cell for painting.
835     setRadioCellState(o, r);
836
837     paintInfo.context->save();
838
839     float zoomLevel = o->style()->effectiveZoom();
840
841     // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
842     // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
843     NSButtonCell* radio = this->radio();
844     IntSize size = radioSizes()[[radio controlSize]];
845     size.setWidth(size.width() * zoomLevel);
846     size.setHeight(size.height() * zoomLevel);
847     IntRect inflatedRect = inflateRect(r, size, radioMargins(), zoomLevel);
848     
849     if (zoomLevel != 1.0f) {
850         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
851         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
852         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
853         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
854         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
855     }
856
857     [radio drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil];
858     [radio setControlView:nil];
859
860     paintInfo.context->restore();
861
862     return false;
863 }
864
865 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
866 const IntSize* RenderThemeChromiumMac::radioSizes() const
867 {
868     static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
869     return sizes;
870 }
871
872 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
873 const int* RenderThemeChromiumMac::radioMargins() const
874 {
875     static const int margins[3][4] =
876     {
877         { 2, 2, 4, 2 },
878         { 3, 2, 3, 2 },
879         { 1, 0, 2, 0 },
880     };
881     return margins[[radio() controlSize]];
882 }
883
884 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
885 void RenderThemeChromiumMac::setRadioCellState(const RenderObject* o, const IntRect& r)
886 {
887     NSButtonCell* radio = this->radio();
888
889     // Set the control size based off the rectangle we're painting into.
890     setControlSize(radio, radioSizes(), r.size(), o->style()->effectiveZoom());
891
892     // Update the various states we respond to.
893     updateActiveState(radio, o);
894     updateCheckedState(radio, o);
895     updateEnabledState(radio, o);
896     updatePressedState(radio, o);
897     updateFocusedState(radio, o);
898 }
899
900 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
901 void RenderThemeChromiumMac::setRadioSize(RenderStyle* style) const
902 {
903     // If the width and height are both specified, then we have nothing to do.
904     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
905         return;
906
907     // Use the font size to determine the intrinsic width of the control.
908     setSizeFromFont(style, radioSizes());
909 }
910
911 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
912 void RenderThemeChromiumMac::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const
913 {
914     // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
915     // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
916     // by definition constrained, since we select mini only for small cramped environments.
917     // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
918     // padding.
919     const int padding = 8 * style->effectiveZoom();
920     style->setPaddingLeft(Length(padding, Fixed));
921     style->setPaddingRight(Length(padding, Fixed));
922     style->setPaddingTop(Length(0, Fixed));
923     style->setPaddingBottom(Length(0, Fixed));
924 }
925
926 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
927 void RenderThemeChromiumMac::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
928 {
929     // There are three appearance constants for buttons.
930     // (1) Push-button is the constant for the default Aqua system button.  Push buttons will not scale vertically and will not allow
931     // custom fonts or colors.  <input>s use this constant.  This button will allow custom colors and font weights/variants but won't
932     // scale vertically.
933     // (2) square-button is the constant for the square button.  This button will allow custom fonts and colors and will scale vertically.
934     // (3) Button is the constant that means "pick the best button as appropriate."  <button>s use this constant.  This button will
935     // also scale vertically and allow custom fonts and colors.  It will attempt to use Aqua if possible and will make this determination
936     // solely on the rectangle of the control.
937
938     // Determine our control size based off our font.
939     NSControlSize controlSize = controlSizeForFont(style);
940
941     if (style->appearance() == PushButtonPart) {
942         // Ditch the border.
943         style->resetBorder();
944
945         // Height is locked to auto.
946         style->setHeight(Length(Auto));
947
948         // White-space is locked to pre
949         style->setWhiteSpace(PRE);
950
951         // Set the button's vertical size.
952         setButtonSize(style);
953
954         // Add in the padding that we'd like to use.
955         setButtonPaddingFromControlSize(style, controlSize);
956
957         // 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
958         // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
959         // system font for the control size instead.
960         setFontFromControlSize(selector, style, controlSize);
961     } else {
962         // Set a min-height so that we can't get smaller than the mini button.
963         style->setMinHeight(Length(static_cast<int>(15 * style->effectiveZoom()), Fixed));
964
965         // Reset the top and bottom borders.
966         style->resetBorderTop();
967         style->resetBorderBottom();
968     }
969
970     style->setBoxShadow(0);
971 }
972
973 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
974 const IntSize* RenderThemeChromiumMac::buttonSizes() const
975 {
976     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
977     return sizes;
978 }
979
980 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
981 const int* RenderThemeChromiumMac::buttonMargins() const
982 {
983     static const int margins[3][4] =
984     {
985         { 4, 6, 7, 6 },
986         { 4, 5, 6, 5 },
987         { 0, 1, 1, 1 },
988     };
989     return margins[[button() controlSize]];
990 }
991
992 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
993 void RenderThemeChromiumMac::setButtonSize(RenderStyle* style) const
994 {
995     // If the width and height are both specified, then we have nothing to do.
996     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
997         return;
998
999     // Use the font size to determine the intrinsic width of the control.
1000     setSizeFromFont(style, buttonSizes());
1001 }
1002
1003 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
1004 void RenderThemeChromiumMac::setButtonCellState(const RenderObject* o, const IntRect& r)
1005 {
1006     NSButtonCell* button = this->button();
1007
1008     // Set the control size based off the rectangle we're painting into.
1009     if (o->style()->appearance() == SquareButtonPart ||
1010         r.height() > buttonSizes()[NSRegularControlSize].height() * o->style()->effectiveZoom()) {
1011         // Use the square button
1012         if ([button bezelStyle] != NSShadowlessSquareBezelStyle)
1013             [button setBezelStyle:NSShadowlessSquareBezelStyle];
1014     } else if ([button bezelStyle] != NSRoundedBezelStyle)
1015         [button setBezelStyle:NSRoundedBezelStyle];
1016
1017     setControlSize(button, buttonSizes(), r.size(), o->style()->effectiveZoom());
1018
1019     NSWindow *window = [nil window];
1020     BOOL isDefaultButton = (isDefault(o) && [window isKeyWindow]);
1021     [button setKeyEquivalent:(isDefaultButton ? @"\r" : @"")];
1022
1023     // Update the various states we respond to.
1024     updateActiveState(button, o);
1025     updateCheckedState(button, o);
1026     updateEnabledState(button, o);
1027     updatePressedState(button, o);
1028     updateFocusedState(button, o);
1029 }
1030
1031 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
1032 bool RenderThemeChromiumMac::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1033 {
1034     NSButtonCell* button = this->button();
1035     LocalCurrentGraphicsContext localContext(paintInfo.context);
1036
1037     // Determine the width and height needed for the control and prepare the cell for painting.
1038     setButtonCellState(o, r);
1039
1040     paintInfo.context->save();
1041
1042     // We inflate the rect as needed to account for padding included in the cell to accommodate the button
1043     // shadow.  We don't consider this part of the bounds of the control in WebKit.
1044     float zoomLevel = o->style()->effectiveZoom();
1045     IntSize size = buttonSizes()[[button controlSize]];
1046     size.setWidth(r.width());
1047     size.setHeight(size.height() * zoomLevel);
1048     IntRect inflatedRect = r;
1049     if ([button bezelStyle] == NSRoundedBezelStyle) {
1050         // Center the button within the available space.
1051         if (inflatedRect.height() > size.height()) {
1052             inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
1053             inflatedRect.setHeight(size.height());
1054         }
1055
1056         // Now inflate it to account for the shadow.
1057         inflatedRect = inflateRect(inflatedRect, size, buttonMargins(), zoomLevel);
1058
1059         if (zoomLevel != 1.0f) {
1060             inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
1061             inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
1062             paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
1063             paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1064             paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
1065         }
1066     } 
1067
1068     NSView *view = nil;
1069     NSWindow *window = [view window];
1070     NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell];
1071
1072     if (isDefault(o) && [window isKeyWindow]) {
1073         [window setDefaultButtonCell:button];
1074         wkAdvanceDefaultButtonPulseAnimation(button);
1075     } else if ([previousDefaultButtonCell isEqual:button])
1076         [window setDefaultButtonCell:nil];
1077
1078     [button drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:view];
1079     [button setControlView:nil];
1080
1081     if (![previousDefaultButtonCell isEqual:button])
1082         [window setDefaultButtonCell:previousDefaultButtonCell];
1083
1084     paintInfo.context->restore();
1085
1086     return false;
1087 }
1088
1089 bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1090 {
1091     LocalCurrentGraphicsContext localContext(paintInfo.context);
1092     wkDrawBezeledTextFieldCell(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o));
1093     return false;
1094 }
1095
1096 void RenderThemeChromiumMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1097 {
1098 }
1099
1100 bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1101 {
1102     if (paintInfo.context->paintingDisabled())
1103         return true;
1104
1105     LocalCurrentGraphicsContext localContext(paintInfo.context);
1106     wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
1107     
1108     return false;
1109 }
1110
1111 bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1112 {
1113     LocalCurrentGraphicsContext localContext(paintInfo.context);
1114     wkDrawBezeledTextArea(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o));
1115     return false;
1116 }
1117
1118 void RenderThemeChromiumMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1119 {
1120 }
1121
1122 const int* RenderThemeChromiumMac::popupButtonMargins() const
1123 {
1124     static const int margins[3][4] =
1125     {
1126         { 0, 3, 1, 3 },
1127         { 0, 3, 2, 3 },
1128         { 0, 1, 0, 1 }
1129     };
1130     return margins[[popupButton() controlSize]];
1131 }
1132
1133 const IntSize* RenderThemeChromiumMac::popupButtonSizes() const
1134 {
1135     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
1136     return sizes;
1137 }
1138
1139 const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const
1140 {
1141     static const int padding[3][4] =
1142     {
1143         { 2, 26, 3, 8 },
1144         { 2, 23, 3, 8 },
1145         { 2, 22, 3, 10 }
1146     };
1147     return padding[size];
1148 }
1149
1150 bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1151 {
1152     LocalCurrentGraphicsContext localContext(paintInfo.context);
1153
1154     setPopupButtonCellState(o, r);
1155
1156     NSPopUpButtonCell* popupButton = this->popupButton();
1157
1158     float zoomLevel = o->style()->effectiveZoom();
1159     IntSize size = popupButtonSizes()[[popupButton controlSize]];
1160     size.setHeight(size.height() * zoomLevel);
1161     size.setWidth(r.width());
1162
1163     // Now inflate it to account for the shadow.
1164     IntRect inflatedRect = r;
1165     if (r.width() >= minimumMenuListSize(o->style()))
1166         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
1167
1168     paintInfo.context->save();
1169     
1170 #ifndef BUILDING_ON_TIGER
1171     // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
1172     paintInfo.context->clip(inflatedRect);
1173 #endif
1174
1175     if (zoomLevel != 1.0f) {
1176         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
1177         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
1178         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
1179         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1180         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
1181     }
1182
1183     [popupButton drawWithFrame:IntRectToNSRect(inflatedRect) inView:nil];
1184     [popupButton setControlView:nil];
1185
1186     paintInfo.context->restore();
1187
1188     return false;
1189 }
1190
1191 static const float baseFontSize = 11.0f;
1192 static const float baseArrowHeight = 4.0f;
1193 static const float baseArrowWidth = 5.0f;
1194 static const float baseSpaceBetweenArrows = 2.0f;
1195 static const int arrowPaddingLeft = 6;
1196 static const int arrowPaddingRight = 6;
1197 static const int paddingBeforeSeparator = 4;
1198 static const int baseBorderRadius = 5;
1199 static const int styledPopupPaddingLeft = 8;
1200 static const int styledPopupPaddingTop = 1;
1201 static const int styledPopupPaddingBottom = 2;
1202
1203 static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
1204 {
1205     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
1206     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
1207     float a = inData[0];
1208     int i = 0;
1209     for (i = 0; i < 4; i++)
1210         outData[i] = (1.0f - a) * dark[i] + a * light[i];
1211 }
1212
1213 static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
1214 {
1215     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
1216     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
1217     float a = inData[0];
1218     int i = 0;
1219     for (i = 0; i < 4; i++)
1220         outData[i] = (1.0f - a) * dark[i] + a * light[i];
1221 }
1222
1223 static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
1224 {
1225     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
1226     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1227     float a = inData[0];
1228     int i = 0;
1229     for (i = 0; i < 4; i++)
1230         outData[i] = (1.0f - a) * dark[i] + a * light[i];
1231 }
1232
1233 static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
1234 {
1235     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
1236     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
1237     float a = inData[0];
1238     int i = 0;
1239     for (i = 0; i < 4; i++)
1240         outData[i] = (1.0f - a) * dark[i] + a * light[i];
1241 }
1242
1243 void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1244 {
1245     CGContextRef context = paintInfo.context->platformContext();
1246
1247     paintInfo.context->save();
1248
1249     int radius = o->style()->borderTopLeftRadius().width();
1250
1251     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1252
1253     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
1254     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
1255     RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
1256     RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
1257
1258     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
1259     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
1260     RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
1261     RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
1262
1263     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
1264     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1265     RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
1266
1267     RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
1268
1269     RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
1270     paintInfo.context->save();
1271     CGContextClipToRect(context, r);
1272     paintInfo.context->addRoundedRectClip(r,
1273         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1274         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1275     CGContextDrawShading(context, mainShading.get());
1276     paintInfo.context->restore();
1277
1278     paintInfo.context->save();
1279     CGContextClipToRect(context, topGradient);
1280     paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
1281         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1282         IntSize(), IntSize());
1283     CGContextDrawShading(context, topShading.get());
1284     paintInfo.context->restore();
1285
1286     paintInfo.context->save();
1287     CGContextClipToRect(context, bottomGradient);
1288     paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
1289         IntSize(), IntSize(),
1290         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1291     CGContextDrawShading(context, bottomShading.get());
1292     paintInfo.context->restore();
1293
1294     paintInfo.context->save();
1295     CGContextClipToRect(context, r);
1296     paintInfo.context->addRoundedRectClip(r,
1297         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1298         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1299     CGContextDrawShading(context, leftShading.get());
1300     CGContextDrawShading(context, rightShading.get());
1301     paintInfo.context->restore();
1302
1303     paintInfo.context->restore();
1304 }
1305
1306 bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1307 {
1308     paintInfo.context->save();
1309
1310     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
1311                              r.y() + o->style()->borderTopWidth(),
1312                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
1313                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
1314     // Draw the gradients to give the styled popup menu a button appearance
1315     paintMenuListButtonGradients(o, paintInfo, bounds);
1316
1317     // 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
1318     float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
1319     float centerY = bounds.y() + bounds.height() / 2.0f;
1320     float arrowHeight = baseArrowHeight * fontScale;
1321     float arrowWidth = baseArrowWidth * fontScale;
1322     float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
1323     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
1324
1325     if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
1326         return false;
1327     
1328     paintInfo.context->setFillColor(o->style()->color());
1329     paintInfo.context->setStrokeStyle(NoStroke);
1330
1331     FloatPoint arrow1[3];
1332     arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
1333     arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
1334     arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
1335
1336     // Draw the top arrow
1337     paintInfo.context->drawConvexPolygon(3, arrow1, true);
1338
1339     FloatPoint arrow2[3];
1340     arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
1341     arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
1342     arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
1343
1344     // Draw the bottom arrow
1345     paintInfo.context->drawConvexPolygon(3, arrow2, true);
1346
1347     Color leftSeparatorColor(0, 0, 0, 40);
1348     Color rightSeparatorColor(255, 255, 255, 40);
1349
1350     // FIXME: Should the separator thickness and space be scaled up by fontScale?
1351     int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
1352     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
1353
1354     // Draw the separator to the left of the arrows
1355     paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
1356     paintInfo.context->setStrokeStyle(SolidStroke);
1357     paintInfo.context->setStrokeColor(leftSeparatorColor);
1358     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
1359                                 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
1360
1361     paintInfo.context->setStrokeColor(rightSeparatorColor);
1362     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
1363                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
1364
1365     paintInfo.context->restore();
1366     return false;
1367 }
1368
1369 static const IntSize* menuListButtonSizes()
1370 {
1371     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
1372     return sizes;
1373 }
1374
1375 void RenderThemeChromiumMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1376 {
1377     NSControlSize controlSize = controlSizeForFont(style);
1378
1379     style->resetBorder();
1380     style->resetPadding();
1381     
1382     // Height is locked to auto.
1383     style->setHeight(Length(Auto));
1384
1385     // White-space is locked to pre
1386     style->setWhiteSpace(PRE);
1387
1388     // Set the foreground color to black or gray when we have the aqua look.
1389     // Cast to RGB32 is to work around a compiler bug.
1390     style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
1391
1392     // Set the button's vertical size.
1393     setSizeFromFont(style, menuListButtonSizes());
1394
1395     // 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
1396     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
1397     // system font for the control size instead.
1398     setFontFromControlSize(selector, style, controlSize);
1399
1400     style->setBoxShadow(0);
1401 }
1402
1403 int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const
1404 {
1405     if (style->appearance() == MenulistPart)
1406         return popupButtonPadding(controlSizeForFont(style))[LeftPadding] * style->effectiveZoom();
1407     if (style->appearance() == MenulistButtonPart)
1408         return styledPopupPaddingLeft * style->effectiveZoom();
1409     return 0;
1410 }
1411
1412 int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
1413 {
1414     if (style->appearance() == MenulistPart)
1415         return popupButtonPadding(controlSizeForFont(style))[RightPadding] * style->effectiveZoom();
1416     if (style->appearance() == MenulistButtonPart) {
1417         float fontScale = style->fontSize() / baseFontSize;
1418         float arrowWidth = baseArrowWidth * fontScale;
1419         return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
1420     }
1421     return 0;
1422 }
1423
1424 int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const
1425 {
1426     if (style->appearance() == MenulistPart)
1427         return popupButtonPadding(controlSizeForFont(style))[TopPadding] * style->effectiveZoom();
1428     if (style->appearance() == MenulistButtonPart)
1429         return styledPopupPaddingTop * style->effectiveZoom();
1430     return 0;
1431 }
1432
1433 int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const
1434 {
1435     if (style->appearance() == MenulistPart)
1436         return popupButtonPadding(controlSizeForFont(style))[BottomPadding] * style->effectiveZoom();
1437     if (style->appearance() == MenulistButtonPart)
1438         return styledPopupPaddingBottom * style->effectiveZoom();
1439     return 0;
1440 }
1441
1442 void RenderThemeChromiumMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1443 {
1444     float fontScale = style->fontSize() / baseFontSize;
1445
1446     style->resetPadding();
1447     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1448
1449     const int minHeight = 15;
1450     style->setMinHeight(Length(minHeight, Fixed));
1451     
1452     style->setLineHeight(RenderStyle::initialLineHeight());
1453 }
1454
1455 void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1456 {
1457     NSPopUpButtonCell* popupButton = this->popupButton();
1458
1459     // Set the control size based off the rectangle we're painting into.
1460     setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
1461
1462     // Update the various states we respond to.
1463     updateActiveState(popupButton, o);
1464     updateCheckedState(popupButton, o);
1465     updateEnabledState(popupButton, o);
1466     updatePressedState(popupButton, o);
1467     updateFocusedState(popupButton, o);
1468 }
1469
1470 const IntSize* RenderThemeChromiumMac::menuListSizes() const
1471 {
1472     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1473     return sizes;
1474 }
1475
1476 int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const
1477 {
1478     return sizeForSystemFont(style, menuListSizes()).width();
1479 }
1480
1481 static Image* mediaSliderThumbImage()
1482 {
1483     static Image* mediaSliderThumb = Image::loadPlatformResource("mediaSliderThumb").releaseRef();
1484     return mediaSliderThumb;
1485 }
1486   
1487 static Image* mediaVolumeSliderThumbImage()
1488 {
1489     static Image* mediaVolumeSliderThumb = Image::loadPlatformResource("mediaVolumeSliderThumb").releaseRef();
1490     return mediaVolumeSliderThumb;
1491 }
1492   
1493 void RenderThemeChromiumMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1494 {
1495     style->setBoxShadow(0);
1496 }
1497
1498 bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1499 {
1500     static const int trackWidth = 5;
1501     static const int trackRadius = 2;
1502   
1503     IntRect bounds = r;
1504     float zoomLevel = o->style()->effectiveZoom();
1505     float zoomedTrackWidth = trackWidth * zoomLevel;
1506
1507     if (o->style()->appearance() ==  SliderHorizontalPart || o->style()->appearance() ==  MediaSliderPart) {
1508         bounds.setHeight(zoomedTrackWidth);
1509         bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
1510     } else if (o->style()->appearance() == SliderVerticalPart) {
1511         bounds.setWidth(zoomedTrackWidth);
1512         bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
1513     }
1514
1515     LocalCurrentGraphicsContext localContext(paintInfo.context);
1516     CGContextRef context = paintInfo.context->platformContext();
1517     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1518
1519     paintInfo.context->save();
1520     CGContextClipToRect(context, bounds);
1521
1522     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
1523     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1524     RetainPtr<CGShadingRef> mainShading;
1525     if (o->style()->appearance() == SliderVerticalPart)
1526         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
1527     else
1528         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
1529
1530     IntSize radius(trackRadius, trackRadius);
1531     paintInfo.context->addRoundedRectClip(bounds,
1532         radius, radius,
1533         radius, radius);
1534     CGContextDrawShading(context, mainShading.get());
1535     paintInfo.context->restore();
1536     
1537     return false;
1538 }
1539
1540 void RenderThemeChromiumMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1541 {
1542     style->setBoxShadow(0);
1543 }
1544
1545 static const float verticalSliderHeightPadding = 0.1f;
1546
1547 bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1548 {
1549     ASSERT(o->parent()->isSlider());
1550
1551     NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
1552         ? sliderThumbVertical()
1553         : sliderThumbHorizontal();
1554
1555     LocalCurrentGraphicsContext localContext(paintInfo.context);
1556
1557     // Update the various states we respond to.
1558     updateActiveState(sliderThumbCell, o);
1559     updateEnabledState(sliderThumbCell, o->parent());
1560     updateFocusedState(sliderThumbCell, o->parent());
1561
1562     // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
1563     bool oldPressed;
1564     if (o->style()->appearance() == SliderThumbVerticalPart)
1565         oldPressed = m_isSliderThumbVerticalPressed;
1566     else
1567         oldPressed = m_isSliderThumbHorizontalPressed;
1568
1569     bool pressed = toRenderSlider(o->parent())->inDragMode();
1570
1571     if (o->style()->appearance() == SliderThumbVerticalPart)
1572         m_isSliderThumbVerticalPressed = pressed;
1573     else
1574         m_isSliderThumbHorizontalPressed = pressed;
1575
1576     if (pressed != oldPressed) {
1577         if (pressed)
1578             [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
1579         else
1580             [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
1581     }
1582
1583     FloatRect bounds = r;
1584     // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
1585     if (o->style()->appearance() == SliderThumbVerticalPart)
1586         bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
1587
1588     paintInfo.context->save();
1589     float zoomLevel = o->style()->effectiveZoom();
1590     
1591     FloatRect unzoomedRect = bounds;
1592     if (zoomLevel != 1.0f) {
1593         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1594         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1595         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1596         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1597         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1598     }
1599
1600     [sliderThumbCell drawWithFrame:FloatRectToNSRect(unzoomedRect) inView:nil];
1601     [sliderThumbCell setControlView:nil];
1602
1603     paintInfo.context->restore();
1604
1605     return false;
1606 }
1607
1608 const int sliderThumbWidth = 15;
1609 const int sliderThumbHeight = 15;
1610
1611 void RenderThemeChromiumMac::adjustSliderThumbSize(RenderObject* o) const
1612 {
1613     float zoomLevel = o->style()->effectiveZoom();
1614     if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
1615         o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
1616         o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
1617     }
1618
1619 #if ENABLE(VIDEO)
1620     Image* thumbImage = 0;
1621     if (o->style()->appearance() == MediaSliderThumbPart)
1622         thumbImage = mediaSliderThumbImage();
1623     else if (o->style()->appearance() == MediaVolumeSliderThumbPart)
1624         thumbImage = mediaVolumeSliderThumbImage();
1625   
1626     if (thumbImage) {
1627         o->style()->setWidth(Length(thumbImage->width(), Fixed));
1628         o->style()->setHeight(Length(thumbImage->height(), Fixed));
1629     }
1630 #endif
1631 }
1632
1633 bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1634 {
1635     NSSearchFieldCell* search = this->search();
1636     LocalCurrentGraphicsContext localContext(paintInfo.context);
1637
1638     setSearchCellState(o, r);
1639
1640     paintInfo.context->save();
1641
1642     float zoomLevel = o->style()->effectiveZoom();
1643
1644     IntRect unzoomedRect = r;
1645     
1646     if (zoomLevel != 1.0f) {
1647         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1648         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1649         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1650         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1651         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1652     }
1653
1654     // Set the search button to nil before drawing.  Then reset it so we can draw it later.
1655     [search setSearchButtonCell:nil];
1656
1657     [search drawWithFrame:NSRect(IntRectToNSRect(unzoomedRect)) inView:nil];
1658 #ifdef BUILDING_ON_TIGER
1659     if ([search showsFirstResponder])
1660         wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
1661 #endif
1662
1663     [search setControlView:nil];
1664     [search resetSearchButtonCell];
1665
1666     paintInfo.context->restore();
1667
1668     return false;
1669 }
1670
1671 void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect& r)
1672 {
1673     NSSearchFieldCell* search = this->search();
1674
1675     [search setControlSize:controlSizeForFont(o->style())];
1676
1677     // Update the various states we respond to.
1678     updateActiveState(search, o);
1679     updateEnabledState(search, o);
1680     updateFocusedState(search, o);
1681 }
1682
1683 const IntSize* RenderThemeChromiumMac::searchFieldSizes() const
1684 {
1685     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
1686     return sizes;
1687 }
1688
1689 void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const
1690 {
1691     // If the width and height are both specified, then we have nothing to do.
1692     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1693         return;
1694     
1695     // Use the font size to determine the intrinsic width of the control.
1696     setSizeFromFont(style, searchFieldSizes());
1697 }
1698
1699 void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1700 {
1701     // Override border.
1702     style->resetBorder();
1703     const short borderWidth = 2 * style->effectiveZoom();
1704     style->setBorderLeftWidth(borderWidth);
1705     style->setBorderLeftStyle(INSET);
1706     style->setBorderRightWidth(borderWidth);
1707     style->setBorderRightStyle(INSET);
1708     style->setBorderBottomWidth(borderWidth);
1709     style->setBorderBottomStyle(INSET);
1710     style->setBorderTopWidth(borderWidth);
1711     style->setBorderTopStyle(INSET);    
1712     
1713     // Override height.
1714     style->setHeight(Length(Auto));
1715     setSearchFieldSize(style);
1716     
1717     // Override padding size to match AppKit text positioning.
1718     const int padding = 1 * style->effectiveZoom();
1719     style->setPaddingLeft(Length(padding, Fixed));
1720     style->setPaddingRight(Length(padding, Fixed));
1721     style->setPaddingTop(Length(padding, Fixed));
1722     style->setPaddingBottom(Length(padding, Fixed));
1723     
1724     NSControlSize controlSize = controlSizeForFont(style);
1725     setFontFromControlSize(selector, style, controlSize);
1726
1727     style->setBoxShadow(0);
1728 }
1729
1730 bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1731 {
1732     LocalCurrentGraphicsContext localContext(paintInfo.context);
1733
1734     Node* input = o->node()->shadowAncestorNode();
1735     setSearchCellState(input->renderer(), r);
1736
1737     NSSearchFieldCell* search = this->search();
1738
1739     updateActiveState([search cancelButtonCell], o);
1740     updatePressedState([search cancelButtonCell], o);
1741
1742     paintInfo.context->save();
1743
1744     float zoomLevel = o->style()->effectiveZoom();
1745
1746     NSRect bounds = [search cancelButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
1747     
1748     IntRect unzoomedRect(NSRectToIntRect(bounds));
1749     if (zoomLevel != 1.0f) {
1750         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1751         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1752         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1753         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1754         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1755     }
1756
1757     [[search cancelButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil];
1758     [[search cancelButtonCell] setControlView:nil];
1759
1760     paintInfo.context->restore();
1761     return false;
1762 }
1763
1764 const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const
1765 {
1766     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1767     return sizes;
1768 }
1769
1770 void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1771 {
1772     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1773     style->setWidth(Length(size.width(), Fixed));
1774     style->setHeight(Length(size.height(), Fixed));
1775     style->setBoxShadow(0);
1776 }
1777
1778 const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const
1779 {
1780     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1781     return sizes;
1782 }
1783
1784 static const int emptyResultsOffset = 9;
1785 void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1786 {
1787     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1788     style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1789     style->setHeight(Length(size.height(), Fixed));
1790     style->setBoxShadow(0);
1791 }
1792
1793 bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1794 {
1795     return false;
1796 }
1797
1798 void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1799 {
1800     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1801     style->setWidth(Length(size.width(), Fixed));
1802     style->setHeight(Length(size.height(), Fixed));
1803     style->setBoxShadow(0);
1804 }
1805
1806 bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1807 {
1808     LocalCurrentGraphicsContext localContext(paintInfo.context);
1809
1810     Node* input = o->node()->shadowAncestorNode();
1811     setSearchCellState(input->renderer(), r);
1812
1813     NSSearchFieldCell* search = this->search();
1814
1815     updateActiveState([search searchButtonCell], o);
1816
1817     if ([search searchMenuTemplate] != nil)
1818         [search setSearchMenuTemplate:nil];
1819
1820     NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
1821     [[search searchButtonCell] drawWithFrame:bounds inView:nil];
1822     [[search searchButtonCell] setControlView:nil];
1823     return false;
1824 }
1825
1826 static const int resultsArrowWidth = 5;
1827 void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1828 {
1829     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1830     style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1831     style->setHeight(Length(size.height(), Fixed));
1832     style->setBoxShadow(0);
1833 }
1834
1835 bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1836 {
1837     LocalCurrentGraphicsContext localContext(paintInfo.context);
1838
1839     Node* input = o->node()->shadowAncestorNode();
1840     setSearchCellState(input->renderer(), r);
1841
1842     NSSearchFieldCell* search = this->search();
1843
1844     updateActiveState([search searchButtonCell], o);
1845
1846     if (![search searchMenuTemplate])
1847         [search setSearchMenuTemplate:searchMenuTemplate()];
1848
1849     paintInfo.context->save();
1850
1851     float zoomLevel = o->style()->effectiveZoom();
1852
1853     NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
1854     
1855     IntRect unzoomedRect(NSRectToIntRect(bounds));
1856     if (zoomLevel != 1.0f) {
1857         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1858         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1859         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1860         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
1861         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1862     }
1863
1864     [[search searchButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil];
1865     [[search searchButtonCell] setControlView:nil];
1866     
1867     paintInfo.context->restore();
1868
1869     return false;
1870 }
1871
1872 bool RenderThemeChromiumMac::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image)
1873 {
1874     // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down.
1875     IntRect imageRect = image->rect();
1876     imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2);
1877     imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2);
1878
1879     context->drawImage(image, imageRect);
1880     return true;
1881 }
1882
1883 bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
1884 {
1885 #if ENABLE(VIDEO)
1886     HTMLMediaElement* mediaElement = mediaElementParent(object->node());
1887     if (!mediaElement)
1888         return false;
1889
1890     static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef();
1891     static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef();
1892     static Image* mediaPlayDisabled = Image::loadPlatformResource("mediaPlayDisabled").releaseRef();
1893
1894     if (mediaElement->networkState() == HTMLMediaElement::NETWORK_NO_SOURCE)
1895         return paintMediaButtonInternal(paintInfo.context, rect, mediaPlayDisabled);
1896
1897     return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
1898 #else
1899     UNUSED_PARAM(object);
1900     UNUSED_PARAM(paintInfo);
1901     UNUSED_PARAM(rect);
1902     return false;
1903 #endif
1904 }
1905
1906 bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
1907 {
1908 #if ENABLE(VIDEO)
1909     HTMLMediaElement* mediaElement = mediaElementParent(object->node());
1910     if (!mediaElement)
1911         return false;
1912
1913     static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef();
1914     static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef();
1915     static Image* soundDisabled = Image::loadPlatformResource("mediaSoundDisabled").releaseRef();
1916
1917     if (mediaElement->networkState() == HTMLMediaElement::NETWORK_NO_SOURCE || !mediaElement->hasAudio())
1918         return paintMediaButtonInternal(paintInfo.context, rect, soundDisabled);
1919
1920     return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone : soundFull);
1921 #else
1922     UNUSED_PARAM(object);
1923     UNUSED_PARAM(paintInfo);
1924     UNUSED_PARAM(rect);
1925     return false;
1926 #endif
1927 }
1928
1929 bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
1930 {
1931 #if ENABLE(VIDEO)
1932     HTMLMediaElement* mediaElement = mediaElementParent(object->node());
1933     if (!mediaElement)
1934         return false;
1935
1936     RenderStyle* style = object->style();    
1937     GraphicsContext* context = paintInfo.context;
1938     context->save();
1939     
1940     context->setShouldAntialias(true);
1941
1942     IntSize topLeftRadius = style->borderTopLeftRadius();
1943     IntSize topRightRadius = style->borderTopRightRadius();
1944     IntSize bottomLeftRadius = style->borderBottomLeftRadius();
1945     IntSize bottomRightRadius = style->borderBottomRightRadius();
1946     float borderWidth = style->borderLeftWidth();
1947
1948     // Draw the border of the time bar.
1949     context->setStrokeColor(style->borderLeftColor());
1950     context->setStrokeThickness(borderWidth);
1951     context->setFillColor(style->backgroundColor());
1952     context->addPath(Path::createRoundedRectangle(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius));
1953     context->drawPath();
1954     
1955     // Draw the buffered ranges.
1956     // FIXME: Draw multiple ranges if there are multiple buffered ranges.
1957     FloatRect bufferedRect = rect;
1958     bufferedRect.inflate(-1.0 - borderWidth);
1959     bufferedRect.setWidth(bufferedRect.width() * mediaElement->percentLoaded());
1960     bufferedRect = context->roundToDevicePixels(bufferedRect);
1961    
1962     // Don't bother drawing an empty area.
1963     if (bufferedRect.width() > 0 && bufferedRect.height() > 0) {
1964         FloatPoint sliderTopLeft = bufferedRect.location();
1965         FloatPoint sliderTopRight = sliderTopLeft;
1966         p1.move(0.0f, bufferedRect.height());
1967         
1968         RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
1969         Color startColor = object->style()->color();
1970         gradient->addColorStop(0.0, startColor);
1971         gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));
1972  
1973         context->setFillGradient(gradient);
1974         context->addPath(Path::createRoundedRectangle(bufferedRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius));
1975         context->fillPath();
1976     }
1977     
1978     context->restore();    
1979     return true;
1980 #else
1981     UNUSED_PARAM(object);
1982     UNUSED_PARAM(paintInfo);
1983     UNUSED_PARAM(rect);
1984     return false;
1985 #endif
1986 }
1987
1988 bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
1989 {
1990 #if ENABLE(VIDEO)
1991     HTMLMediaElement* mediaElement = mediaElementParent(object->node());
1992     if (!mediaElement)
1993         return false;
1994
1995     GraphicsContext* context = paintInfo.context;
1996     Color originalColor = context->strokeColor();
1997     if (originalColor != Color::white)
1998         context->setStrokeColor(Color::white);
1999
2000     int x = rect.x() + rect.width() / 2;
2001     context->drawLine(IntPoint(x, rect.y()),  IntPoint(x, rect.y() + rect.height()));
2002     
2003     if (originalColor != Color::white)
2004         context->setStrokeColor(originalColor);
2005     return true;
2006 #else
2007     UNUSED_PARAM(object);
2008     UNUSED_PARAM(paintInfo);
2009     UNUSED_PARAM(rect);
2010     return false;
2011 #endif
2012 }
2013
2014 bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
2015 {
2016 #if ENABLE(VIDEO)
2017     if (!object->parent()->isSlider())
2018         return false;
2019
2020     return paintMediaButtonInternal(paintInfo.context, rect, mediaSliderThumbImage());
2021 #else
2022     UNUSED_PARAM(object);
2023     UNUSED_PARAM(paintInfo);
2024     UNUSED_PARAM(rect);
2025     return false;
2026 #endif
2027 }
2028
2029 bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
2030 {
2031 #if ENABLE(VIDEO)
2032     if (!object->parent()->isSlider())
2033         return false;
2034
2035     return paintMediaButtonInternal(paintInfo.context, rect, mediaVolumeSliderThumbImage());
2036 #else
2037     UNUSED_PARAM(object);
2038     UNUSED_PARAM(paintInfo);
2039     UNUSED_PARAM(rect);
2040     return false;
2041 #endif
2042 }
2043
2044 bool RenderThemeChromiumMac::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
2045 {
2046 #if ENABLE(VIDEO)
2047     HTMLMediaElement* mediaElement = mediaElementParent(object->node());
2048     if (!mediaElement)
2049         return false;
2050
2051     if (!rect.isEmpty())
2052     {
2053         GraphicsContext* context = paintInfo.context;
2054         Color originalColor = context->strokeColor();
2055  
2056         // Draws the left border, it is always 1px wide.
2057         context->setStrokeColor(object->style()->borderLeftColor());
2058         context->drawLine(IntPoint(rect.x() + 1, rect.y()),
2059                           IntPoint(rect.x() + 1, rect.y() + rect.height()));
2060                          
2061
2062         // Draws the right border, it is always 1px wide.
2063         context->setStrokeColor(object->style()->borderRightColor());
2064         context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()),
2065                           IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height()));
2066         
2067         context->setStrokeColor(originalColor);
2068     }
2069     return true;
2070 #else
2071     UNUSED_PARAM(object);
2072     UNUSED_PARAM(paintInfo);
2073     UNUSED_PARAM(rect);
2074     return false;
2075 #endif
2076 }
2077
2078 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
2079 NSButtonCell* RenderThemeChromiumMac::checkbox() const
2080 {
2081     if (!m_checkbox) {
2082         m_checkbox.adoptNS([[NSButtonCell alloc] init]);
2083         [m_checkbox.get() setButtonType:NSSwitchButton];
2084         [m_checkbox.get() setTitle:nil];
2085         [m_checkbox.get() setAllowsMixedState:YES];
2086         [m_checkbox.get() setFocusRingType:NSFocusRingTypeExterior];
2087     }
2088     
2089     return m_checkbox.get();
2090 }
2091
2092 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
2093 NSButtonCell* RenderThemeChromiumMac::radio() const
2094 {
2095     if (!m_radio) {
2096         m_radio.adoptNS([[NSButtonCell alloc] init]);
2097         [m_radio.get() setButtonType:NSRadioButton];
2098         [m_radio.get() setTitle:nil];
2099         [m_radio.get() setFocusRingType:NSFocusRingTypeExterior];
2100     }
2101     
2102     return m_radio.get();
2103 }
2104
2105 // FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
2106 NSButtonCell* RenderThemeChromiumMac::button() const
2107 {
2108     if (!m_button) {
2109         m_button.adoptNS([[NSButtonCell alloc] init]);
2110         [m_button.get() setTitle:nil];
2111         [m_button.get() setButtonType:NSMomentaryPushInButton];
2112     }
2113     
2114     return m_button.get();
2115 }
2116
2117 NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const
2118 {
2119     if (!m_popupButton) {
2120         m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
2121         [m_popupButton.get() setUsesItemFromMenu:NO];
2122         [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
2123     }
2124     
2125     return m_popupButton.get();
2126 }
2127
2128 NSSearchFieldCell* RenderThemeChromiumMac::search() const
2129 {
2130     if (!m_search) {
2131         m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
2132         [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
2133         [m_search.get() setBezeled:YES];
2134         [m_search.get() setEditable:YES];
2135         [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
2136     }
2137
2138     return m_search.get();
2139 }
2140
2141 NSMenu* RenderThemeChromiumMac::searchMenuTemplate() const
2142 {
2143     if (!m_searchMenuTemplate)
2144         m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
2145
2146     return m_searchMenuTemplate.get();
2147 }
2148
2149 NSSliderCell* RenderThemeChromiumMac::sliderThumbHorizontal() const
2150 {
2151     if (!m_sliderThumbHorizontal) {
2152         m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
2153         [m_sliderThumbHorizontal.get() setTitle:nil];
2154         [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
2155         [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
2156         [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
2157     }
2158     
2159     return m_sliderThumbHorizontal.get();
2160 }
2161
2162 NSSliderCell* RenderThemeChromiumMac::sliderThumbVertical() const
2163 {
2164     if (!m_sliderThumbVertical) {
2165         m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
2166         [m_sliderThumbVertical.get() setTitle:nil];
2167         [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
2168         [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
2169         [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
2170     }
2171     
2172     return m_sliderThumbVertical.get();
2173 }
2174
2175 } // namespace WebCore