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 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 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 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 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 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 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 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 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 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 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 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