1 /* 2 * This file is part of the WebKit project. 3 * 4 * Copyright (C) 2006 Apple Computer, Inc. 5 * Copyright (C) 2008, 2009 Google, Inc. 6 * Copyright (C) 2009 Kenneth Rohde Christiansen 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 * Boston, MA 02111-1307, USA. 22 * 23 */ 24 25 #include "config.h" 26 #include "core/rendering/RenderThemeChromiumWin.h" 27 28 #include <windows.h> 29 #include <uxtheme.h> 30 #include <vssym32.h> 31 32 #include "CSSValueKeywords.h" 33 #include "HTMLNames.h" 34 #include "core/html/HTMLMediaElement.h" 35 #include "core/html/shadow/MediaControlElements.h" 36 #include "core/rendering/PaintInfo.h" 37 #include "core/rendering/RenderBox.h" 38 #include "core/rendering/RenderProgress.h" 39 #include "core/rendering/RenderSlider.h" 40 #include "platform/LayoutTestSupport.h" 41 #include "platform/fonts/FontSelector.h" 42 #include "platform/graphics/GraphicsContext.h" 43 #include "platform/graphics/win/TransparencyWin.h" 44 #include "platform/scroll/ScrollbarTheme.h" 45 #include "platform/win/SystemInfo.h" 46 #include "public/platform/Platform.h" 47 #include "public/platform/WebColor.h" 48 #include "public/platform/WebRect.h" 49 #include "public/platform/win/WebThemeEngine.h" 50 #include "wtf/CurrentTime.h" 51 #include "wtf/StdLibExtras.h" 52 53 // FIXME: This dependency should eventually be removed. 54 #include <skia/ext/skia_utils_win.h> 55 56 namespace WebCore { 57 58 // The standard width for the menu list drop-down button when run under 59 // layout test mode. Use the value that's currently captured in most baselines. 60 static const int kStandardMenuListButtonWidth = 17; 61 62 namespace { 63 // We must not create multiple ThemePainter instances. 64 class ThemePainter { 65 public: 66 ThemePainter(GraphicsContext* context, const IntRect& r) 67 { 68 #ifndef NDEBUG 69 ASSERT(!s_hasInstance); 70 s_hasInstance = true; 71 #endif 72 TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM()); 73 m_helper.init(context, getLayerMode(context, transformMode), transformMode, r); 74 75 if (!m_helper.context()) { 76 // TransparencyWin doesn't have well-defined copy-ctor nor op=() 77 // so we re-initialize it instead of assigning a fresh istance. 78 // On the reinitialization, we fallback to use NoLayer mode. 79 // Note that the original initialization failure can be caused by 80 // a failure of an internal buffer allocation and NoLayer mode 81 // does not have such buffer allocations. 82 m_helper.~TransparencyWin(); 83 new (&m_helper) TransparencyWin(); 84 m_helper.init(context, TransparencyWin::NoLayer, transformMode, r); 85 } 86 } 87 88 ~ThemePainter() 89 { 90 m_helper.composite(); 91 #ifndef NDEBUG 92 s_hasInstance = false; 93 #endif 94 } 95 96 GraphicsContext* context() { return m_helper.context(); } 97 const IntRect& drawRect() { return m_helper.drawRect(); } 98 99 private: 100 101 static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode) 102 { 103 if (!context->isCertainlyOpaque()) // Might have transparent background. 104 return TransparencyWin::WhiteLayer; 105 if (context->canvas()->isDrawingToLayer()) // Needs antialiasing help. 106 return TransparencyWin::OpaqueCompositeLayer; 107 // Nothing interesting. 108 return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer; 109 } 110 111 static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix) 112 { 113 if (matrix.b() || matrix.c()) // Skew. 114 return TransparencyWin::Untransform; 115 if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale. 116 return TransparencyWin::ScaleTransform; 117 // Nothing interesting. 118 return TransparencyWin::KeepTransform; 119 } 120 121 TransparencyWin m_helper; 122 #ifndef NDEBUG 123 static bool s_hasInstance; 124 #endif 125 }; 126 127 #ifndef NDEBUG 128 bool ThemePainter::s_hasInstance = false; 129 #endif 130 131 } // namespace 132 133 // Internal static helper functions. We don't put them in an anonymous 134 // namespace so they have easier access to the WebCore namespace. 135 136 static bool supportsFocus(ControlPart appearance) 137 { 138 switch (appearance) { 139 case SquareButtonPart: 140 case PushButtonPart: 141 case ButtonPart: 142 case SearchFieldPart: 143 case TextFieldPart: 144 case TextAreaPart: 145 return true; 146 } 147 return false; 148 } 149 150 static double querySystemBlinkInterval(double defaultInterval) 151 { 152 UINT blinkTime = GetCaretBlinkTime(); 153 if (!blinkTime) 154 return defaultInterval; 155 if (blinkTime == INFINITE) 156 return 0; 157 return blinkTime / 1000.0; 158 } 159 160 PassRefPtr<RenderTheme> RenderThemeChromiumWin::create() 161 { 162 return adoptRef(new RenderThemeChromiumWin); 163 } 164 165 RenderTheme& RenderTheme::theme() 166 { 167 DEFINE_STATIC_REF(RenderTheme, renderTheme, (RenderThemeChromiumWin::create())); 168 return *renderTheme; 169 } 170 171 bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const 172 { 173 // Let webkit draw one of its halo rings around any focused element, 174 // except push buttons. For buttons we use the windows PBS_DEFAULTED 175 // styling to give it a blue border. 176 return style->appearance() == ButtonPart 177 || style->appearance() == PushButtonPart 178 || style->appearance() == SquareButtonPart; 179 } 180 181 Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const 182 { 183 if (isRunningLayoutTest()) 184 return Color(0x00, 0x00, 0xff); // Royal blue. 185 COLORREF color = GetSysColor(COLOR_HIGHLIGHT); 186 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 187 } 188 189 Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const 190 { 191 if (isRunningLayoutTest()) 192 return Color(0x99, 0x99, 0x99); // Medium gray. 193 COLORREF color = GetSysColor(COLOR_GRAYTEXT); 194 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 195 } 196 197 Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const 198 { 199 if (isRunningLayoutTest()) 200 return Color(0xff, 0xff, 0xcc); // Pale yellow. 201 COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT); 202 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 203 } 204 205 Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const 206 { 207 return Color::white; 208 } 209 210 Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const 211 { 212 return Color(0xff, 0x96, 0x32); // Orange. 213 } 214 215 Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const 216 { 217 return Color(0xff, 0xff, 0x96); // Yellow. 218 } 219 220 // Map a CSSValue* system color to an index understood by GetSysColor(). 221 static int cssValueIdToSysColorIndex(int cssValueId) 222 { 223 switch (cssValueId) { 224 case CSSValueActiveborder: return COLOR_ACTIVEBORDER; 225 case CSSValueActivecaption: return COLOR_ACTIVECAPTION; 226 case CSSValueAppworkspace: return COLOR_APPWORKSPACE; 227 case CSSValueBackground: return COLOR_BACKGROUND; 228 case CSSValueButtonface: return COLOR_BTNFACE; 229 case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT; 230 case CSSValueButtonshadow: return COLOR_BTNSHADOW; 231 case CSSValueButtontext: return COLOR_BTNTEXT; 232 case CSSValueCaptiontext: return COLOR_CAPTIONTEXT; 233 case CSSValueGraytext: return COLOR_GRAYTEXT; 234 case CSSValueHighlight: return COLOR_HIGHLIGHT; 235 case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT; 236 case CSSValueInactiveborder: return COLOR_INACTIVEBORDER; 237 case CSSValueInactivecaption: return COLOR_INACTIVECAPTION; 238 case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT; 239 case CSSValueInfobackground: return COLOR_INFOBK; 240 case CSSValueInfotext: return COLOR_INFOTEXT; 241 case CSSValueMenu: return COLOR_MENU; 242 case CSSValueMenutext: return COLOR_MENUTEXT; 243 case CSSValueScrollbar: return COLOR_SCROLLBAR; 244 case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW; 245 case CSSValueThreedface: return COLOR_3DFACE; 246 case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT; 247 case CSSValueThreedlightshadow: return COLOR_3DLIGHT; 248 case CSSValueThreedshadow: return COLOR_3DSHADOW; 249 case CSSValueWindow: return COLOR_WINDOW; 250 case CSSValueWindowframe: return COLOR_WINDOWFRAME; 251 case CSSValueWindowtext: return COLOR_WINDOWTEXT; 252 default: return -1; // Unsupported CSSValue 253 } 254 } 255 256 Color RenderThemeChromiumWin::systemColor(CSSValueID cssValueId) const 257 { 258 int sysColorIndex = cssValueIdToSysColorIndex(cssValueId); 259 if (isRunningLayoutTest() || (sysColorIndex == -1)) 260 return RenderTheme::systemColor(cssValueId); 261 262 COLORREF color = GetSysColor(sysColorIndex); 263 return Color(GetRValue(color), GetGValue(color), GetBValue(color)); 264 } 265 266 IntSize RenderThemeChromiumWin::sliderTickSize() const 267 { 268 return IntSize(1, 3); 269 } 270 271 int RenderThemeChromiumWin::sliderTickOffsetFromTrackCenter() const 272 { 273 return 11; 274 } 275 276 void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const 277 { 278 // These sizes match what WinXP draws for various menus. 279 const int sliderThumbAlongAxis = 11; 280 const int sliderThumbAcrossAxis = 21; 281 if (style->appearance() == SliderThumbHorizontalPart) { 282 style->setWidth(Length(sliderThumbAlongAxis, Fixed)); 283 style->setHeight(Length(sliderThumbAcrossAxis, Fixed)); 284 } else if (style->appearance() == SliderThumbVerticalPart) { 285 style->setWidth(Length(sliderThumbAcrossAxis, Fixed)); 286 style->setHeight(Length(sliderThumbAlongAxis, Fixed)); 287 } else 288 RenderThemeChromiumSkia::adjustSliderThumbSize(style, element); 289 } 290 291 bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r) 292 { 293 return paintButton(o, i, r); 294 } 295 bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r) 296 { 297 return paintButton(o, i, r); 298 } 299 300 bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r) 301 { 302 const ThemeData& themeData = getThemeData(o); 303 304 ThemePainter painter(i.context, r); 305 blink::WebCanvas* canvas = painter.context()->canvas(); 306 blink::Platform::current()->themeEngine()->paintButton(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect())); 307 return false; 308 } 309 310 bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r) 311 { 312 return paintTextFieldInternal(o, i, r, true); 313 } 314 315 bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r) 316 { 317 const ThemeData& themeData = getThemeData(o); 318 319 ThemePainter painter(i.context, r); 320 blink::WebCanvas* canvas = painter.context()->canvas(); 321 blink::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect())); 322 323 paintSliderTicks(o, i, r); 324 325 return false; 326 } 327 328 bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r) 329 { 330 const ThemeData& themeData = getThemeData(o); 331 332 ThemePainter painter(i.context, r); 333 blink::WebCanvas* canvas = painter.context()->canvas(); 334 blink::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect())); 335 336 return false; 337 } 338 339 static int menuListButtonWidth() 340 { 341 static int width = isRunningLayoutTest() ? kStandardMenuListButtonWidth : 342 IntSize(blink::Platform::current()->themeEngine()->getSize(SBP_ARROWBTN)).width(); 343 return width; 344 } 345 346 // Used to paint unstyled menulists (i.e. with the default border) 347 bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r) 348 { 349 if (!o->isBox()) 350 return false; 351 352 const RenderBox* box = toRenderBox(o); 353 int borderRight = box->borderRight(); 354 int borderLeft = box->borderLeft(); 355 int borderTop = box->borderTop(); 356 int borderBottom = box->borderBottom(); 357 358 // If all the borders are 0, then tell skia not to paint the border on the 359 // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not 360 // draw individual borders and then pass that to skia so we can avoid 361 // drawing any borders that are set to 0. For non-zero borders, we draw the 362 // border, but webkit just draws over it. 363 bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom); 364 365 paintTextFieldInternal(o, i, r, drawEdges); 366 return paintMenuListButton(o, i, r); 367 } 368 369 bool RenderThemeChromiumWin::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r) 370 { 371 if (!o->isBox()) 372 return false; 373 374 const RenderBox* box = toRenderBox(o); 375 // Take padding and border into account. If the MenuList is smaller than 376 // the size of a button, make sure to shrink it appropriately and not put 377 // its x position to the left of the menulist. 378 const int buttonWidth = menuListButtonWidth(); 379 int spacingLeft = box->borderLeft() + box->paddingLeft(); 380 int spacingRight = box->borderRight() + box->paddingRight(); 381 int spacingTop = box->borderTop() + box->paddingTop(); 382 int spacingBottom = box->borderBottom() + box->paddingBottom(); 383 384 int buttonX; 385 if (r.maxX() - r.x() < buttonWidth) 386 buttonX = r.x(); 387 else 388 buttonX = o->style()->direction() == LTR ? r.maxX() - spacingRight - buttonWidth : r.x() + spacingLeft; 389 390 // Compute the rectangle of the button in the destination image. 391 IntRect rect(buttonX, 392 r.y() + spacingTop, 393 std::min(buttonWidth, r.maxX() - r.x()), 394 r.height() - (spacingTop + spacingBottom)); 395 396 // Get the correct theme data for a textfield and paint the menu. 397 ThemePainter painter(i.context, rect); 398 blink::WebCanvas* canvas = painter.context()->canvas(); 399 blink::Platform::current()->themeEngine()->paintMenuList(canvas, CP_DROPDOWNBUTTON, determineState(o), determineClassicState(o), blink::WebRect(painter.drawRect())); 400 return false; 401 } 402 403 double RenderThemeChromiumWin::caretBlinkIntervalInternal() const 404 { 405 // This involves a system call, so we cache the result. 406 static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval()); 407 return blinkInterval; 408 } 409 410 unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart) 411 { 412 unsigned result = TS_NORMAL; 413 ControlPart appearance = o->style()->appearance(); 414 if (!isEnabled(o)) 415 result = TS_DISABLED; 416 else if (isReadOnlyControl(o)) 417 result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED; 418 // Active overrides hover and focused. 419 else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) 420 result = TS_PRESSED; 421 else if (supportsFocus(appearance) && isFocused(o)) 422 result = ETS_FOCUSED; 423 else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) 424 result = TS_HOT; 425 426 // CBS_UNCHECKED*: 1-4 427 // CBS_CHECKED*: 5-8 428 // CBS_MIXED*: 9-12 429 if (isIndeterminate(o)) 430 result += 8; 431 else if (isChecked(o)) 432 result += 4; 433 return result; 434 } 435 436 unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o) 437 { 438 unsigned result = TUS_NORMAL; 439 if (!isEnabled(o)) 440 result = TUS_DISABLED; 441 else if (supportsFocus(o->style()->appearance()) && isFocused(o)) 442 result = TUS_FOCUSED; 443 else if (isPressed(o)) 444 result = TUS_PRESSED; 445 else if (isHovered(o)) 446 result = TUS_HOT; 447 return result; 448 } 449 450 unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart) 451 { 452 unsigned result = 0; 453 454 ControlPart part = o->style()->appearance(); 455 456 // Sliders are always in the normal state. 457 if (part == SliderHorizontalPart || part == SliderVerticalPart) 458 return result; 459 460 // So are readonly text fields. 461 if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart)) 462 return result; 463 464 if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { 465 if (!isEnabled(o)) 466 result = DFCS_INACTIVE; 467 else if (isPressed(o)) // Active supersedes hover 468 result = DFCS_PUSHED; 469 else if (isHovered(o)) 470 result = DFCS_HOT; 471 } else { 472 if (!isEnabled(o) || isReadOnlyControl(o)) 473 result = DFCS_INACTIVE; 474 // Active supersedes hover 475 else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) 476 result = DFCS_PUSHED; 477 else if (supportsFocus(part) && isFocused(o)) // So does focused 478 result = 0; 479 else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) 480 result = DFCS_HOT; 481 // Classic theme can't represent indeterminate states. Use unchecked appearance. 482 if (isChecked(o) && !isIndeterminate(o)) 483 result |= DFCS_CHECKED; 484 } 485 return result; 486 } 487 488 ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart) 489 { 490 ThemeData result; 491 switch (o->style()->appearance()) { 492 case CheckboxPart: 493 result.m_part = BP_CHECKBOX; 494 result.m_state = determineState(o); 495 result.m_classicState = DFCS_BUTTONCHECK; 496 break; 497 case RadioPart: 498 result.m_part = BP_RADIOBUTTON; 499 result.m_state = determineState(o); 500 result.m_classicState = DFCS_BUTTONRADIO; 501 break; 502 case SquareButtonPart: 503 case PushButtonPart: 504 case ButtonPart: 505 result.m_part = BP_PUSHBUTTON; 506 result.m_state = determineState(o); 507 result.m_classicState = DFCS_BUTTONPUSH; 508 break; 509 case SliderHorizontalPart: 510 result.m_part = TKP_TRACK; 511 result.m_state = TRS_NORMAL; 512 break; 513 case SliderVerticalPart: 514 result.m_part = TKP_TRACKVERT; 515 result.m_state = TRVS_NORMAL; 516 break; 517 case SliderThumbHorizontalPart: 518 result.m_part = TKP_THUMBBOTTOM; 519 result.m_state = determineSliderThumbState(o); 520 break; 521 case SliderThumbVerticalPart: 522 result.m_part = TKP_THUMBVERT; 523 result.m_state = determineSliderThumbState(o); 524 break; 525 case ListboxPart: 526 case MenulistPart: 527 case MenulistButtonPart: 528 case SearchFieldPart: 529 case TextFieldPart: 530 case TextAreaPart: 531 result.m_part = EP_EDITTEXT; 532 result.m_state = determineState(o); 533 break; 534 case InnerSpinButtonPart: 535 result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN; 536 result.m_state = determineState(o, subPart); 537 result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN; 538 break; 539 } 540 541 result.m_classicState |= determineClassicState(o, subPart); 542 543 return result; 544 } 545 546 bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o, 547 const PaintInfo& i, 548 const IntRect& r, 549 bool drawEdges) 550 { 551 // Fallback to white if the specified color object is invalid. 552 Color backgroundColor(Color::white); 553 if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) 554 backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor); 555 556 // If we have background-image, don't fill the content area to expose the 557 // parent's background. Also, we shouldn't fill the content area if the 558 // alpha of the color is 0. The API of Windows GDI ignores the alpha. 559 // 560 // Note that we should paint the content area white if we have neither the 561 // background color nor background image explicitly specified to keep the 562 // appearance of select element consistent with other browsers. 563 bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha(); 564 565 if (o->style()->hasBorderRadius()) { 566 // If the style has rounded borders, setup the context to clip the 567 // background (themed or filled) appropriately. 568 // FIXME: make sure we do the right thing if css background-clip is set. 569 i.context->save(); 570 i.context->clipRoundedRect(o->style()->getRoundedBorderFor(r)); 571 } 572 { 573 const ThemeData& themeData = getThemeData(o); 574 ThemePainter painter(i.context, r); 575 blink::WebCanvas* canvas = painter.context()->canvas(); 576 blink::Platform::current()->themeEngine()->paintTextField(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, blink::WebRect(painter.drawRect()), backgroundColor.rgb(), fillContentArea, drawEdges); 577 // End of block commits the painter before restoring context. 578 } 579 if (o->style()->hasBorderRadius()) 580 i.context->restore(); 581 return false; 582 } 583 584 void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(RenderStyle* style, Element*) const 585 { 586 int width = ScrollbarTheme::theme()->scrollbarThickness(); 587 style->setWidth(Length(width, Fixed)); 588 style->setMinWidth(Length(width, Fixed)); 589 } 590 591 bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect) 592 { 593 IntRect half = rect; 594 595 // Need explicit blocks to avoid to create multiple ThemePainter instances. 596 { 597 half.setHeight(rect.height() / 2); 598 const ThemeData& upThemeData = getThemeData(object, SpinButtonUp); 599 ThemePainter upPainter(info.context, half); 600 blink::WebCanvas* canvas = upPainter.context()->canvas(); 601 blink::Platform::current()->themeEngine()->paintSpinButton(canvas, upThemeData.m_part, upThemeData.m_state, upThemeData.m_classicState, blink::WebRect(upPainter.drawRect())); 602 } 603 604 { 605 half.setY(rect.y() + rect.height() / 2); 606 const ThemeData& downThemeData = getThemeData(object, SpinButtonDown); 607 ThemePainter downPainter(info.context, half); 608 blink::WebCanvas* canvas = downPainter.context()->canvas(); 609 blink::Platform::current()->themeEngine()->paintSpinButton(canvas, downThemeData.m_part, downThemeData.m_state, downThemeData.m_classicState, blink::WebRect(downPainter.drawRect())); 610 } 611 return false; 612 } 613 614 // MSDN says that update intervals for the bar is 30ms. 615 // http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx 616 static const double progressAnimationFrameRate = 0.033; 617 618 double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const 619 { 620 return progressAnimationFrameRate; 621 } 622 623 double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const 624 { 625 // On Chromium Windows port, animationProgress() and associated values aren't used. 626 // So here we can return arbitrary positive value. 627 return progressAnimationFrameRate; 628 } 629 630 bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r) 631 { 632 if (!o->isProgress()) 633 return true; 634 635 RenderProgress* renderProgress = toRenderProgress(o); 636 // For indeterminate bar, valueRect is ignored and it is computed by the theme engine 637 // because the animation is a platform detail and WebKit doesn't need to know how. 638 IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0); 639 double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0; 640 ThemePainter painter(i.context, r); 641 DirectionFlippingScope scope(o, i, r); 642 blink::WebCanvas* canvas = painter.context()->canvas(); 643 blink::Platform::current()->themeEngine()->paintProgressBar(canvas, blink::WebRect(r), blink::WebRect(valueRect), renderProgress->isDeterminate(), animatedSeconds); 644 return false; 645 } 646 647 bool RenderThemeChromiumWin::shouldOpenPickerWithF4Key() const 648 { 649 return true; 650 } 651 652 bool RenderThemeChromiumWin::shouldUseFallbackTheme(RenderStyle* style) const 653 { 654 ControlPart part = style->appearance(); 655 if (part == CheckboxPart || part == RadioPart) 656 return style->effectiveZoom() != 1; 657 return false; 658 } 659 660 } // namespace WebCore 661