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
WebRectToRECT(const WebRect & rect)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
WebButtonStateToGfx(int part,int state,ui::NativeTheme::ButtonExtraParams * extra)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
paintButton(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)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
WebListMenuStateToGfx(int part,int state)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
paintMenuList(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)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
WebScrollbarArrowStateToGfx(int state,ui::NativeTheme::Part * part,ui::NativeTheme::ScrollbarArrowExtraParams * extra)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
paintScrollbarArrow(WebCanvas * canvas,int state,int classic_state,const WebRect & rect)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
WebScrollbarThumbStateToGfx(int state,ui::NativeTheme::ScrollbarThumbExtraParams * extra)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
paintScrollbarThumb(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)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
WebScrollbarTrackStateToGfx(int part,int state,ui::NativeTheme::Part * gfx_part,ui::NativeTheme::ScrollbarTrackExtraParams * extra)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
paintScrollbarTrack(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect,const WebRect & align_rect)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
WebSpinButtonStateToGfx(int part,int state,ui::NativeTheme::InnerSpinButtonExtraParams * extra)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
paintSpinButton(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)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
WebTextFieldStateToGfx(int part,int state,ui::NativeTheme::TextFieldExtraParams * extra)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
paintTextField(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect,WebColor color,bool fill_content_area,bool draw_edges)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
WebTrackbarStateToGfx(int part,int state,ui::NativeTheme::TrackbarExtraParams * extra)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
paintTrackbar(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)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
paintProgressBar(WebCanvas * canvas,const WebRect & barRect,const WebRect & valueRect,bool determinate,double animatedSeconds)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
getSize(int part)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