Home | History | Annotate | Download | only in child
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "webkit/child/webthemeengine_impl_win.h"
      6 
      7 #include <vsstyle.h>  // To convert to ui::NativeTheme::State
      8 
      9 #include "base/logging.h"
     10 #include "skia/ext/platform_canvas.h"
     11 #include "skia/ext/skia_utils_win.h"
     12 #include "third_party/WebKit/public/platform/WebRect.h"
     13 #include "ui/gfx/win/dpi.h"
     14 #include "ui/native_theme/native_theme.h"
     15 
     16 using blink::WebCanvas;
     17 using blink::WebColor;
     18 using blink::WebRect;
     19 using blink::WebSize;
     20 
     21 namespace webkit_glue {
     22 
     23 static RECT WebRectToRECT(const WebRect& rect) {
     24   RECT result;
     25   result.left = rect.x;
     26   result.top = rect.y;
     27   result.right = rect.x + rect.width;
     28   result.bottom = rect.y + rect.height;
     29   return result;
     30 }
     31 
     32 static ui::NativeTheme::State WebButtonStateToGfx(
     33     int part, int state, ui::NativeTheme::ButtonExtraParams* extra) {
     34   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
     35   // Native buttons have a different focus style.
     36   extra->is_focused = false;
     37   extra->has_border = false;
     38   extra->background_color = ui::NativeTheme::instance()->GetSystemColor(
     39       ui::NativeTheme::kColorId_ButtonBackgroundColor);
     40 
     41   if (part == BP_PUSHBUTTON) {
     42     switch (state) {
     43       case PBS_NORMAL:
     44         gfx_state = ui::NativeTheme::kNormal;
     45         extra->checked = false;
     46         extra->indeterminate = false;
     47         extra->is_default = false;
     48         break;
     49       case PBS_HOT:
     50         gfx_state = ui::NativeTheme::kHovered;
     51         extra->checked = false;
     52         extra->indeterminate = false;
     53         extra->is_default = false;
     54         break;
     55       case PBS_PRESSED:
     56         gfx_state = ui::NativeTheme::kPressed;
     57         extra->checked = false;
     58         extra->indeterminate = false;
     59         extra->is_default = false;
     60         break;
     61       case PBS_DISABLED:
     62         gfx_state = ui::NativeTheme::kDisabled;
     63         extra->checked = false;
     64         extra->indeterminate = false;
     65         extra->is_default = false;
     66         break;
     67       case PBS_DEFAULTED:
     68         gfx_state = ui::NativeTheme::kNormal;
     69         extra->checked = false;
     70         extra->indeterminate = false;
     71         extra->is_default = true;
     72         break;
     73       case PBS_DEFAULTED_ANIMATING:
     74         gfx_state = ui::NativeTheme::kNormal;
     75         extra->checked = false;
     76         extra->indeterminate = false;
     77         extra->is_default = true;
     78         break;
     79       default:
     80         NOTREACHED() << "Invalid state: " << state;
     81     }
     82   } else if (part == BP_RADIOBUTTON) {
     83     switch (state) {
     84       case RBS_UNCHECKEDNORMAL:
     85         gfx_state = ui::NativeTheme::kNormal;
     86         extra->checked = false;
     87         extra->indeterminate = false;
     88         extra->is_default = false;
     89         break;
     90       case RBS_UNCHECKEDHOT:
     91         gfx_state = ui::NativeTheme::kHovered;
     92         extra->checked = false;
     93         extra->indeterminate = false;
     94         extra->is_default = false;
     95         break;
     96       case RBS_UNCHECKEDPRESSED:
     97         gfx_state = ui::NativeTheme::kPressed;
     98         extra->checked = false;
     99         extra->indeterminate = false;
    100         extra->is_default = false;
    101         break;
    102       case RBS_UNCHECKEDDISABLED:
    103         gfx_state = ui::NativeTheme::kDisabled;
    104         extra->checked = false;
    105         extra->indeterminate = false;
    106         extra->is_default = false;
    107         break;
    108       case RBS_CHECKEDNORMAL:
    109         gfx_state = ui::NativeTheme::kNormal;
    110         extra->checked = true;
    111         extra->indeterminate = false;
    112         extra->is_default = false;
    113         break;
    114       case RBS_CHECKEDHOT:
    115         gfx_state = ui::NativeTheme::kHovered;
    116         extra->checked = true;
    117         extra->indeterminate = false;
    118         extra->is_default = false;
    119         break;
    120       case RBS_CHECKEDPRESSED:
    121         gfx_state = ui::NativeTheme::kPressed;
    122         extra->checked = true;
    123         extra->indeterminate = false;
    124         extra->is_default = false;
    125         break;
    126       case RBS_CHECKEDDISABLED:
    127         gfx_state = ui::NativeTheme::kDisabled;
    128         extra->checked = true;
    129         extra->indeterminate = false;
    130         extra->is_default = false;
    131         break;
    132       default:
    133         NOTREACHED() << "Invalid state: " << state;
    134         break;
    135     }
    136   } else if (part == BP_CHECKBOX) {
    137     switch (state) {
    138       case CBS_UNCHECKEDNORMAL:
    139         gfx_state = ui::NativeTheme::kNormal;
    140         extra->checked = false;
    141         extra->indeterminate = false;
    142         extra->is_default = false;
    143         break;
    144       case CBS_UNCHECKEDHOT:
    145         gfx_state = ui::NativeTheme::kHovered;
    146         extra->checked = false;
    147         extra->indeterminate = false;
    148         extra->is_default = false;
    149         break;
    150       case CBS_UNCHECKEDPRESSED:
    151         gfx_state = ui::NativeTheme::kPressed;
    152         extra->checked = false;
    153         extra->indeterminate = false;
    154         extra->is_default = false;
    155         break;
    156       case CBS_UNCHECKEDDISABLED:
    157         gfx_state = ui::NativeTheme::kDisabled;
    158         extra->checked = false;
    159         extra->indeterminate = false;
    160         extra->is_default = false;
    161         break;
    162       case CBS_CHECKEDNORMAL:
    163         gfx_state = ui::NativeTheme::kNormal;
    164         extra->checked = true;
    165         extra->indeterminate = false;
    166         extra->is_default = false;
    167         break;
    168       case CBS_CHECKEDHOT:
    169         gfx_state = ui::NativeTheme::kHovered;
    170         extra->checked = true;
    171         extra->indeterminate = false;
    172         extra->is_default = false;
    173         break;
    174       case CBS_CHECKEDPRESSED:
    175         gfx_state = ui::NativeTheme::kPressed;
    176         extra->checked = true;
    177         extra->indeterminate = false;
    178         extra->is_default = false;
    179         break;
    180       case CBS_CHECKEDDISABLED:
    181         gfx_state = ui::NativeTheme::kDisabled;
    182         extra->checked = true;
    183         extra->indeterminate = false;
    184         extra->is_default = false;
    185         break;
    186       case CBS_MIXEDNORMAL:
    187         gfx_state = ui::NativeTheme::kNormal;
    188         extra->checked = false;
    189         extra->indeterminate = true;
    190         extra->is_default = false;
    191         break;
    192       case CBS_MIXEDHOT:
    193         gfx_state = ui::NativeTheme::kHovered;
    194         extra->checked = false;
    195         extra->indeterminate = true;
    196         extra->is_default = false;
    197         break;
    198       case CBS_MIXEDPRESSED:
    199         gfx_state = ui::NativeTheme::kPressed;
    200         extra->checked = false;
    201         extra->indeterminate = true;
    202         extra->is_default = false;
    203         break;
    204       case CBS_MIXEDDISABLED:
    205         gfx_state = ui::NativeTheme::kDisabled;
    206         extra->checked = false;
    207         extra->indeterminate = true;
    208         extra->is_default = false;
    209         break;
    210       case CBS_IMPLICITNORMAL:
    211         gfx_state = ui::NativeTheme::kNormal;
    212         extra->checked = false;
    213         extra->indeterminate = false;
    214         extra->is_default = false;
    215         break;
    216       case CBS_IMPLICITHOT:
    217         gfx_state = ui::NativeTheme::kHovered;
    218         extra->checked = false;
    219         extra->indeterminate = false;
    220         extra->is_default = false;
    221         break;
    222       case CBS_IMPLICITPRESSED:
    223         gfx_state = ui::NativeTheme::kPressed;
    224         extra->checked = false;
    225         extra->indeterminate = false;
    226         extra->is_default = false;
    227         break;
    228       case CBS_IMPLICITDISABLED:
    229         gfx_state = ui::NativeTheme::kDisabled;
    230         extra->checked = false;
    231         extra->indeterminate = false;
    232         extra->is_default = false;
    233         break;
    234       case CBS_EXCLUDEDNORMAL:
    235         gfx_state = ui::NativeTheme::kNormal;
    236         extra->checked = false;
    237         extra->indeterminate = false;
    238         extra->is_default = false;
    239         break;
    240       case CBS_EXCLUDEDHOT:
    241         gfx_state = ui::NativeTheme::kHovered;
    242         extra->checked = false;
    243         extra->indeterminate = false;
    244         extra->is_default = false;
    245         break;
    246       case CBS_EXCLUDEDPRESSED:
    247         gfx_state = ui::NativeTheme::kPressed;
    248         extra->checked = false;
    249         extra->indeterminate = false;
    250         extra->is_default = false;
    251         break;
    252       case CBS_EXCLUDEDDISABLED:
    253         gfx_state = ui::NativeTheme::kDisabled;
    254         extra->checked = false;
    255         extra->indeterminate = false;
    256         extra->is_default = false;
    257         break;
    258       default:
    259         NOTREACHED() << "Invalid state: " << state;
    260         break;
    261     }
    262   } else if (part == BP_GROUPBOX) {
    263     switch (state) {
    264       case GBS_NORMAL:
    265         gfx_state = ui::NativeTheme::kNormal;
    266         extra->checked = false;
    267         extra->indeterminate = false;
    268         extra->is_default = false;
    269         break;
    270       case GBS_DISABLED:
    271         gfx_state = ui::NativeTheme::kDisabled;
    272         extra->checked = false;
    273         extra->indeterminate = false;
    274         extra->is_default = false;
    275         break;
    276       default:
    277         NOTREACHED() << "Invalid state: " << state;
    278         break;
    279     }
    280   } else if (part == BP_COMMANDLINK) {
    281     switch (state) {
    282       case CMDLS_NORMAL:
    283         gfx_state = ui::NativeTheme::kNormal;
    284         extra->checked = false;
    285         extra->indeterminate = false;
    286         extra->is_default = false;
    287         break;
    288       case CMDLS_HOT:
    289         gfx_state = ui::NativeTheme::kHovered;
    290         extra->checked = false;
    291         extra->indeterminate = false;
    292         extra->is_default = false;
    293         break;
    294       case CMDLS_PRESSED:
    295         gfx_state = ui::NativeTheme::kPressed;
    296         extra->checked = false;
    297         extra->indeterminate = false;
    298         extra->is_default = false;
    299         break;
    300       case CMDLS_DISABLED:
    301         gfx_state = ui::NativeTheme::kDisabled;
    302         extra->checked = false;
    303         extra->indeterminate = false;
    304         extra->is_default = false;
    305         break;
    306       case CMDLS_DEFAULTED:
    307         gfx_state = ui::NativeTheme::kNormal;
    308         extra->checked = false;
    309         extra->indeterminate = false;
    310         extra->is_default = true;
    311         break;
    312       case CMDLS_DEFAULTED_ANIMATING:
    313         gfx_state = ui::NativeTheme::kNormal;
    314         extra->checked = false;
    315         extra->indeterminate = false;
    316         extra->is_default = true;
    317         break;
    318       default:
    319         NOTREACHED() << "Invalid state: " << state;
    320         break;
    321     }
    322   } else if (part == BP_COMMANDLINKGLYPH) {
    323     switch (state) {
    324       case CMDLGS_NORMAL:
    325         gfx_state = ui::NativeTheme::kNormal;
    326         extra->checked = false;
    327         extra->indeterminate = false;
    328         extra->is_default = false;
    329         break;
    330       case CMDLGS_HOT:
    331         gfx_state = ui::NativeTheme::kHovered;
    332         extra->checked = false;
    333         extra->indeterminate = false;
    334         extra->is_default = false;
    335         break;
    336       case CMDLGS_PRESSED:
    337         gfx_state = ui::NativeTheme::kPressed;
    338         extra->checked = false;
    339         extra->indeterminate = false;
    340         extra->is_default = false;
    341         break;
    342       case CMDLGS_DISABLED:
    343         gfx_state = ui::NativeTheme::kDisabled;
    344         extra->checked = false;
    345         extra->indeterminate = false;
    346         extra->is_default = false;
    347         break;
    348       case CMDLGS_DEFAULTED:
    349         gfx_state = ui::NativeTheme::kNormal;
    350         extra->checked = false;
    351         extra->indeterminate = false;
    352         extra->is_default = true;
    353         break;
    354       default:
    355         NOTREACHED() << "Invalid state: " << state;
    356         break;
    357     }
    358   }
    359   return gfx_state;
    360 }
    361 
    362 void WebThemeEngineImpl::paintButton(
    363     WebCanvas* canvas, int part, int state, int classic_state,
    364     const WebRect& rect) {
    365   ui::NativeTheme::Part native_part = ui::NativeTheme::kPushButton;
    366   switch (part) {
    367     case BP_PUSHBUTTON:
    368       native_part = ui::NativeTheme::kPushButton;
    369       break;
    370     case BP_CHECKBOX:
    371       native_part = ui::NativeTheme::kCheckbox;
    372       break;
    373     case BP_RADIOBUTTON:
    374       native_part = ui::NativeTheme::kRadio;
    375       break;
    376     default:
    377       NOTREACHED() << "Invalid part: " << part;
    378       break;
    379   }
    380   ui::NativeTheme::ExtraParams extra;
    381   ui::NativeTheme::State native_state = WebButtonStateToGfx(part, state,
    382                                                              &extra.button);
    383   extra.button.classic_state = classic_state;
    384   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    385   ui::NativeTheme::instance()->Paint(canvas, native_part,
    386                                       native_state, gfx_rect, extra);
    387 }
    388 
    389 static ui::NativeTheme::State WebListMenuStateToGfx(int part, int state) {
    390   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    391 
    392   switch (part) {
    393     case CP_DROPDOWNBUTTON:
    394       switch (state) {
    395         case CBXS_NORMAL:
    396           gfx_state = ui::NativeTheme::kNormal;
    397           break;
    398         case CBXS_HOT:
    399           gfx_state = ui::NativeTheme::kHovered;
    400           break;
    401         case CBXS_PRESSED:
    402           gfx_state = ui::NativeTheme::kPressed;
    403           break;
    404         case CBXS_DISABLED:
    405           gfx_state = ui::NativeTheme::kDisabled;
    406           break;
    407         default:
    408           NOTREACHED() << "Invalid state: " << state;
    409           break;
    410       }
    411       break;
    412     default:
    413       NOTREACHED() << "Invalid part: " << part;
    414       break;
    415   }
    416   return gfx_state;
    417 }
    418 
    419 void WebThemeEngineImpl::paintMenuList(
    420     WebCanvas* canvas, int part, int state, int classic_state,
    421     const WebRect& rect) {
    422   ui::NativeTheme::Part native_part = ui::NativeTheme::kMenuList;
    423   switch (part) {
    424     case CP_DROPDOWNBUTTON:
    425       native_part = ui::NativeTheme::kMenuList;
    426       break;
    427     default:
    428       NOTREACHED() << "Invalid part: " << part;
    429       break;
    430   }
    431   ui::NativeTheme::State native_state = WebListMenuStateToGfx(part, state);
    432   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    433   ui::NativeTheme::ExtraParams extra;
    434   extra.menu_list.classic_state = classic_state;
    435   ui::NativeTheme::instance()->Paint(canvas, native_part,
    436                                       native_state, gfx_rect, extra);
    437 }
    438 
    439 static ui::NativeTheme::State WebScrollbarArrowStateToGfx(
    440     int state, ui::NativeTheme::Part* part,
    441     ui::NativeTheme::ScrollbarArrowExtraParams* extra) {
    442   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    443   switch (state) {
    444     case ABS_UPNORMAL:
    445       gfx_state = ui::NativeTheme::kNormal;
    446       *part = ui::NativeTheme::kScrollbarUpArrow;
    447       extra->is_hovering = false;
    448       break;
    449     case ABS_UPHOT:
    450       gfx_state = ui::NativeTheme::kHovered;
    451       *part = ui::NativeTheme::kScrollbarUpArrow;
    452       extra->is_hovering = false;
    453       break;
    454     case ABS_UPPRESSED:
    455       gfx_state = ui::NativeTheme::kPressed;
    456       *part = ui::NativeTheme::kScrollbarUpArrow;
    457       extra->is_hovering = false;
    458       break;
    459     case ABS_UPDISABLED:
    460       gfx_state = ui::NativeTheme::kDisabled;
    461       *part = ui::NativeTheme::kScrollbarUpArrow;
    462       extra->is_hovering = false;
    463       break;
    464     case ABS_DOWNNORMAL:
    465       gfx_state = ui::NativeTheme::kNormal;
    466       *part = ui::NativeTheme::kScrollbarDownArrow;
    467       extra->is_hovering = false;
    468       break;
    469     case ABS_DOWNHOT:
    470       gfx_state = ui::NativeTheme::kHovered;
    471       *part = ui::NativeTheme::kScrollbarDownArrow;
    472       extra->is_hovering = false;
    473       break;
    474     case ABS_DOWNPRESSED:
    475       gfx_state = ui::NativeTheme::kPressed;
    476       *part = ui::NativeTheme::kScrollbarDownArrow;
    477       extra->is_hovering = false;
    478       break;
    479     case ABS_DOWNDISABLED:
    480       gfx_state = ui::NativeTheme::kDisabled;
    481       *part = ui::NativeTheme::kScrollbarDownArrow;
    482       extra->is_hovering = false;
    483       break;
    484     case ABS_LEFTNORMAL:
    485       gfx_state = ui::NativeTheme::kNormal;
    486       *part = ui::NativeTheme::kScrollbarLeftArrow;
    487       extra->is_hovering = false;
    488       break;
    489     case ABS_LEFTHOT:
    490       gfx_state = ui::NativeTheme::kHovered;
    491       *part = ui::NativeTheme::kScrollbarLeftArrow;
    492       extra->is_hovering = false;
    493       break;
    494     case ABS_LEFTPRESSED:
    495       gfx_state = ui::NativeTheme::kPressed;
    496       *part = ui::NativeTheme::kScrollbarLeftArrow;
    497       extra->is_hovering = false;
    498       break;
    499     case ABS_LEFTDISABLED:
    500       gfx_state = ui::NativeTheme::kDisabled;
    501       *part = ui::NativeTheme::kScrollbarLeftArrow;
    502       extra->is_hovering = false;
    503       break;
    504     case ABS_RIGHTNORMAL:
    505       gfx_state = ui::NativeTheme::kNormal;
    506       *part = ui::NativeTheme::kScrollbarRightArrow;
    507       extra->is_hovering = false;
    508       break;
    509     case ABS_RIGHTHOT:
    510       gfx_state = ui::NativeTheme::kHovered;
    511       *part = ui::NativeTheme::kScrollbarRightArrow;
    512       extra->is_hovering = false;
    513       break;
    514     case ABS_RIGHTPRESSED:
    515       gfx_state = ui::NativeTheme::kPressed;
    516       *part = ui::NativeTheme::kScrollbarRightArrow;
    517       extra->is_hovering = false;
    518       break;
    519     case ABS_RIGHTDISABLED:
    520       gfx_state = ui::NativeTheme::kDisabled;
    521       *part = ui::NativeTheme::kScrollbarRightArrow;
    522       extra->is_hovering = false;
    523       break;
    524     case ABS_UPHOVER:
    525       gfx_state = ui::NativeTheme::kHovered;
    526       *part = ui::NativeTheme::kScrollbarUpArrow;
    527       extra->is_hovering = true;
    528       break;
    529     case ABS_DOWNHOVER:
    530       gfx_state = ui::NativeTheme::kHovered;
    531       *part = ui::NativeTheme::kScrollbarDownArrow;
    532       extra->is_hovering = true;
    533       break;
    534     case ABS_LEFTHOVER:
    535       gfx_state = ui::NativeTheme::kHovered;
    536       *part = ui::NativeTheme::kScrollbarLeftArrow;
    537       extra->is_hovering = true;
    538       break;
    539     case ABS_RIGHTHOVER:
    540       gfx_state = ui::NativeTheme::kHovered;
    541       *part = ui::NativeTheme::kScrollbarRightArrow;
    542       extra->is_hovering = true;
    543       break;
    544     default:
    545       NOTREACHED() << "Invalid state: " << state;
    546       break;
    547   }
    548   return gfx_state;
    549 }
    550 
    551 void WebThemeEngineImpl::paintScrollbarArrow(
    552     WebCanvas* canvas, int state, int classic_state, const WebRect& rect) {
    553   ui::NativeTheme::Part native_part;
    554   ui::NativeTheme::ExtraParams extra;
    555   ui::NativeTheme::State native_state = WebScrollbarArrowStateToGfx(
    556       state, &native_part, &extra.scrollbar_arrow);
    557   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    558   ui::NativeTheme::instance()->Paint(canvas, native_part,
    559                                       native_state, gfx_rect, extra);
    560 }
    561 
    562 static ui::NativeTheme::State WebScrollbarThumbStateToGfx(
    563     int state, ui::NativeTheme::ScrollbarThumbExtraParams* extra) {
    564   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    565   switch (state) {
    566     case SCRBS_NORMAL:
    567       gfx_state = ui::NativeTheme::kNormal;
    568       extra->is_hovering = false;
    569       break;
    570     case SCRBS_HOVER:
    571       gfx_state = ui::NativeTheme::kHovered;
    572       extra->is_hovering = true;
    573       break;
    574     case SCRBS_HOT:
    575       gfx_state = ui::NativeTheme::kHovered;
    576       extra->is_hovering = false;
    577       break;
    578     case SCRBS_PRESSED:
    579       gfx_state = ui::NativeTheme::kPressed;
    580       extra->is_hovering = false;
    581       break;
    582     case SCRBS_DISABLED:
    583       gfx_state = ui::NativeTheme::kDisabled;
    584       extra->is_hovering = false;
    585       break;
    586     default:
    587       NOTREACHED() << "Invalid state: " << state;
    588       break;
    589   }
    590   return gfx_state;
    591 }
    592 
    593 void WebThemeEngineImpl::paintScrollbarThumb(
    594     WebCanvas* canvas, int part, int state, int classic_state,
    595     const WebRect& rect) {
    596   ui::NativeTheme::Part native_part;
    597   if (part == SBP_THUMBBTNHORZ) {
    598     native_part = ui::NativeTheme::kScrollbarHorizontalThumb;
    599   } else if (part == SBP_THUMBBTNVERT) {
    600     native_part = ui::NativeTheme::kScrollbarVerticalThumb;
    601   } else if (part == SBP_GRIPPERHORZ) {
    602     native_part = ui::NativeTheme::kScrollbarHorizontalGripper;
    603   } else if (part == SBP_GRIPPERVERT) {
    604     native_part = ui::NativeTheme::kScrollbarVerticalGripper;
    605   } else {
    606       NOTREACHED() << "Invalid part: " << part;
    607   }
    608 
    609   ui::NativeTheme::ExtraParams extra;
    610   ui::NativeTheme::State native_state = WebScrollbarThumbStateToGfx(
    611       state, &extra.scrollbar_thumb);
    612 
    613   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    614   ui::NativeTheme::instance()->Paint(canvas, native_part,
    615                                       native_state, gfx_rect, extra);
    616 }
    617 
    618 static ui::NativeTheme::State WebScrollbarTrackStateToGfx(
    619     int part, int state, ui::NativeTheme::Part* gfx_part,
    620     ui::NativeTheme::ScrollbarTrackExtraParams* extra) {
    621   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    622   switch (part) {
    623     case SBP_LOWERTRACKHORZ:
    624       switch (state) {
    625         case SCRBS_NORMAL:
    626           gfx_state = ui::NativeTheme::kNormal;
    627           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    628           extra->is_upper = false;
    629           break;
    630         case SCRBS_HOVER:
    631         case SCRBS_HOT:
    632           gfx_state = ui::NativeTheme::kHovered;
    633           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    634           extra->is_upper = false;
    635           break;
    636         case SCRBS_PRESSED:
    637           gfx_state = ui::NativeTheme::kPressed;
    638           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    639           extra->is_upper = false;
    640           break;
    641         case SCRBS_DISABLED:
    642           gfx_state = ui::NativeTheme::kDisabled;
    643           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    644           extra->is_upper = false;
    645           break;
    646         default:
    647           NOTREACHED() << "Invalid state: " << state;
    648           break;
    649       }
    650       break;
    651     case SBP_UPPERTRACKHORZ:
    652       switch (state) {
    653         case SCRBS_NORMAL:
    654           gfx_state = ui::NativeTheme::kNormal;
    655           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    656           extra->is_upper = true;
    657           break;
    658         case SCRBS_HOVER:
    659         case SCRBS_HOT:
    660           gfx_state = ui::NativeTheme::kHovered;
    661           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    662           extra->is_upper = true;
    663           break;
    664         case SCRBS_PRESSED:
    665           gfx_state = ui::NativeTheme::kPressed;
    666           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    667           extra->is_upper = true;
    668           break;
    669         case SCRBS_DISABLED:
    670           gfx_state = ui::NativeTheme::kDisabled;
    671           *gfx_part = ui::NativeTheme::kScrollbarHorizontalTrack;
    672           extra->is_upper = true;
    673           break;
    674         default:
    675           NOTREACHED() << "Invalid state: " << state;
    676           break;
    677       }
    678       break;
    679     case SBP_LOWERTRACKVERT:
    680       switch (state) {
    681         case SCRBS_NORMAL:
    682           gfx_state = ui::NativeTheme::kNormal;
    683           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    684           extra->is_upper = false;
    685           break;
    686         case SCRBS_HOVER:
    687         case SCRBS_HOT:
    688           gfx_state = ui::NativeTheme::kHovered;
    689           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    690           extra->is_upper = false;
    691           break;
    692         case SCRBS_PRESSED:
    693           gfx_state = ui::NativeTheme::kPressed;
    694           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    695           extra->is_upper = false;
    696           break;
    697         case SCRBS_DISABLED:
    698           gfx_state = ui::NativeTheme::kDisabled;
    699           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    700           extra->is_upper = false;
    701           break;
    702         default:
    703           NOTREACHED() << "Invalid state: " << state;
    704           break;
    705       }
    706       break;
    707     case SBP_UPPERTRACKVERT:
    708       switch (state) {
    709         case SCRBS_NORMAL:
    710           gfx_state = ui::NativeTheme::kNormal;
    711           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    712           extra->is_upper = true;
    713           break;
    714         case SCRBS_HOVER:
    715         case SCRBS_HOT:
    716           gfx_state = ui::NativeTheme::kHovered;
    717           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    718           extra->is_upper = true;
    719           break;
    720         case SCRBS_PRESSED:
    721           gfx_state = ui::NativeTheme::kPressed;
    722           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    723           extra->is_upper = true;
    724           break;
    725         case SCRBS_DISABLED:
    726           gfx_state = ui::NativeTheme::kDisabled;
    727           *gfx_part = ui::NativeTheme::kScrollbarVerticalTrack;
    728           extra->is_upper = true;
    729           break;
    730         default:
    731           NOTREACHED() << "Invalid state: " << state;
    732           break;
    733       }
    734       break;
    735     default:
    736       NOTREACHED() << "Invalid part: " << part;
    737       break;
    738   }
    739   return gfx_state;
    740 }
    741 
    742 void WebThemeEngineImpl::paintScrollbarTrack(
    743     WebCanvas* canvas, int part, int state, int classic_state,
    744     const WebRect& rect, const WebRect& align_rect) {
    745   ui::NativeTheme::Part native_part;
    746   ui::NativeTheme::ExtraParams extra;
    747   ui::NativeTheme::State native_state = WebScrollbarTrackStateToGfx(
    748       part, state, &native_part, &extra.scrollbar_track);
    749   extra.scrollbar_track.classic_state = classic_state;
    750   extra.scrollbar_track.track_x = align_rect.x;
    751   extra.scrollbar_track.track_y = align_rect.y;
    752   extra.scrollbar_track.track_width = align_rect.width;
    753   extra.scrollbar_track.track_height = align_rect.height;
    754 
    755   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    756   ui::NativeTheme::instance()->Paint(canvas, native_part,
    757                                       native_state, gfx_rect, extra);
    758 }
    759 
    760 static ui::NativeTheme::State WebSpinButtonStateToGfx(
    761     int part, int state, ui::NativeTheme::InnerSpinButtonExtraParams* extra) {
    762   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    763   switch (part) {
    764     case SPNP_UP:
    765       switch (state) {
    766         case UPS_NORMAL:
    767           gfx_state = ui::NativeTheme::kNormal;
    768           extra->spin_up = true;
    769           extra->read_only = false;
    770           break;
    771         case UPS_HOT:
    772           gfx_state = ui::NativeTheme::kHovered;
    773           extra->spin_up = true;
    774           extra->read_only = false;
    775           break;
    776         case UPS_PRESSED:
    777           gfx_state = ui::NativeTheme::kPressed;
    778           extra->spin_up = true;
    779           extra->read_only = false;
    780           break;
    781         case UPS_DISABLED:
    782           gfx_state = ui::NativeTheme::kDisabled;
    783           extra->spin_up = true;
    784           extra->read_only = false;
    785           break;
    786         default:
    787           NOTREACHED() << "Invalid state: " << state;
    788           break;
    789       }
    790       break;
    791     case SPNP_DOWN:
    792       switch (state) {
    793         case DNS_NORMAL:
    794           gfx_state = ui::NativeTheme::kNormal;
    795           extra->spin_up = false;
    796           extra->read_only = false;
    797           break;
    798         case DNS_HOT:
    799           gfx_state = ui::NativeTheme::kHovered;
    800           extra->spin_up = false;
    801           extra->read_only = false;
    802           break;
    803         case DNS_PRESSED:
    804           gfx_state = ui::NativeTheme::kPressed;
    805           extra->spin_up = false;
    806           extra->read_only = false;
    807           break;
    808         case DNS_DISABLED:
    809           gfx_state = ui::NativeTheme::kDisabled;
    810           extra->spin_up = false;
    811           extra->read_only = false;
    812           break;
    813         default:
    814           NOTREACHED() << "Invalid state: " << state;
    815           break;
    816       }
    817       break;
    818     default:
    819       NOTREACHED() << "Invalid part: " << part;
    820       break;
    821   }
    822   return gfx_state;
    823 }
    824 
    825 void WebThemeEngineImpl::paintSpinButton(
    826     WebCanvas* canvas, int part, int state, int classic_state,
    827     const WebRect& rect) {
    828   ui::NativeTheme::ExtraParams extra;
    829   ui::NativeTheme::State native_state = WebSpinButtonStateToGfx(
    830       part, state, &extra.inner_spin);
    831   extra.inner_spin.classic_state = classic_state;
    832   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    833   ui::NativeTheme::instance()->Paint(canvas,
    834                                       ui::NativeTheme::kInnerSpinButton,
    835                                       native_state,
    836                                       gfx_rect,
    837                                       extra);
    838 }
    839 
    840 static ui::NativeTheme::State WebTextFieldStateToGfx(
    841     int part, int state, ui::NativeTheme::TextFieldExtraParams* extra) {
    842   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    843   switch (part) {
    844     case EP_EDITTEXT:
    845       switch (state) {
    846         case ETS_NORMAL:
    847           gfx_state = ui::NativeTheme::kNormal;
    848           extra->is_read_only = false;
    849           extra->is_focused = false;
    850           break;
    851         case ETS_HOT:
    852           gfx_state = ui::NativeTheme::kHovered;
    853           extra->is_read_only = false;
    854           extra->is_focused = false;
    855           break;
    856         case ETS_SELECTED:
    857           gfx_state = ui::NativeTheme::kPressed;
    858           extra->is_read_only = false;
    859           extra->is_focused = false;
    860           break;
    861         case ETS_DISABLED:
    862           gfx_state = ui::NativeTheme::kDisabled;
    863           extra->is_read_only = false;
    864           extra->is_focused = false;
    865           break;
    866         case ETS_FOCUSED:
    867           gfx_state = ui::NativeTheme::kNormal;
    868           extra->is_read_only = false;
    869           extra->is_focused = true;
    870           break;
    871         case ETS_READONLY:
    872           gfx_state = ui::NativeTheme::kNormal;
    873           extra->is_read_only = true;
    874           extra->is_focused = false;
    875           break;
    876         default:
    877           NOTREACHED() << "Invalid state: " << state;
    878           break;
    879       }
    880       break;
    881     default:
    882       NOTREACHED() << "Invalid part: " << part;
    883       break;
    884   }
    885   return gfx_state;
    886 }
    887 
    888 void WebThemeEngineImpl::paintTextField(
    889     WebCanvas* canvas, int part, int state, int classic_state,
    890     const WebRect& rect, WebColor color, bool fill_content_area,
    891     bool draw_edges) {
    892   ui::NativeTheme::ExtraParams extra;
    893   ui::NativeTheme::State native_state = WebTextFieldStateToGfx(
    894       part, state, &extra.text_field);
    895   extra.text_field.fill_content_area = fill_content_area;
    896   extra.text_field.draw_edges = draw_edges;
    897   extra.text_field.background_color = color;
    898   extra.text_field.classic_state = classic_state;
    899   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    900 
    901   ui::NativeTheme::instance()->Paint(canvas,
    902       ui::NativeTheme::kTextField, native_state, gfx_rect, extra);
    903 }
    904 
    905 static ui::NativeTheme::State WebTrackbarStateToGfx(
    906     int part,
    907     int state,
    908     ui::NativeTheme::TrackbarExtraParams* extra) {
    909   ui::NativeTheme::State gfx_state = ui::NativeTheme::kNormal;
    910   switch (state) {
    911     case TUS_NORMAL:
    912       gfx_state = ui::NativeTheme::kNormal;
    913       break;
    914     case TUS_HOT:
    915       gfx_state = ui::NativeTheme::kHovered;
    916       break;
    917     case TUS_PRESSED:
    918       gfx_state = ui::NativeTheme::kPressed;
    919       break;
    920     case TUS_DISABLED:
    921       gfx_state = ui::NativeTheme::kDisabled;
    922       break;
    923     default:
    924       NOTREACHED() << "Invalid state: " << state;
    925       break;
    926   }
    927 
    928   switch (part) {
    929     case TKP_TRACK:
    930     case TKP_THUMBBOTTOM:
    931       extra->vertical = false;
    932       break;
    933     case TKP_TRACKVERT:
    934     case TKP_THUMBVERT:
    935       extra->vertical = true;
    936       break;
    937     default:
    938       NOTREACHED() << "Invalid part: " << part;
    939       break;
    940   }
    941 
    942   return gfx_state;
    943 }
    944 
    945 void WebThemeEngineImpl::paintTrackbar(
    946     WebCanvas* canvas, int part, int state, int classic_state,
    947     const WebRect& rect) {
    948   ui::NativeTheme::Part native_part = ui::NativeTheme::kTrackbarTrack;
    949   switch (part) {
    950     case TKP_TRACK:
    951     case TKP_TRACKVERT:
    952       native_part = ui::NativeTheme::kTrackbarTrack;
    953       break;
    954     case TKP_THUMBBOTTOM:
    955     case TKP_THUMBVERT:
    956       native_part = ui::NativeTheme::kTrackbarThumb;
    957       break;
    958     default:
    959       NOTREACHED() << "Invalid part: " << part;
    960       break;
    961   }
    962 
    963   ui::NativeTheme::ExtraParams extra;
    964   ui::NativeTheme::State native_state = WebTrackbarStateToGfx(part, state,
    965                                                                &extra.trackbar);
    966   gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
    967   extra.trackbar.classic_state = classic_state;
    968   ui::NativeTheme::instance()->Paint(canvas, native_part,
    969                                       native_state, gfx_rect, extra);
    970 }
    971 
    972 void WebThemeEngineImpl::paintProgressBar(
    973     WebCanvas* canvas, const WebRect& barRect, const WebRect& valueRect,
    974     bool determinate, double animatedSeconds)
    975 {
    976   gfx::Rect gfx_rect(barRect.x, barRect.y, barRect.width, barRect.height);
    977   ui::NativeTheme::ExtraParams extra;
    978   extra.progress_bar.animated_seconds = animatedSeconds;
    979   extra.progress_bar.determinate = determinate;
    980   extra.progress_bar.value_rect_x = valueRect.x;
    981   extra.progress_bar.value_rect_y = valueRect.y;
    982   extra.progress_bar.value_rect_width = valueRect.width;
    983   extra.progress_bar.value_rect_height = valueRect.height;
    984   ui::NativeTheme::instance()->Paint(canvas, ui::NativeTheme::kProgressBar,
    985                                       ui::NativeTheme::kNormal, gfx_rect,
    986                                       extra);
    987 }
    988 
    989 WebSize WebThemeEngineImpl::getSize(int part) {
    990   switch (part) {
    991     case SBP_ARROWBTN: {
    992       gfx::Size size = ui::NativeTheme::instance()->GetPartSize(
    993           ui::NativeTheme::kScrollbarUpArrow,
    994           ui::NativeTheme::kNormal,
    995           ui::NativeTheme::ExtraParams());
    996       // GetPartSize returns a size of (0, 0) when not using a themed style
    997       // (i.e. Windows Classic).  Returning a non-zero size in this context
    998       // creates repaint conflicts, particularly in the window titlebar area
    999       // which significantly degrades performance.  Fallback to using a system
   1000       // metric if required.
   1001       if (size.width() == 0) {
   1002         int width = static_cast<int>(GetSystemMetrics(SM_CXVSCROLL) /
   1003             gfx::win::GetDeviceScaleFactor());
   1004         size = gfx::Size(width, width);
   1005       }
   1006       return WebSize(size.width(), size.height());
   1007     }
   1008     default:
   1009       NOTREACHED() << "Unhandled part: " << part;
   1010   }
   1011   return WebSize();
   1012 }
   1013 
   1014 }  // namespace webkit_glue
   1015