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