c2dd6c02b4bc566a480dd35011b49d65f0af9a7e
[WebKit-https.git] / WebCore / rendering / RenderTheme.cpp
1 /**
2  * This file is part of the theme implementation for form controls in WebCore.
3  *
4  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Computer, Inc.
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 #include "config.h"
23 #include "RenderTheme.h"
24
25 #include "CSSValueKeywords.h"
26 #include "Document.h"
27 #include "FloatConversion.h"
28 #include "FocusController.h"
29 #include "FontSelector.h"
30 #include "Frame.h"
31 #include "GraphicsContext.h"
32 #include "HTMLInputElement.h"
33 #include "HTMLNames.h"
34 #include "MediaControlElements.h"
35 #include "Page.h"
36 #include "RenderStyle.h"
37 #include "RenderView.h"
38 #include "SelectionController.h"
39 #include "Settings.h"
40 #include "TextControlInnerElements.h"
41
42 #if ENABLE(METER_TAG)
43 #include "HTMLMeterElement.h"
44 #include "RenderMeter.h"
45 #endif
46
47 #if ENABLE(INPUT_SPEECH)
48 #include "RenderInputSpeech.h"
49 #endif
50
51 // The methods in this file are shared by all themes on every platform.
52
53 namespace WebCore {
54
55 using namespace HTMLNames;
56
57 static Color& customFocusRingColor()
58 {
59     DEFINE_STATIC_LOCAL(Color, color, ());
60     return color;
61 }
62
63 RenderTheme::RenderTheme()
64 #if USE(NEW_THEME)
65     : m_theme(platformTheme())
66 #endif
67 {
68 }
69
70 void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e,
71                               bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
72 {
73     // Force inline and table display styles to be inline-block (except for table- which is block)
74     ControlPart part = style->appearance();
75     if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP ||
76         style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP ||
77         style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN ||
78         style->display() == TABLE_CELL || style->display() == TABLE_CAPTION)
79         style->setDisplay(INLINE_BLOCK);
80     else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE)
81         style->setDisplay(BLOCK);
82
83     if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) {
84         if (part == MenulistPart) {
85             style->setAppearance(MenulistButtonPart);
86             part = MenulistButtonPart;
87         } else
88             style->setAppearance(NoControlPart);
89     }
90
91     if (!style->hasAppearance())
92         return;
93
94     // Never support box-shadow on native controls.
95     style->setBoxShadow(0);
96     
97 #if USE(NEW_THEME)
98     switch (part) {
99         case ListButtonPart:
100         case CheckboxPart:
101         case InnerSpinButtonPart:
102         case OuterSpinButtonPart:
103         case RadioPart:
104         case PushButtonPart:
105         case SquareButtonPart:
106         case DefaultButtonPart:
107         case ButtonPart: {
108             // Border
109             LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth());
110             borderBox = m_theme->controlBorder(part, style->font(), borderBox, style->effectiveZoom());
111             if (borderBox.top().value() != style->borderTopWidth()) {
112                 if (borderBox.top().value())
113                     style->setBorderTopWidth(borderBox.top().value());
114                 else
115                     style->resetBorderTop();
116             }
117             if (borderBox.right().value() != style->borderRightWidth()) {
118                 if (borderBox.right().value())
119                     style->setBorderRightWidth(borderBox.right().value());
120                 else
121                     style->resetBorderRight();
122             }
123             if (borderBox.bottom().value() != style->borderBottomWidth()) {
124                 style->setBorderBottomWidth(borderBox.bottom().value());
125                 if (borderBox.bottom().value())
126                     style->setBorderBottomWidth(borderBox.bottom().value());
127                 else
128                     style->resetBorderBottom();
129             }
130             if (borderBox.left().value() != style->borderLeftWidth()) {
131                 style->setBorderLeftWidth(borderBox.left().value());
132                 if (borderBox.left().value())
133                     style->setBorderLeftWidth(borderBox.left().value());
134                 else
135                     style->resetBorderLeft();
136             }
137
138             // Padding
139             LengthBox paddingBox = m_theme->controlPadding(part, style->font(), style->paddingBox(), style->effectiveZoom());
140             if (paddingBox != style->paddingBox())
141                 style->setPaddingBox(paddingBox);
142
143             // Whitespace
144             if (m_theme->controlRequiresPreWhiteSpace(part))
145                 style->setWhiteSpace(PRE);
146             
147             // Width / Height
148             // The width and height here are affected by the zoom.
149             // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
150             LengthSize controlSize = m_theme->controlSize(part, style->font(), LengthSize(style->width(), style->height()), style->effectiveZoom());
151             if (controlSize.width() != style->width())
152                 style->setWidth(controlSize.width());
153             if (controlSize.height() != style->height())
154                 style->setHeight(controlSize.height());
155                 
156             // Min-Width / Min-Height
157             LengthSize minControlSize = m_theme->minimumControlSize(part, style->font(), style->effectiveZoom());
158             if (minControlSize.width() != style->minWidth())
159                 style->setMinWidth(minControlSize.width());
160             if (minControlSize.height() != style->minHeight())
161                 style->setMinHeight(minControlSize.height());
162                 
163             // Font
164             FontDescription controlFont = m_theme->controlFont(part, style->font(), style->effectiveZoom());
165             if (controlFont != style->font().fontDescription()) {
166                 // Reset our line-height
167                 style->setLineHeight(RenderStyle::initialLineHeight());
168                 
169                 // Now update our font.
170                 if (style->setFontDescription(controlFont))
171                     style->font().update(0);
172             }
173         }
174         default:
175             break;
176     }
177 #endif
178
179     // Call the appropriate style adjustment method based off the appearance value.
180     switch (style->appearance()) {
181 #if !USE(NEW_THEME)
182         case CheckboxPart:
183             return adjustCheckboxStyle(selector, style, e);
184         case RadioPart:
185             return adjustRadioStyle(selector, style, e);
186         case PushButtonPart:
187         case SquareButtonPart:
188         case ListButtonPart:
189         case DefaultButtonPart:
190         case ButtonPart:
191             return adjustButtonStyle(selector, style, e);
192         case InnerSpinButtonPart:
193             return adjustInnerSpinButtonStyle(selector, style, e);
194         case OuterSpinButtonPart:
195             return adjustOuterSpinButtonStyle(selector, style, e);
196 #endif
197         case TextFieldPart:
198             return adjustTextFieldStyle(selector, style, e);
199         case TextAreaPart:
200             return adjustTextAreaStyle(selector, style, e);
201         case MenulistPart:
202             return adjustMenuListStyle(selector, style, e);
203         case MenulistButtonPart:
204             return adjustMenuListButtonStyle(selector, style, e);
205         case MediaSliderPart:
206         case MediaVolumeSliderPart:
207         case SliderHorizontalPart:
208         case SliderVerticalPart:
209             return adjustSliderTrackStyle(selector, style, e);
210         case SliderThumbHorizontalPart:
211         case SliderThumbVerticalPart:
212             return adjustSliderThumbStyle(selector, style, e);
213         case SearchFieldPart:
214             return adjustSearchFieldStyle(selector, style, e);
215         case SearchFieldCancelButtonPart:
216             return adjustSearchFieldCancelButtonStyle(selector, style, e);
217         case SearchFieldDecorationPart:
218             return adjustSearchFieldDecorationStyle(selector, style, e);
219         case SearchFieldResultsDecorationPart:
220             return adjustSearchFieldResultsDecorationStyle(selector, style, e);
221         case SearchFieldResultsButtonPart:
222             return adjustSearchFieldResultsButtonStyle(selector, style, e);
223 #if ENABLE(PROGRESS_TAG)
224         case ProgressBarPart:
225             return adjustProgressBarStyle(selector, style, e);
226 #endif
227 #if ENABLE(METER_TAG)
228         case MeterPart:
229         case RelevancyLevelIndicatorPart:
230         case ContinuousCapacityLevelIndicatorPart:
231         case DiscreteCapacityLevelIndicatorPart:
232         case RatingLevelIndicatorPart:
233             return adjustMeterStyle(selector, style, e);
234 #endif
235 #if ENABLE(INPUT_SPEECH)
236         case InputSpeechButtonPart:
237             return adjustInputFieldSpeechButtonStyle(selector, style, e);
238 #endif
239         default:
240             break;
241     }
242 }
243
244 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
245 {
246     // If painting is disabled, but we aren't updating control tints, then just bail.
247     // If we are updating control tints, just schedule a repaint if the theme supports tinting
248     // for that control.
249     if (paintInfo.context->updatingControlTints()) {
250         if (controlSupportsTints(o))
251             o->repaint();
252         return false;
253     }
254     if (paintInfo.context->paintingDisabled())
255         return false;
256
257     ControlPart part = o->style()->appearance();
258
259 #if USE(NEW_THEME)
260     switch (part) {
261         case CheckboxPart:
262         case RadioPart:
263         case PushButtonPart:
264         case SquareButtonPart:
265         case ListButtonPart:
266         case DefaultButtonPart:
267         case ButtonPart:
268         case InnerSpinButtonPart:
269         case OuterSpinButtonPart:
270             m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView());
271             return false;
272         default:
273             break;
274     }
275 #endif
276
277     // Call the appropriate paint method based off the appearance value.
278     switch (part) {
279 #if !USE(NEW_THEME)
280         case CheckboxPart:
281             return paintCheckbox(o, paintInfo, r);
282         case RadioPart:
283             return paintRadio(o, paintInfo, r);
284         case PushButtonPart:
285         case SquareButtonPart:
286         case ListButtonPart:
287         case DefaultButtonPart:
288         case ButtonPart:
289             return paintButton(o, paintInfo, r);
290         case InnerSpinButtonPart:
291             return paintInnerSpinButton(o, paintInfo, r);
292         case OuterSpinButtonPart:
293             return paintOuterSpinButton(o, paintInfo, r);
294 #endif
295         case MenulistPart:
296             return paintMenuList(o, paintInfo, r);
297 #if ENABLE(METER_TAG)
298         case MeterPart:
299         case RelevancyLevelIndicatorPart:
300         case ContinuousCapacityLevelIndicatorPart:
301         case DiscreteCapacityLevelIndicatorPart:
302         case RatingLevelIndicatorPart:
303             return paintMeter(o, paintInfo, r);
304 #endif
305 #if ENABLE(PROGRESS_TAG)
306         case ProgressBarPart:
307             return paintProgressBar(o, paintInfo, r);
308 #endif
309         case SliderHorizontalPart:
310         case SliderVerticalPart:
311             return paintSliderTrack(o, paintInfo, r);
312         case SliderThumbHorizontalPart:
313         case SliderThumbVerticalPart:
314             if (o->parent()->isSlider())
315                 return paintSliderThumb(o, paintInfo, r);
316             // We don't support drawing a slider thumb without a parent slider
317             break;
318         case MediaFullscreenButtonPart:
319             return paintMediaFullscreenButton(o, paintInfo, r);
320         case MediaPlayButtonPart:
321             return paintMediaPlayButton(o, paintInfo, r);
322         case MediaMuteButtonPart:
323             return paintMediaMuteButton(o, paintInfo, r);
324         case MediaSeekBackButtonPart:
325             return paintMediaSeekBackButton(o, paintInfo, r);
326         case MediaSeekForwardButtonPart:
327             return paintMediaSeekForwardButton(o, paintInfo, r);
328         case MediaRewindButtonPart:
329             return paintMediaRewindButton(o, paintInfo, r);
330         case MediaReturnToRealtimeButtonPart:
331             return paintMediaReturnToRealtimeButton(o, paintInfo, r);
332         case MediaToggleClosedCaptionsButtonPart:
333             return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
334         case MediaSliderPart:
335             return paintMediaSliderTrack(o, paintInfo, r);
336         case MediaSliderThumbPart:
337             if (o->parent()->isSlider())
338                 return paintMediaSliderThumb(o, paintInfo, r);
339             break;
340         case MediaVolumeSliderContainerPart:
341             return paintMediaVolumeSliderContainer(o, paintInfo, r);
342         case MediaVolumeSliderPart:
343             return paintMediaVolumeSliderTrack(o, paintInfo, r);
344         case MediaVolumeSliderThumbPart:
345             if (o->parent()->isSlider())
346                 return paintMediaVolumeSliderThumb(o, paintInfo, r);
347             break;
348         case MediaTimeRemainingPart:
349             return paintMediaTimeRemaining(o, paintInfo, r);
350         case MediaCurrentTimePart:
351             return paintMediaCurrentTime(o, paintInfo, r);
352         case MediaControlsBackgroundPart:
353             return paintMediaControlsBackground(o, paintInfo, r);
354         case MenulistButtonPart:
355         case TextFieldPart:
356         case TextAreaPart:
357         case ListboxPart:
358             return true;
359         case SearchFieldPart:
360             return paintSearchField(o, paintInfo, r);
361         case SearchFieldCancelButtonPart:
362             return paintSearchFieldCancelButton(o, paintInfo, r);
363         case SearchFieldDecorationPart:
364             return paintSearchFieldDecoration(o, paintInfo, r);
365         case SearchFieldResultsDecorationPart:
366             return paintSearchFieldResultsDecoration(o, paintInfo, r);
367         case SearchFieldResultsButtonPart:
368             return paintSearchFieldResultsButton(o, paintInfo, r);
369 #if ENABLE(INPUT_SPEECH)
370         case InputSpeechButtonPart:
371             return paintInputFieldSpeechButton(o, paintInfo, r);
372 #endif
373         default:
374             break;
375     }
376
377     return true; // We don't support the appearance, so let the normal background/border paint.
378 }
379
380 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
381 {
382     if (paintInfo.context->paintingDisabled())
383         return false;
384
385     // Call the appropriate paint method based off the appearance value.
386     switch (o->style()->appearance()) {
387         case TextFieldPart:
388             return paintTextField(o, paintInfo, r);
389         case ListboxPart:
390         case TextAreaPart:
391             return paintTextArea(o, paintInfo, r);
392         case MenulistButtonPart:
393         case SearchFieldPart:
394             return true;
395         case CheckboxPart:
396         case RadioPart:
397         case PushButtonPart:
398         case SquareButtonPart:
399         case ListButtonPart:
400         case DefaultButtonPart:
401         case ButtonPart:
402         case MenulistPart:
403 #if ENABLE(METER_TAG)
404         case MeterPart:
405         case RelevancyLevelIndicatorPart:
406         case ContinuousCapacityLevelIndicatorPart:
407         case DiscreteCapacityLevelIndicatorPart:
408         case RatingLevelIndicatorPart:
409 #endif
410 #if ENABLE(PROGRESS_TAG)
411         case ProgressBarPart:
412 #endif
413         case SliderHorizontalPart:
414         case SliderVerticalPart:
415         case SliderThumbHorizontalPart:
416         case SliderThumbVerticalPart:
417         case SearchFieldCancelButtonPart:
418         case SearchFieldDecorationPart:
419         case SearchFieldResultsDecorationPart:
420         case SearchFieldResultsButtonPart:
421 #if ENABLE(INPUT_SPEECH)
422         case InputSpeechButtonPart:
423 #endif
424         default:
425             break;
426     }
427
428     return false;
429 }
430
431 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
432 {
433     if (paintInfo.context->paintingDisabled())
434         return false;
435
436     // Call the appropriate paint method based off the appearance value.
437     switch (o->style()->appearance()) {
438         case MenulistButtonPart:
439             return paintMenuListButton(o, paintInfo, r);
440         case TextFieldPart:
441         case TextAreaPart:
442         case ListboxPart:
443         case CheckboxPart:
444         case RadioPart:
445         case PushButtonPart:
446         case SquareButtonPart:
447         case ListButtonPart:
448         case DefaultButtonPart:
449         case ButtonPart:
450         case MenulistPart:
451 #if ENABLE(METER_TAG)
452         case MeterPart:
453         case RelevancyLevelIndicatorPart:
454         case ContinuousCapacityLevelIndicatorPart:
455         case DiscreteCapacityLevelIndicatorPart:
456         case RatingLevelIndicatorPart:
457 #endif
458 #if ENABLE(PROGRESS_TAG)
459         case ProgressBarPart:
460 #endif
461         case SliderHorizontalPart:
462         case SliderVerticalPart:
463         case SliderThumbHorizontalPart:
464         case SliderThumbVerticalPart:
465         case SearchFieldPart:
466         case SearchFieldCancelButtonPart:
467         case SearchFieldDecorationPart:
468         case SearchFieldResultsDecorationPart:
469         case SearchFieldResultsButtonPart:
470 #if ENABLE(INPUT_SPEECH)
471         case InputSpeechButtonPart:
472 #endif
473         default:
474             break;
475     }
476
477     return false;
478 }
479
480 #if ENABLE(VIDEO)
481 bool RenderTheme::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPoint)
482 {
483     if (!o->isBox())
484         return false;
485
486     FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true);  // respect transforms
487     return toRenderBox(o)->borderBoxRect().contains(roundedIntPoint(localPoint));
488 }
489
490 bool RenderTheme::shouldRenderMediaControlPart(ControlPart part, Element* e)
491 {
492     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(e);
493     switch (part) {
494     case MediaMuteButtonPart:
495         return mediaElement->hasAudio();
496     case MediaRewindButtonPart:
497         return mediaElement->movieLoadType() != MediaPlayer::LiveStream;
498     case MediaReturnToRealtimeButtonPart:
499         return mediaElement->movieLoadType() == MediaPlayer::LiveStream;
500     case MediaFullscreenButtonPart:
501         return mediaElement->supportsFullscreen();
502     case MediaToggleClosedCaptionsButtonPart:
503         return mediaElement->hasClosedCaptions();
504     default:
505         return true;
506     }
507 }
508
509 String RenderTheme::formatMediaControlsTime(float time) const
510 {
511     if (!isfinite(time))
512         time = 0;
513     int seconds = (int)fabsf(time);
514     int hours = seconds / (60 * 60);
515     int minutes = (seconds / 60) % 60;
516     seconds %= 60;
517     if (hours) {
518         if (hours > 9)
519             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
520
521         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
522     }
523
524     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
525 }
526
527 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
528 {
529     return formatMediaControlsTime(currentTime);
530 }
531
532 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
533 {
534     return formatMediaControlsTime(currentTime - duration);
535 }
536
537 #endif
538
539 Color RenderTheme::activeSelectionBackgroundColor() const
540 {
541     if (!m_activeSelectionBackgroundColor.isValid())
542         m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
543     return m_activeSelectionBackgroundColor;
544 }
545
546 Color RenderTheme::inactiveSelectionBackgroundColor() const
547 {
548     if (!m_inactiveSelectionBackgroundColor.isValid())
549         m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
550     return m_inactiveSelectionBackgroundColor;
551 }
552
553 Color RenderTheme::activeSelectionForegroundColor() const
554 {
555     if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
556         m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
557     return m_activeSelectionForegroundColor;
558 }
559
560 Color RenderTheme::inactiveSelectionForegroundColor() const
561 {
562     if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
563         m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
564     return m_inactiveSelectionForegroundColor;
565 }
566
567 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
568 {
569     if (!m_activeListBoxSelectionBackgroundColor.isValid())
570         m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
571     return m_activeListBoxSelectionBackgroundColor;
572 }
573
574 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
575 {
576     if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
577         m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
578     return m_inactiveListBoxSelectionBackgroundColor;
579 }
580
581 Color RenderTheme::activeListBoxSelectionForegroundColor() const
582 {
583     if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
584         m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
585     return m_activeListBoxSelectionForegroundColor;
586 }
587
588 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
589 {
590     if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
591         m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
592     return m_inactiveListBoxSelectionForegroundColor;
593 }
594
595 Color RenderTheme::platformActiveSelectionBackgroundColor() const
596 {
597     // Use a blue color by default if the platform theme doesn't define anything.
598     return Color(0, 0, 255);
599 }
600
601 Color RenderTheme::platformActiveSelectionForegroundColor() const
602 {
603     // Use a white color by default if the platform theme doesn't define anything.
604     return Color::white;
605 }
606
607 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
608 {
609     // Use a grey color by default if the platform theme doesn't define anything.
610     // This color matches Firefox's inactive color.
611     return Color(176, 176, 176);
612 }
613
614 Color RenderTheme::platformInactiveSelectionForegroundColor() const
615 {
616     // Use a black color by default.
617     return Color::black;
618 }
619
620 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
621 {
622     return platformActiveSelectionBackgroundColor();
623 }
624
625 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
626 {
627     return platformActiveSelectionForegroundColor();
628 }
629
630 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
631 {
632     return platformInactiveSelectionBackgroundColor();
633 }
634
635 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
636 {
637     return platformInactiveSelectionForegroundColor();
638 }
639
640 int RenderTheme::baselinePosition(const RenderObject* o) const
641 {
642     if (!o->isBox())
643         return 0;
644
645     const RenderBox* box = toRenderBox(o);
646
647 #if USE(NEW_THEME)
648     return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
649 #else
650     return box->height() + box->marginTop();
651 #endif
652 }
653
654 bool RenderTheme::isControlContainer(ControlPart appearance) const
655 {
656     // There are more leaves than this, but we'll patch this function as we add support for
657     // more controls.
658     return appearance != CheckboxPart && appearance != RadioPart;
659 }
660
661 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background,
662                                   const Color& backgroundColor) const
663 {
664     switch (style->appearance()) {
665         case PushButtonPart:
666         case SquareButtonPart:
667         case DefaultButtonPart:
668         case ButtonPart:
669         case ListboxPart:
670         case MenulistPart:
671         case ProgressBarPart:
672         case MeterPart:
673         case RelevancyLevelIndicatorPart:
674         case ContinuousCapacityLevelIndicatorPart:
675         case DiscreteCapacityLevelIndicatorPart:
676         case RatingLevelIndicatorPart:
677         // FIXME: Uncomment this when making search fields style-able.
678         // case SearchFieldPart:
679         case TextFieldPart:
680         case TextAreaPart:
681             // Test the style to see if the UA border and background match.
682             return (style->border() != border ||
683                     *style->backgroundLayers() != background ||
684                     style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
685         default:
686             return false;
687     }
688 }
689
690 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
691 {
692 #if USE(NEW_THEME)
693     m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
694 #endif
695 }
696
697 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
698 {
699     return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
700 }
701
702 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
703 {
704     // Default implementation assumes the controls don't respond to changes in :hover state
705     if (state == HoverState && !supportsHover(o->style()))
706         return false;
707
708     // Assume pressed state is only responded to if the control is enabled.
709     if (state == PressedState && !isEnabled(o))
710         return false;
711
712     // Repaint the control.
713     o->repaint();
714     return true;
715 }
716
717 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
718 {
719     ControlStates result = 0;
720     if (isHovered(o)) {
721         result |= HoverState;
722         if (isSpinUpButtonPartHovered(o))
723             result |= SpinUpState;
724     }
725     if (isPressed(o)) {
726         result |= PressedState;
727         if (isSpinUpButtonPartPressed(o))
728             result |= SpinUpState;
729     }
730     if (isFocused(o) && o->style()->outlineStyleIsAuto())
731         result |= FocusState;
732     if (isEnabled(o))
733         result |= EnabledState;
734     if (isChecked(o))
735         result |= CheckedState;
736     if (isReadOnlyControl(o))
737         result |= ReadOnlyState;
738     if (isDefault(o))
739         result |= DefaultState;
740     if (!isActive(o))
741         result |= WindowInactiveState;
742     if (isIndeterminate(o))
743         result |= IndeterminateState;
744     return result;
745 }
746
747 bool RenderTheme::isActive(const RenderObject* o) const
748 {
749     Node* node = o->node();
750     if (!node)
751         return false;
752
753     Frame* frame = node->document()->frame();
754     if (!frame)
755         return false;
756
757     Page* page = frame->page();
758     if (!page)
759         return false;
760
761     return page->focusController()->isActive();
762 }
763
764 bool RenderTheme::isChecked(const RenderObject* o) const
765 {
766     if (!o->node() || !o->node()->isElementNode())
767         return false;
768
769     InputElement* inputElement = toInputElement(static_cast<Element*>(o->node()));
770     if (!inputElement)
771         return false;
772
773     return inputElement->isChecked();
774 }
775
776 bool RenderTheme::isIndeterminate(const RenderObject* o) const
777 {
778     if (!o->node() || !o->node()->isElementNode())
779         return false;
780
781     InputElement* inputElement = toInputElement(static_cast<Element*>(o->node()));
782     if (!inputElement)
783         return false;
784
785     return inputElement->isIndeterminate();
786 }
787
788 bool RenderTheme::isEnabled(const RenderObject* o) const
789 {
790     Node* node = o->node();
791     if (!node || !node->isElementNode())
792         return true;
793     return static_cast<Element*>(node)->isEnabledFormControl();
794 }
795
796 bool RenderTheme::isFocused(const RenderObject* o) const
797 {
798     Node* node = o->node();
799     if (!node)
800         return false;
801     Document* document = node->document();
802     Frame* frame = document->frame();
803     return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive();
804 }
805
806 bool RenderTheme::isPressed(const RenderObject* o) const
807 {
808     if (!o->node())
809         return false;
810     return o->node()->active();
811 }
812
813 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
814 {
815     Node* node = o->node();
816     if (!node || !node->active() || !node->isElementNode()
817         || !static_cast<Element*>(node)->isSpinButtonElement())
818         return false;
819     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
820     return element->onUpButton();
821 }
822
823 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
824 {
825     Node* node = o->node();
826     if (!node || !node->isElementNode())
827         return false;
828     return static_cast<Element*>(node)->isReadOnlyFormControl();
829 }
830
831 bool RenderTheme::isHovered(const RenderObject* o) const
832 {
833     if (!o->node())
834         return false;
835     return o->node()->hovered();
836 }
837
838 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
839 {
840     Node* node = o->node();
841     if (!node || !node->active() || !node->isElementNode()
842         || !static_cast<Element*>(node)->isSpinButtonElement())
843         return false;
844     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
845     return element->onUpButton();
846 }
847
848 bool RenderTheme::isDefault(const RenderObject* o) const
849 {
850     // A button should only have the default appearance if the page is active
851     if (!isActive(o))
852         return false;
853
854     if (!o->document())
855         return false;
856
857     Settings* settings = o->document()->settings();
858     if (!settings || !settings->inApplicationChromeMode())
859         return false;
860     
861     return o->style()->appearance() == DefaultButtonPart;
862 }
863
864 #if !USE(NEW_THEME)
865
866 void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
867 {
868     // A summary of the rules for checkbox designed to match WinIE:
869     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
870     // font-size - not honored (control has no text), but we use it to decide which control size to use.
871     setCheckboxSize(style);
872
873     // padding - not honored by WinIE, needs to be removed.
874     style->resetPadding();
875
876     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
877     // for now, we will not honor it.
878     style->resetBorder();
879
880     style->setBoxShadow(0);
881 }
882
883 void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
884 {
885     // A summary of the rules for checkbox designed to match WinIE:
886     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
887     // font-size - not honored (control has no text), but we use it to decide which control size to use.
888     setRadioSize(style);
889
890     // padding - not honored by WinIE, needs to be removed.
891     style->resetPadding();
892
893     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
894     // for now, we will not honor it.
895     style->resetBorder();
896
897     style->setBoxShadow(0);
898 }
899
900 void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
901 {
902     // Most platforms will completely honor all CSS, and so we have no need to adjust the style
903     // at all by default.  We will still allow the theme a crack at setting up a desired vertical size.
904     setButtonSize(style);
905 }
906
907 void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
908 {
909 }
910
911 void RenderTheme::adjustOuterSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
912 {
913 }
914
915 #endif
916
917 void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
918 {
919 }
920
921 void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
922 {
923 }
924
925 void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
926 {
927 }
928
929 #if ENABLE(INPUT_SPEECH)
930 void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
931 {
932     RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element);
933 }
934
935 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
936 {
937     return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
938 }
939 #endif
940
941 #if ENABLE(METER_TAG)
942 void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
943 {
944     style->setBoxShadow(0);
945 }
946
947 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
948 {
949     return bounds.size();
950 }
951
952 bool RenderTheme::supportsMeter(ControlPart, bool) const
953 {
954     return false;
955 }
956
957 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
958 {
959     return true;
960 }
961
962 #endif
963
964 #if ENABLE(PROGRESS_TAG)
965 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
966 {
967     return 0;
968 }
969
970 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
971 {
972     return 0;
973 }
974
975 void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
976 {
977 }
978 #endif
979
980 void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
981 {
982 }
983
984 void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
985 {
986 }
987
988 void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const
989 {
990 }
991
992 void RenderTheme::adjustSliderThumbSize(RenderObject*) const
993 {
994 }
995
996 void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
997 {
998 }
999
1000 void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1001 {
1002 }
1003
1004 void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1005 {
1006 }
1007
1008 void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1009 {
1010 }
1011
1012 void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1013 {
1014 }
1015
1016 void RenderTheme::platformColorsDidChange()
1017 {
1018     m_activeSelectionForegroundColor = Color();
1019     m_inactiveSelectionForegroundColor = Color();
1020     m_activeSelectionBackgroundColor = Color();
1021     m_inactiveSelectionBackgroundColor = Color();
1022
1023     m_activeListBoxSelectionForegroundColor = Color();
1024     m_inactiveListBoxSelectionForegroundColor = Color();
1025     m_activeListBoxSelectionBackgroundColor = Color();
1026     m_inactiveListBoxSelectionForegroundColor = Color();
1027 }
1028
1029 Color RenderTheme::systemColor(int cssValueId) const
1030 {
1031     switch (cssValueId) {
1032         case CSSValueActiveborder:
1033             return 0xFFFFFFFF;
1034         case CSSValueActivecaption:
1035             return 0xFFCCCCCC;
1036         case CSSValueAppworkspace:
1037             return 0xFFFFFFFF;
1038         case CSSValueBackground:
1039             return 0xFF6363CE;
1040         case CSSValueButtonface:
1041             return 0xFFC0C0C0;
1042         case CSSValueButtonhighlight:
1043             return 0xFFDDDDDD;
1044         case CSSValueButtonshadow:
1045             return 0xFF888888;
1046         case CSSValueButtontext:
1047             return 0xFF000000;
1048         case CSSValueCaptiontext:
1049             return 0xFF000000;
1050         case CSSValueGraytext:
1051             return 0xFF808080;
1052         case CSSValueHighlight:
1053             return 0xFFB5D5FF;
1054         case CSSValueHighlighttext:
1055             return 0xFF000000;
1056         case CSSValueInactiveborder:
1057             return 0xFFFFFFFF;
1058         case CSSValueInactivecaption:
1059             return 0xFFFFFFFF;
1060         case CSSValueInactivecaptiontext:
1061             return 0xFF7F7F7F;
1062         case CSSValueInfobackground:
1063             return 0xFFFBFCC5;
1064         case CSSValueInfotext:
1065             return 0xFF000000;
1066         case CSSValueMenu:
1067             return 0xFFC0C0C0;
1068         case CSSValueMenutext:
1069             return 0xFF000000;
1070         case CSSValueScrollbar:
1071             return 0xFFFFFFFF;
1072         case CSSValueText:
1073             return 0xFF000000;
1074         case CSSValueThreeddarkshadow:
1075             return 0xFF666666;
1076         case CSSValueThreedface:
1077             return 0xFFC0C0C0;
1078         case CSSValueThreedhighlight:
1079             return 0xFFDDDDDD;
1080         case CSSValueThreedlightshadow:
1081             return 0xFFC0C0C0;
1082         case CSSValueThreedshadow:
1083             return 0xFF888888;
1084         case CSSValueWindow:
1085             return 0xFFFFFFFF;
1086         case CSSValueWindowframe:
1087             return 0xFFCCCCCC;
1088         case CSSValueWindowtext:
1089             return 0xFF000000;
1090     }
1091     return Color();
1092 }
1093
1094 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1095 {
1096     return Color(255, 150, 50); // Orange.
1097 }
1098
1099 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1100 {
1101     return Color(255, 255, 0); // Yellow.
1102 }
1103
1104 void RenderTheme::setCustomFocusRingColor(const Color& c)
1105 {
1106     customFocusRingColor() = c;
1107 }
1108
1109 Color RenderTheme::focusRingColor()
1110 {
1111     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1112 }
1113
1114 } // namespace WebCore