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