1 // Copyright (c) 2011 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/glue/webthemeengine_impl_win.h"
6
7 #include <vsstyle.h> // To convert to gfx::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/Source/WebKit/chromium/public/WebRect.h"
13 #include "ui/gfx/native_theme_win.h"
14
15 using WebKit::WebCanvas;
16 using WebKit::WebColor;
17 using WebKit::WebRect;
18
19 namespace webkit_glue {
20
WebRectToRECT(const WebRect & rect)21 static RECT WebRectToRECT(const WebRect& rect) {
22 RECT result;
23 result.left = rect.x;
24 result.top = rect.y;
25 result.right = rect.x + rect.width;
26 result.bottom = rect.y + rect.height;
27 return result;
28 }
29
WebButtonStateToGfx(int part,int state,gfx::NativeTheme::ButtonExtraParams * extra)30 static gfx::NativeTheme::State WebButtonStateToGfx(
31 int part,
32 int state,
33 gfx::NativeTheme::ButtonExtraParams* extra) {
34 gfx::NativeTheme::State gfx_state = gfx::NativeTheme::kNormal;
35
36 if (part == BP_PUSHBUTTON) {
37 switch(state) {
38 case PBS_NORMAL:
39 gfx_state = gfx::NativeTheme::kNormal;
40 extra->checked = false;
41 extra->indeterminate = false;
42 extra->is_default = false;
43 break;
44 case PBS_HOT:
45 gfx_state = gfx::NativeTheme::kHovered;
46 extra->checked = false;
47 extra->indeterminate = false;
48 extra->is_default = false;
49 break;
50 case PBS_PRESSED:
51 gfx_state = gfx::NativeTheme::kPressed;
52 extra->checked = false;
53 extra->indeterminate = false;
54 extra->is_default = false;
55 break;
56 case PBS_DISABLED:
57 gfx_state = gfx::NativeTheme::kDisabled;
58 extra->checked = false;
59 extra->indeterminate = false;
60 extra->is_default = false;
61 break;
62 case PBS_DEFAULTED:
63 gfx_state = gfx::NativeTheme::kNormal;
64 extra->checked = false;
65 extra->indeterminate = false;
66 extra->is_default = true;
67 break;
68 case PBS_DEFAULTED_ANIMATING:
69 gfx_state = gfx::NativeTheme::kNormal;
70 extra->checked = false;
71 extra->indeterminate = false;
72 extra->is_default = true;
73 break;
74 default:
75 NOTREACHED() << "Invalid state: " << state;
76 }
77 } else if (part == BP_RADIOBUTTON) {
78 switch(state) {
79 case RBS_UNCHECKEDNORMAL:
80 gfx_state = gfx::NativeTheme::kNormal;
81 extra->checked = false;
82 extra->indeterminate = false;
83 extra->is_default = false;
84 break;
85 case RBS_UNCHECKEDHOT:
86 gfx_state = gfx::NativeTheme::kHovered;
87 extra->checked = false;
88 extra->indeterminate = false;
89 extra->is_default = false;
90 break;
91 case RBS_UNCHECKEDPRESSED:
92 gfx_state = gfx::NativeTheme::kPressed;
93 extra->checked = false;
94 extra->indeterminate = false;
95 extra->is_default = false;
96 break;
97 case RBS_UNCHECKEDDISABLED:
98 gfx_state = gfx::NativeTheme::kDisabled;
99 extra->checked = false;
100 extra->indeterminate = false;
101 extra->is_default = false;
102 break;
103 case RBS_CHECKEDNORMAL:
104 gfx_state = gfx::NativeTheme::kNormal;
105 extra->checked = true;
106 extra->indeterminate = false;
107 extra->is_default = false;
108 break;
109 case RBS_CHECKEDHOT:
110 gfx_state = gfx::NativeTheme::kHovered;
111 extra->checked = true;
112 extra->indeterminate = false;
113 extra->is_default = false;
114 break;
115 case RBS_CHECKEDPRESSED:
116 gfx_state = gfx::NativeTheme::kPressed;
117 extra->checked = true;
118 extra->indeterminate = false;
119 extra->is_default = false;
120 break;
121 case RBS_CHECKEDDISABLED:
122 gfx_state = gfx::NativeTheme::kDisabled;
123 extra->checked = true;
124 extra->indeterminate = false;
125 extra->is_default = false;
126 break;
127 default:
128 NOTREACHED() << "Invalid state: " << state;
129 break;
130 }
131 } else if (part == BP_CHECKBOX) {
132 switch(state) {
133 case CBS_UNCHECKEDNORMAL:
134 gfx_state = gfx::NativeTheme::kNormal;
135 extra->checked = false;
136 extra->indeterminate = false;
137 extra->is_default = false;
138 break;
139 case CBS_UNCHECKEDHOT:
140 gfx_state = gfx::NativeTheme::kHovered;
141 extra->checked = false;
142 extra->indeterminate = false;
143 extra->is_default = false;
144 break;
145 case CBS_UNCHECKEDPRESSED:
146 gfx_state = gfx::NativeTheme::kPressed;
147 extra->checked = false;
148 extra->indeterminate = false;
149 extra->is_default = false;
150 break;
151 case CBS_UNCHECKEDDISABLED:
152 gfx_state = gfx::NativeTheme::kDisabled;
153 extra->checked = false;
154 extra->indeterminate = false;
155 extra->is_default = false;
156 break;
157 case CBS_CHECKEDNORMAL:
158 gfx_state = gfx::NativeTheme::kNormal;
159 extra->checked = true;
160 extra->indeterminate = false;
161 extra->is_default = false;
162 break;
163 case CBS_CHECKEDHOT:
164 gfx_state = gfx::NativeTheme::kHovered;
165 extra->checked = true;
166 extra->indeterminate = false;
167 extra->is_default = false;
168 break;
169 case CBS_CHECKEDPRESSED:
170 gfx_state = gfx::NativeTheme::kPressed;
171 extra->checked = true;
172 extra->indeterminate = false;
173 extra->is_default = false;
174 break;
175 case CBS_CHECKEDDISABLED:
176 gfx_state = gfx::NativeTheme::kDisabled;
177 extra->checked = true;
178 extra->indeterminate = false;
179 extra->is_default = false;
180 break;
181 case CBS_MIXEDNORMAL:
182 gfx_state = gfx::NativeTheme::kNormal;
183 extra->checked = false;
184 extra->indeterminate = true;
185 extra->is_default = false;
186 break;
187 case CBS_MIXEDHOT:
188 gfx_state = gfx::NativeTheme::kHovered;
189 extra->checked = false;
190 extra->indeterminate = true;
191 extra->is_default = false;
192 break;
193 case CBS_MIXEDPRESSED:
194 gfx_state = gfx::NativeTheme::kPressed;
195 extra->checked = false;
196 extra->indeterminate = true;
197 extra->is_default = false;
198 break;
199 case CBS_MIXEDDISABLED:
200 gfx_state = gfx::NativeTheme::kDisabled;
201 extra->checked = false;
202 extra->indeterminate = true;
203 extra->is_default = false;
204 break;
205 case CBS_IMPLICITNORMAL:
206 gfx_state = gfx::NativeTheme::kNormal;
207 extra->checked = false;
208 extra->indeterminate = false;
209 extra->is_default = false;
210 break;
211 case CBS_IMPLICITHOT:
212 gfx_state = gfx::NativeTheme::kHovered;
213 extra->checked = false;
214 extra->indeterminate = false;
215 extra->is_default = false;
216 break;
217 case CBS_IMPLICITPRESSED:
218 gfx_state = gfx::NativeTheme::kPressed;
219 extra->checked = false;
220 extra->indeterminate = false;
221 extra->is_default = false;
222 break;
223 case CBS_IMPLICITDISABLED:
224 gfx_state = gfx::NativeTheme::kDisabled;
225 extra->checked = false;
226 extra->indeterminate = false;
227 extra->is_default = false;
228 break;
229 case CBS_EXCLUDEDNORMAL:
230 gfx_state = gfx::NativeTheme::kNormal;
231 extra->checked = false;
232 extra->indeterminate = false;
233 extra->is_default = false;
234 break;
235 case CBS_EXCLUDEDHOT:
236 gfx_state = gfx::NativeTheme::kHovered;
237 extra->checked = false;
238 extra->indeterminate = false;
239 extra->is_default = false;
240 break;
241 case CBS_EXCLUDEDPRESSED:
242 gfx_state = gfx::NativeTheme::kPressed;
243 extra->checked = false;
244 extra->indeterminate = false;
245 extra->is_default = false;
246 break;
247 case CBS_EXCLUDEDDISABLED:
248 gfx_state = gfx::NativeTheme::kDisabled;
249 extra->checked = false;
250 extra->indeterminate = false;
251 extra->is_default = false;
252 break;
253 default:
254 NOTREACHED() << "Invalid state: " << state;
255 break;
256 }
257 } else if (part == BP_GROUPBOX) {
258 switch(state) {
259 case GBS_NORMAL:
260 gfx_state = gfx::NativeTheme::kNormal;
261 extra->checked = false;
262 extra->indeterminate = false;
263 extra->is_default = false;
264 break;
265 case GBS_DISABLED:
266 gfx_state = gfx::NativeTheme::kDisabled;
267 extra->checked = false;
268 extra->indeterminate = false;
269 extra->is_default = false;
270 break;
271 default:
272 NOTREACHED() << "Invalid state: " << state;
273 break;
274 }
275 } else if (part == BP_COMMANDLINK) {
276 switch(state) {
277 case CMDLS_NORMAL:
278 gfx_state = gfx::NativeTheme::kNormal;
279 extra->checked = false;
280 extra->indeterminate = false;
281 extra->is_default = false;
282 break;
283 case CMDLS_HOT:
284 gfx_state = gfx::NativeTheme::kHovered;
285 extra->checked = false;
286 extra->indeterminate = false;
287 extra->is_default = false;
288 break;
289 case CMDLS_PRESSED:
290 gfx_state = gfx::NativeTheme::kPressed;
291 extra->checked = false;
292 extra->indeterminate = false;
293 extra->is_default = false;
294 break;
295 case CMDLS_DISABLED:
296 gfx_state = gfx::NativeTheme::kDisabled;
297 extra->checked = false;
298 extra->indeterminate = false;
299 extra->is_default = false;
300 break;
301 case CMDLS_DEFAULTED:
302 gfx_state = gfx::NativeTheme::kNormal;
303 extra->checked = false;
304 extra->indeterminate = false;
305 extra->is_default = true;
306 break;
307 case CMDLS_DEFAULTED_ANIMATING:
308 gfx_state = gfx::NativeTheme::kNormal;
309 extra->checked = false;
310 extra->indeterminate = false;
311 extra->is_default = true;
312 break;
313 default:
314 NOTREACHED() << "Invalid state: " << state;
315 break;
316 }
317 } else if (part == BP_COMMANDLINKGLYPH) {
318 switch(state) {
319 case CMDLGS_NORMAL:
320 gfx_state = gfx::NativeTheme::kNormal;
321 extra->checked = false;
322 extra->indeterminate = false;
323 extra->is_default = false;
324 break;
325 case CMDLGS_HOT:
326 gfx_state = gfx::NativeTheme::kHovered;
327 extra->checked = false;
328 extra->indeterminate = false;
329 extra->is_default = false;
330 break;
331 case CMDLGS_PRESSED:
332 gfx_state = gfx::NativeTheme::kPressed;
333 extra->checked = false;
334 extra->indeterminate = false;
335 extra->is_default = false;
336 break;
337 case CMDLGS_DISABLED:
338 gfx_state = gfx::NativeTheme::kDisabled;
339 extra->checked = false;
340 extra->indeterminate = false;
341 extra->is_default = false;
342 break;
343 case CMDLGS_DEFAULTED:
344 gfx_state = gfx::NativeTheme::kNormal;
345 extra->checked = false;
346 extra->indeterminate = false;
347 extra->is_default = true;
348 break;
349 default:
350 NOTREACHED() << "Invalid state: " << state;
351 break;
352 }
353 }
354 return gfx_state;
355 }
356
paintButton(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)357 void WebThemeEngineImpl::paintButton(
358 WebCanvas* canvas, int part, int state, int classic_state,
359 const WebRect& rect) {
360 gfx::NativeTheme::Part native_part = gfx::NativeTheme::kPushButton;
361 switch(part) {
362 case BP_PUSHBUTTON:
363 native_part = gfx::NativeTheme::kPushButton;
364 break;
365 case BP_CHECKBOX:
366 native_part = gfx::NativeTheme::kCheckbox;
367 break;
368 case BP_RADIOBUTTON:
369 native_part = gfx::NativeTheme::kRadio;
370 break;
371 default:
372 break;
373 }
374 gfx::NativeTheme::ExtraParams extra;
375 gfx::NativeTheme::State native_state = WebButtonStateToGfx(part, state,
376 &extra.button);
377 extra.button.classic_state = classic_state;
378 gfx::Rect gfx_rect(rect.x, rect.y, rect.width, rect.height);
379 gfx::NativeTheme::instance()->Paint(canvas, native_part,
380 native_state, gfx_rect, extra);
381 }
382
paintMenuList(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)383 void WebThemeEngineImpl::paintMenuList(
384 WebCanvas* canvas, int part, int state, int classic_state,
385 const WebRect& rect) {
386 HDC hdc = skia::BeginPlatformPaint(canvas);
387
388 RECT native_rect = WebRectToRECT(rect);
389 gfx::NativeThemeWin::instance()->PaintMenuList(
390 hdc, part, state, classic_state, &native_rect);
391
392 skia::EndPlatformPaint(canvas);
393 }
394
paintScrollbarArrow(WebCanvas * canvas,int state,int classic_state,const WebRect & rect)395 void WebThemeEngineImpl::paintScrollbarArrow(
396 WebCanvas* canvas, int state, int classic_state,
397 const WebRect& rect) {
398 HDC hdc = skia::BeginPlatformPaint(canvas);
399
400 RECT native_rect = WebRectToRECT(rect);
401 gfx::NativeThemeWin::instance()->PaintScrollbarArrow(
402 hdc, state, classic_state, &native_rect);
403
404 skia::EndPlatformPaint(canvas);
405 }
406
paintScrollbarThumb(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)407 void WebThemeEngineImpl::paintScrollbarThumb(
408 WebCanvas* canvas, int part, int state, int classic_state,
409 const WebRect& rect) {
410 HDC hdc = skia::BeginPlatformPaint(canvas);
411
412 RECT native_rect = WebRectToRECT(rect);
413 gfx::NativeThemeWin::instance()->PaintScrollbarThumb(
414 hdc, part, state, classic_state, &native_rect);
415
416 skia::EndPlatformPaint(canvas);
417 }
418
paintScrollbarTrack(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect,const WebRect & align_rect)419 void WebThemeEngineImpl::paintScrollbarTrack(
420 WebCanvas* canvas, int part, int state, int classic_state,
421 const WebRect& rect, const WebRect& align_rect) {
422 HDC hdc = skia::BeginPlatformPaint(canvas);
423
424 RECT native_rect = WebRectToRECT(rect);
425 RECT native_align_rect = WebRectToRECT(align_rect);
426 gfx::NativeThemeWin::instance()->PaintScrollbarTrack(
427 hdc, part, state, classic_state, &native_rect, &native_align_rect,
428 canvas);
429
430 skia::EndPlatformPaint(canvas);
431 }
432
paintSpinButton(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)433 void WebThemeEngineImpl::paintSpinButton(
434 WebCanvas* canvas, int part, int state, int classic_state,
435 const WebRect& rect) {
436 HDC hdc = skia::BeginPlatformPaint(canvas);
437
438 RECT native_rect = WebRectToRECT(rect);
439 gfx::NativeThemeWin::instance()->PaintSpinButton(
440 hdc, part, state, classic_state, &native_rect);
441
442 skia::EndPlatformPaint(canvas);
443 }
444
paintTextField(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect,WebColor color,bool fill_content_area,bool draw_edges)445 void WebThemeEngineImpl::paintTextField(
446 WebCanvas* canvas, int part, int state, int classic_state,
447 const WebRect& rect, WebColor color, bool fill_content_area,
448 bool draw_edges) {
449 HDC hdc = skia::BeginPlatformPaint(canvas);
450
451 RECT native_rect = WebRectToRECT(rect);
452 COLORREF c = skia::SkColorToCOLORREF(color);
453
454 gfx::NativeThemeWin::instance()->PaintTextField(
455 hdc, part, state, classic_state, &native_rect, c, fill_content_area,
456 draw_edges);
457
458 skia::EndPlatformPaint(canvas);
459 }
460
paintTrackbar(WebCanvas * canvas,int part,int state,int classic_state,const WebRect & rect)461 void WebThemeEngineImpl::paintTrackbar(
462 WebCanvas* canvas, int part, int state, int classic_state,
463 const WebRect& rect) {
464 HDC hdc = skia::BeginPlatformPaint(canvas);
465
466 RECT native_rect = WebRectToRECT(rect);
467 gfx::NativeThemeWin::instance()->PaintTrackbar(
468 hdc, part, state, classic_state, &native_rect, canvas);
469
470 skia::EndPlatformPaint(canvas);
471 }
472
paintProgressBar(WebCanvas * canvas,const WebRect & barRect,const WebRect & valueRect,bool determinate,double animatedSeconds)473 void WebThemeEngineImpl::paintProgressBar(
474 WebCanvas* canvas, const WebRect& barRect, const WebRect& valueRect,
475 bool determinate, double animatedSeconds)
476 {
477 HDC hdc = skia::BeginPlatformPaint(canvas);
478
479 RECT native_bar_rect = WebRectToRECT(barRect);
480 RECT native_value_rect = WebRectToRECT(valueRect);
481 gfx::NativeThemeWin::instance()->PaintProgressBar(
482 hdc, &native_bar_rect,
483 &native_value_rect, determinate, animatedSeconds, canvas);
484
485 skia::EndPlatformPaint(canvas);
486 }
487
488 } // namespace webkit_glue
489