- add sources.
[platform/framework/web/crosswalk.git] / src / webkit / child / webthemeengine_impl_win.cc
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 WebKit::WebCanvas;
17 using WebKit::WebColor;
18 using WebKit::WebRect;
19 using WebKit::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