1 /** 2 * This file is part of the theme implementation for form controls in WebCore. 3 * 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 #include "core/rendering/RenderTheme.h" 24 25 #include "CSSValueKeywords.h" 26 #include "HTMLNames.h" 27 #include "RuntimeEnabledFeatures.h" 28 #include "core/dom/Document.h" 29 #include "core/dom/shadow/ElementShadow.h" 30 #include "core/editing/FrameSelection.h" 31 #include "core/fileapi/FileList.h" 32 #include "core/html/HTMLCollection.h" 33 #include "core/html/HTMLDataListElement.h" 34 #include "core/html/HTMLInputElement.h" 35 #include "core/html/HTMLMeterElement.h" 36 #include "core/html/HTMLOptionElement.h" 37 #include "core/html/InputTypeNames.h" 38 #include "core/html/parser/HTMLParserIdioms.h" 39 #include "core/html/shadow/MediaControlElements.h" 40 #include "core/html/shadow/SpinButtonElement.h" 41 #include "core/html/shadow/TextControlInnerElements.h" 42 #include "core/page/FocusController.h" 43 #include "core/page/Frame.h" 44 #include "core/page/Page.h" 45 #include "core/page/Settings.h" 46 #include "core/platform/FileSystem.h" 47 #include "core/platform/FloatConversion.h" 48 #include "core/platform/LocalizedStrings.h" 49 #include "core/platform/graphics/FontSelector.h" 50 #include "core/platform/graphics/GraphicsContextStateSaver.h" 51 #include "core/platform/graphics/StringTruncator.h" 52 #include "core/rendering/PaintInfo.h" 53 #include "core/rendering/RenderMeter.h" 54 #include "core/rendering/RenderView.h" 55 #include "core/rendering/style/RenderStyle.h" 56 #include "public/platform/Platform.h" 57 #include "public/platform/WebFallbackThemeEngine.h" 58 #include "public/platform/WebRect.h" 59 #include "wtf/text/StringBuilder.h" 60 61 #if ENABLE(INPUT_SPEECH) 62 #include "core/rendering/RenderInputSpeech.h" 63 #endif 64 65 // The methods in this file are shared by all themes on every platform. 66 67 namespace WebCore { 68 69 using namespace HTMLNames; 70 71 static StyleColor& customFocusRingColor() 72 { 73 DEFINE_STATIC_LOCAL(StyleColor, color, ()); 74 return color; 75 } 76 77 static WebKit::WebFallbackThemeEngine::State getWebFallbackThemeState(const RenderTheme* theme, const RenderObject* o) 78 { 79 if (!theme->isEnabled(o)) 80 return WebKit::WebFallbackThemeEngine::StateDisabled; 81 if (theme->isPressed(o)) 82 return WebKit::WebFallbackThemeEngine::StatePressed; 83 if (theme->isHovered(o)) 84 return WebKit::WebFallbackThemeEngine::StateHover; 85 86 return WebKit::WebFallbackThemeEngine::StateNormal; 87 } 88 89 RenderTheme::RenderTheme() 90 #if USE(NEW_THEME) 91 : m_theme(platformTheme()) 92 #endif 93 { 94 m_selectionColorsValid = 0; 95 } 96 97 void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyle& uaStyle) 98 { 99 // Force inline and table display styles to be inline-block (except for table- which is block) 100 ControlPart part = style->appearance(); 101 if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP 102 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP 103 || style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN 104 || style->display() == TABLE_CELL || style->display() == TABLE_CAPTION) 105 style->setDisplay(INLINE_BLOCK); 106 else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE) 107 style->setDisplay(BLOCK); 108 109 if (uaStyle.hasAppearance && isControlStyled(style, uaStyle)) { 110 if (part == MenulistPart) { 111 style->setAppearance(MenulistButtonPart); 112 part = MenulistButtonPart; 113 } else 114 style->setAppearance(NoControlPart); 115 } 116 117 if (!style->hasAppearance()) 118 return; 119 120 if (shouldUseFallbackTheme(style)) { 121 adjustStyleUsingFallbackTheme(style, e); 122 return; 123 } 124 125 #if USE(NEW_THEME) 126 switch (part) { 127 case CheckboxPart: 128 case InnerSpinButtonPart: 129 case RadioPart: 130 case PushButtonPart: 131 case SquareButtonPart: 132 case ButtonPart: { 133 // Border 134 LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth()); 135 borderBox = m_theme->controlBorder(part, style->font(), borderBox, style->effectiveZoom()); 136 if (borderBox.top().value() != static_cast<int>(style->borderTopWidth())) { 137 if (borderBox.top().value()) 138 style->setBorderTopWidth(borderBox.top().value()); 139 else 140 style->resetBorderTop(); 141 } 142 if (borderBox.right().value() != static_cast<int>(style->borderRightWidth())) { 143 if (borderBox.right().value()) 144 style->setBorderRightWidth(borderBox.right().value()); 145 else 146 style->resetBorderRight(); 147 } 148 if (borderBox.bottom().value() != static_cast<int>(style->borderBottomWidth())) { 149 style->setBorderBottomWidth(borderBox.bottom().value()); 150 if (borderBox.bottom().value()) 151 style->setBorderBottomWidth(borderBox.bottom().value()); 152 else 153 style->resetBorderBottom(); 154 } 155 if (borderBox.left().value() != static_cast<int>(style->borderLeftWidth())) { 156 style->setBorderLeftWidth(borderBox.left().value()); 157 if (borderBox.left().value()) 158 style->setBorderLeftWidth(borderBox.left().value()); 159 else 160 style->resetBorderLeft(); 161 } 162 163 // Padding 164 LengthBox paddingBox = m_theme->controlPadding(part, style->font(), style->paddingBox(), style->effectiveZoom()); 165 if (paddingBox != style->paddingBox()) 166 style->setPaddingBox(paddingBox); 167 168 // Whitespace 169 if (m_theme->controlRequiresPreWhiteSpace(part)) 170 style->setWhiteSpace(PRE); 171 172 // Width / Height 173 // The width and height here are affected by the zoom. 174 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. 175 LengthSize controlSize = m_theme->controlSize(part, style->font(), LengthSize(style->width(), style->height()), style->effectiveZoom()); 176 if (controlSize.width() != style->width()) 177 style->setWidth(controlSize.width()); 178 if (controlSize.height() != style->height()) 179 style->setHeight(controlSize.height()); 180 181 // Min-Width / Min-Height 182 LengthSize minControlSize = m_theme->minimumControlSize(part, style->font(), style->effectiveZoom()); 183 if (minControlSize.width() != style->minWidth()) 184 style->setMinWidth(minControlSize.width()); 185 if (minControlSize.height() != style->minHeight()) 186 style->setMinHeight(minControlSize.height()); 187 188 // Font 189 FontDescription controlFont = m_theme->controlFont(part, style->font(), style->effectiveZoom()); 190 if (controlFont != style->font().fontDescription()) { 191 // Reset our line-height 192 style->setLineHeight(RenderStyle::initialLineHeight()); 193 194 // Now update our font. 195 if (style->setFontDescription(controlFont)) 196 style->font().update(0); 197 } 198 } 199 default: 200 break; 201 } 202 #endif 203 204 // Call the appropriate style adjustment method based off the appearance value. 205 switch (style->appearance()) { 206 #if !USE(NEW_THEME) 207 case CheckboxPart: 208 return adjustCheckboxStyle(style, e); 209 case RadioPart: 210 return adjustRadioStyle(style, e); 211 case PushButtonPart: 212 case SquareButtonPart: 213 case ButtonPart: 214 return adjustButtonStyle(style, e); 215 case InnerSpinButtonPart: 216 return adjustInnerSpinButtonStyle(style, e); 217 #endif 218 case TextFieldPart: 219 return adjustTextFieldStyle(style, e); 220 case TextAreaPart: 221 return adjustTextAreaStyle(style, e); 222 case MenulistPart: 223 return adjustMenuListStyle(style, e); 224 case MenulistButtonPart: 225 return adjustMenuListButtonStyle(style, e); 226 case MediaPlayButtonPart: 227 case MediaCurrentTimePart: 228 case MediaTimeRemainingPart: 229 case MediaEnterFullscreenButtonPart: 230 case MediaExitFullscreenButtonPart: 231 case MediaMuteButtonPart: 232 case MediaVolumeSliderContainerPart: 233 return adjustMediaControlStyle(style, e); 234 case MediaSliderPart: 235 case MediaVolumeSliderPart: 236 case MediaFullScreenVolumeSliderPart: 237 case SliderHorizontalPart: 238 case SliderVerticalPart: 239 return adjustSliderTrackStyle(style, e); 240 case SliderThumbHorizontalPart: 241 case SliderThumbVerticalPart: 242 return adjustSliderThumbStyle(style, e); 243 case SearchFieldPart: 244 return adjustSearchFieldStyle(style, e); 245 case SearchFieldCancelButtonPart: 246 return adjustSearchFieldCancelButtonStyle(style, e); 247 case SearchFieldDecorationPart: 248 return adjustSearchFieldDecorationStyle(style, e); 249 case SearchFieldResultsDecorationPart: 250 return adjustSearchFieldResultsDecorationStyle(style, e); 251 case ProgressBarPart: 252 return adjustProgressBarStyle(style, e); 253 case MeterPart: 254 case RelevancyLevelIndicatorPart: 255 case ContinuousCapacityLevelIndicatorPart: 256 case DiscreteCapacityLevelIndicatorPart: 257 case RatingLevelIndicatorPart: 258 return adjustMeterStyle(style, e); 259 #if ENABLE(INPUT_SPEECH) 260 case InputSpeechButtonPart: 261 return adjustInputFieldSpeechButtonStyle(style, e); 262 #endif 263 default: 264 break; 265 } 266 } 267 268 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 269 { 270 // If painting is disabled, but we aren't updating control tints, then just bail. 271 // If we are updating control tints, just schedule a repaint if the theme supports tinting 272 // for that control. 273 if (paintInfo.context->updatingControlTints()) { 274 if (controlSupportsTints(o)) 275 o->repaint(); 276 return false; 277 } 278 if (paintInfo.context->paintingDisabled()) 279 return false; 280 281 ControlPart part = o->style()->appearance(); 282 283 if (shouldUseFallbackTheme(o->style())) 284 return paintUsingFallbackTheme(o, paintInfo, r); 285 286 #if USE(NEW_THEME) 287 switch (part) { 288 case CheckboxPart: 289 case RadioPart: 290 case PushButtonPart: 291 case SquareButtonPart: 292 case ButtonPart: 293 case InnerSpinButtonPart: 294 m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView()); 295 return false; 296 default: 297 break; 298 } 299 #endif 300 301 // Call the appropriate paint method based off the appearance value. 302 switch (part) { 303 #if !USE(NEW_THEME) 304 case CheckboxPart: 305 return paintCheckbox(o, paintInfo, r); 306 case RadioPart: 307 return paintRadio(o, paintInfo, r); 308 case PushButtonPart: 309 case SquareButtonPart: 310 case ButtonPart: 311 return paintButton(o, paintInfo, r); 312 case InnerSpinButtonPart: 313 return paintInnerSpinButton(o, paintInfo, r); 314 #endif 315 case MenulistPart: 316 return paintMenuList(o, paintInfo, r); 317 case MeterPart: 318 case RelevancyLevelIndicatorPart: 319 case ContinuousCapacityLevelIndicatorPart: 320 case DiscreteCapacityLevelIndicatorPart: 321 case RatingLevelIndicatorPart: 322 return paintMeter(o, paintInfo, r); 323 case ProgressBarPart: 324 return paintProgressBar(o, paintInfo, r); 325 case SliderHorizontalPart: 326 case SliderVerticalPart: 327 return paintSliderTrack(o, paintInfo, r); 328 case SliderThumbHorizontalPart: 329 case SliderThumbVerticalPart: 330 return paintSliderThumb(o, paintInfo, r); 331 case MediaEnterFullscreenButtonPart: 332 case MediaExitFullscreenButtonPart: 333 return paintMediaFullscreenButton(o, paintInfo, r); 334 case MediaPlayButtonPart: 335 return paintMediaPlayButton(o, paintInfo, r); 336 case MediaOverlayPlayButtonPart: 337 return paintMediaOverlayPlayButton(o, paintInfo, r); 338 case MediaMuteButtonPart: 339 return paintMediaMuteButton(o, paintInfo, r); 340 case MediaSeekBackButtonPart: 341 return paintMediaSeekBackButton(o, paintInfo, r); 342 case MediaSeekForwardButtonPart: 343 return paintMediaSeekForwardButton(o, paintInfo, r); 344 case MediaRewindButtonPart: 345 return paintMediaRewindButton(o, paintInfo, r); 346 case MediaReturnToRealtimeButtonPart: 347 return paintMediaReturnToRealtimeButton(o, paintInfo, r); 348 case MediaToggleClosedCaptionsButtonPart: 349 return paintMediaToggleClosedCaptionsButton(o, paintInfo, r); 350 case MediaSliderPart: 351 return paintMediaSliderTrack(o, paintInfo, r); 352 case MediaSliderThumbPart: 353 return paintMediaSliderThumb(o, paintInfo, r); 354 case MediaVolumeSliderMuteButtonPart: 355 return paintMediaMuteButton(o, paintInfo, r); 356 case MediaVolumeSliderContainerPart: 357 return paintMediaVolumeSliderContainer(o, paintInfo, r); 358 case MediaVolumeSliderPart: 359 return paintMediaVolumeSliderTrack(o, paintInfo, r); 360 case MediaVolumeSliderThumbPart: 361 return paintMediaVolumeSliderThumb(o, paintInfo, r); 362 case MediaFullScreenVolumeSliderPart: 363 return paintMediaFullScreenVolumeSliderTrack(o, paintInfo, r); 364 case MediaFullScreenVolumeSliderThumbPart: 365 return paintMediaFullScreenVolumeSliderThumb(o, paintInfo, r); 366 case MediaTimeRemainingPart: 367 return paintMediaTimeRemaining(o, paintInfo, r); 368 case MediaCurrentTimePart: 369 return paintMediaCurrentTime(o, paintInfo, r); 370 case MediaControlsBackgroundPart: 371 return paintMediaControlsBackground(o, paintInfo, r); 372 case MenulistButtonPart: 373 case TextFieldPart: 374 case TextAreaPart: 375 case ListboxPart: 376 return true; 377 case SearchFieldPart: 378 return paintSearchField(o, paintInfo, r); 379 case SearchFieldCancelButtonPart: 380 return paintSearchFieldCancelButton(o, paintInfo, r); 381 case SearchFieldDecorationPart: 382 return paintSearchFieldDecoration(o, paintInfo, r); 383 case SearchFieldResultsDecorationPart: 384 return paintSearchFieldResultsDecoration(o, paintInfo, r); 385 #if ENABLE(INPUT_SPEECH) 386 case InputSpeechButtonPart: 387 return paintInputFieldSpeechButton(o, paintInfo, r); 388 #endif 389 default: 390 break; 391 } 392 393 return true; // We don't support the appearance, so let the normal background/border paint. 394 } 395 396 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 397 { 398 if (paintInfo.context->paintingDisabled()) 399 return false; 400 401 // Call the appropriate paint method based off the appearance value. 402 switch (o->style()->appearance()) { 403 case TextFieldPart: 404 return paintTextField(o, paintInfo, r); 405 case ListboxPart: 406 case TextAreaPart: 407 return paintTextArea(o, paintInfo, r); 408 case MenulistButtonPart: 409 case SearchFieldPart: 410 return true; 411 case CheckboxPart: 412 case RadioPart: 413 case PushButtonPart: 414 case SquareButtonPart: 415 case ButtonPart: 416 case MenulistPart: 417 case MeterPart: 418 case RelevancyLevelIndicatorPart: 419 case ContinuousCapacityLevelIndicatorPart: 420 case DiscreteCapacityLevelIndicatorPart: 421 case RatingLevelIndicatorPart: 422 case ProgressBarPart: 423 case SliderHorizontalPart: 424 case SliderVerticalPart: 425 case SliderThumbHorizontalPart: 426 case SliderThumbVerticalPart: 427 case SearchFieldCancelButtonPart: 428 case SearchFieldDecorationPart: 429 case SearchFieldResultsDecorationPart: 430 #if ENABLE(INPUT_SPEECH) 431 case InputSpeechButtonPart: 432 #endif 433 default: 434 break; 435 } 436 437 return false; 438 } 439 440 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 441 { 442 if (paintInfo.context->paintingDisabled()) 443 return false; 444 445 // Call the appropriate paint method based off the appearance value. 446 switch (o->style()->appearance()) { 447 case MenulistButtonPart: 448 return paintMenuListButton(o, paintInfo, r); 449 case TextFieldPart: 450 case TextAreaPart: 451 case ListboxPart: 452 case CheckboxPart: 453 case RadioPart: 454 case PushButtonPart: 455 case SquareButtonPart: 456 case ButtonPart: 457 case MenulistPart: 458 case MeterPart: 459 case RelevancyLevelIndicatorPart: 460 case ContinuousCapacityLevelIndicatorPart: 461 case DiscreteCapacityLevelIndicatorPart: 462 case RatingLevelIndicatorPart: 463 case ProgressBarPart: 464 case SliderHorizontalPart: 465 case SliderVerticalPart: 466 case SliderThumbHorizontalPart: 467 case SliderThumbVerticalPart: 468 case SearchFieldPart: 469 case SearchFieldCancelButtonPart: 470 case SearchFieldDecorationPart: 471 case SearchFieldResultsDecorationPart: 472 #if ENABLE(INPUT_SPEECH) 473 case InputSpeechButtonPart: 474 #endif 475 default: 476 break; 477 } 478 479 return false; 480 } 481 482 String RenderTheme::extraDefaultStyleSheet() 483 { 484 if (!RuntimeEnabledFeatures::dataListElementEnabled() && !RuntimeEnabledFeatures::dialogElementEnabled()) 485 return String(); 486 StringBuilder runtimeCSS; 487 488 if (RuntimeEnabledFeatures::dataListElementEnabled()) { 489 runtimeCSS.appendLiteral("datalist {display: none ;}"); 490 491 if (RuntimeEnabledFeatures::inputTypeColorEnabled()) { 492 runtimeCSS.appendLiteral("input[type=\"color\"][list] { -webkit-appearance: menulist; width: 88px; height: 23px;}"); 493 runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch-wrapper { padding-left: 8px; padding-right: 24px;}"); 494 runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch { border-color: #000000;}"); 495 } 496 } 497 if (RuntimeEnabledFeatures::dialogElementEnabled()) { 498 runtimeCSS.appendLiteral("dialog:not([open]) { display: none; }"); 499 runtimeCSS.appendLiteral("dialog { position: absolute; left: 0; right: 0; margin: auto; border: solid; padding: 1em; background: white; color: black;}"); 500 runtimeCSS.appendLiteral("dialog::backdrop { background: rgba(0,0,0,0.1); }"); 501 } 502 503 return runtimeCSS.toString(); 504 } 505 506 String RenderTheme::formatMediaControlsTime(float time) const 507 { 508 if (!std::isfinite(time)) 509 time = 0; 510 int seconds = (int)fabsf(time); 511 int hours = seconds / (60 * 60); 512 int minutes = (seconds / 60) % 60; 513 seconds %= 60; 514 if (hours) { 515 if (hours > 9) 516 return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 517 518 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 519 } 520 521 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); 522 } 523 524 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const 525 { 526 return formatMediaControlsTime(currentTime); 527 } 528 529 namespace SelectionColors { 530 enum { 531 ActiveBackground = 1, 532 InactiveBackground = 2, 533 ActiveForeground = 4, 534 InactiveForeground = 8, 535 ActiveListBoxBackground = 16, 536 InactiveListBoxBackground = 32, 537 ActiveListBoxForeground = 64, 538 InactiveListBoxForeground = 128 539 }; 540 }; 541 542 Color RenderTheme::activeSelectionBackgroundColor() const 543 { 544 if (!(m_selectionColorsValid & SelectionColors::ActiveBackground)) { 545 m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite(); 546 m_selectionColorsValid |= SelectionColors::ActiveBackground; 547 } 548 return m_activeSelectionBackgroundColor; 549 } 550 551 Color RenderTheme::inactiveSelectionBackgroundColor() const 552 { 553 if (!(m_selectionColorsValid & SelectionColors::InactiveBackground)) { 554 m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite(); 555 m_selectionColorsValid |= SelectionColors::InactiveBackground; 556 } 557 return m_inactiveSelectionBackgroundColor; 558 } 559 560 Color RenderTheme::activeSelectionForegroundColor() const 561 { 562 if (!(m_selectionColorsValid & SelectionColors::ActiveForeground) && supportsSelectionForegroundColors()) { 563 m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor(); 564 m_selectionColorsValid |= SelectionColors::ActiveForeground; 565 } 566 return m_activeSelectionForegroundColor; 567 } 568 569 Color RenderTheme::inactiveSelectionForegroundColor() const 570 { 571 if (!(m_selectionColorsValid & SelectionColors::InactiveForeground) && supportsSelectionForegroundColors()) { 572 m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor(); 573 m_selectionColorsValid |= SelectionColors::InactiveForeground; 574 } 575 return m_inactiveSelectionForegroundColor; 576 } 577 578 Color RenderTheme::activeListBoxSelectionBackgroundColor() const 579 { 580 if (!(m_selectionColorsValid & SelectionColors::ActiveListBoxBackground)) { 581 m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor(); 582 m_selectionColorsValid |= SelectionColors::ActiveListBoxBackground; 583 } 584 return m_activeListBoxSelectionBackgroundColor; 585 } 586 587 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const 588 { 589 if (!(m_selectionColorsValid & SelectionColors::InactiveListBoxBackground)) { 590 m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor(); 591 m_selectionColorsValid |= SelectionColors::InactiveListBoxBackground; 592 } 593 return m_inactiveListBoxSelectionBackgroundColor; 594 } 595 596 Color RenderTheme::activeListBoxSelectionForegroundColor() const 597 { 598 if (!(m_selectionColorsValid & SelectionColors::ActiveListBoxForeground) && supportsListBoxSelectionForegroundColors()) { 599 m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor(); 600 m_selectionColorsValid |= SelectionColors::ActiveListBoxForeground; 601 } 602 return m_activeListBoxSelectionForegroundColor; 603 } 604 605 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const 606 { 607 if (!(m_selectionColorsValid & SelectionColors::InactiveListBoxForeground) && supportsListBoxSelectionForegroundColors()) { 608 m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor(); 609 m_selectionColorsValid |= SelectionColors::InactiveListBoxForeground; 610 } 611 return m_inactiveListBoxSelectionForegroundColor; 612 } 613 614 Color RenderTheme::platformActiveSelectionBackgroundColor() const 615 { 616 // Use a blue color by default if the platform theme doesn't define anything. 617 return Color(0, 0, 255); 618 } 619 620 Color RenderTheme::platformActiveSelectionForegroundColor() const 621 { 622 // Use a white color by default if the platform theme doesn't define anything. 623 return Color::white; 624 } 625 626 Color RenderTheme::platformInactiveSelectionBackgroundColor() const 627 { 628 // Use a grey color by default if the platform theme doesn't define anything. 629 // This color matches Firefox's inactive color. 630 return Color(176, 176, 176); 631 } 632 633 Color RenderTheme::platformInactiveSelectionForegroundColor() const 634 { 635 // Use a black color by default. 636 return Color::black; 637 } 638 639 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const 640 { 641 return platformActiveSelectionBackgroundColor(); 642 } 643 644 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const 645 { 646 return platformActiveSelectionForegroundColor(); 647 } 648 649 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const 650 { 651 return platformInactiveSelectionBackgroundColor(); 652 } 653 654 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const 655 { 656 return platformInactiveSelectionForegroundColor(); 657 } 658 659 int RenderTheme::baselinePosition(const RenderObject* o) const 660 { 661 if (!o->isBox()) 662 return 0; 663 664 const RenderBox* box = toRenderBox(o); 665 666 #if USE(NEW_THEME) 667 return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom(); 668 #else 669 return box->height() + box->marginTop(); 670 #endif 671 } 672 673 bool RenderTheme::isControlContainer(ControlPart appearance) const 674 { 675 // There are more leaves than this, but we'll patch this function as we add support for 676 // more controls. 677 return appearance != CheckboxPart && appearance != RadioPart; 678 } 679 680 static bool isBackgroundOrBorderStyled(const RenderStyle& style, const CachedUAStyle& uaStyle) 681 { 682 // Code below excludes the background-repeat from comparison by resetting it 683 FillLayer backgroundCopy = uaStyle.backgroundLayers; 684 FillLayer backgroundLayersCopy = *style.backgroundLayers(); 685 backgroundCopy.setRepeatX(NoRepeatFill); 686 backgroundCopy.setRepeatY(NoRepeatFill); 687 backgroundLayersCopy.setRepeatX(NoRepeatFill); 688 backgroundLayersCopy.setRepeatY(NoRepeatFill); 689 // Test the style to see if the UA border and background match. 690 return style.border() != uaStyle.border 691 || backgroundLayersCopy != backgroundCopy 692 || style.visitedDependentColor(CSSPropertyBackgroundColor).color() != uaStyle.backgroundColor; 693 } 694 695 bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle& uaStyle) const 696 { 697 switch (style->appearance()) { 698 case PushButtonPart: 699 case SquareButtonPart: 700 case ButtonPart: 701 case ProgressBarPart: 702 case MeterPart: 703 case RelevancyLevelIndicatorPart: 704 case ContinuousCapacityLevelIndicatorPart: 705 case DiscreteCapacityLevelIndicatorPart: 706 case RatingLevelIndicatorPart: 707 return isBackgroundOrBorderStyled(*style, uaStyle); 708 709 case ListboxPart: 710 case MenulistPart: 711 case SearchFieldPart: 712 case TextAreaPart: 713 case TextFieldPart: 714 return isBackgroundOrBorderStyled(*style, uaStyle) || style->boxShadow(); 715 716 case SliderHorizontalPart: 717 case SliderVerticalPart: 718 return style->boxShadow(); 719 720 default: 721 return false; 722 } 723 } 724 725 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r) 726 { 727 #if USE(NEW_THEME) 728 m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom()); 729 #else 730 UNUSED_PARAM(o); 731 UNUSED_PARAM(r); 732 #endif 733 } 734 735 bool RenderTheme::shouldDrawDefaultFocusRing(RenderObject* renderer) const 736 { 737 if (supportsFocusRing(renderer->style())) 738 return false; 739 if (!renderer->style()->hasAppearance()) 740 return true; 741 Node* node = renderer->node(); 742 if (!node) 743 return true; 744 // We can't use RenderTheme::isFocused because outline:auto might be 745 // specified to non-:focus rulesets. 746 if (node->focused() && !node->shouldHaveFocusAppearance()) 747 return false; 748 return true; 749 } 750 751 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const 752 { 753 return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart); 754 } 755 756 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const 757 { 758 // Default implementation assumes the controls don't respond to changes in :hover state 759 if (state == HoverState && !supportsHover(o->style())) 760 return false; 761 762 // Assume pressed state is only responded to if the control is enabled. 763 if (state == PressedState && !isEnabled(o)) 764 return false; 765 766 // Repaint the control. 767 o->repaint(); 768 return true; 769 } 770 771 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const 772 { 773 ControlStates result = 0; 774 if (isHovered(o)) { 775 result |= HoverState; 776 if (isSpinUpButtonPartHovered(o)) 777 result |= SpinUpState; 778 } 779 if (isPressed(o)) { 780 result |= PressedState; 781 if (isSpinUpButtonPartPressed(o)) 782 result |= SpinUpState; 783 } 784 if (isFocused(o) && o->style()->outlineStyleIsAuto()) 785 result |= FocusState; 786 if (isEnabled(o)) 787 result |= EnabledState; 788 if (isChecked(o)) 789 result |= CheckedState; 790 if (isReadOnlyControl(o)) 791 result |= ReadOnlyState; 792 if (!isActive(o)) 793 result |= WindowInactiveState; 794 if (isIndeterminate(o)) 795 result |= IndeterminateState; 796 return result; 797 } 798 799 bool RenderTheme::isActive(const RenderObject* o) const 800 { 801 Node* node = o->node(); 802 if (!node) 803 return false; 804 805 Page* page = node->document()->page(); 806 if (!page) 807 return false; 808 809 return page->focusController().isActive(); 810 } 811 812 bool RenderTheme::isChecked(const RenderObject* o) const 813 { 814 if (!o->node() || !o->node()->hasTagName(inputTag)) 815 return false; 816 return toHTMLInputElement(o->node())->shouldAppearChecked(); 817 } 818 819 bool RenderTheme::isIndeterminate(const RenderObject* o) const 820 { 821 if (!o->node() || !o->node()->hasTagName(inputTag)) 822 return false; 823 return toHTMLInputElement(o->node())->shouldAppearIndeterminate(); 824 } 825 826 bool RenderTheme::isEnabled(const RenderObject* o) const 827 { 828 Node* node = o->node(); 829 if (!node || !node->isElementNode()) 830 return true; 831 return !toElement(node)->isDisabledFormControl(); 832 } 833 834 bool RenderTheme::isFocused(const RenderObject* o) const 835 { 836 Node* node = o->node(); 837 if (!node) 838 return false; 839 840 node = node->focusDelegate(); 841 Document* document = node->document(); 842 Frame* frame = document->frame(); 843 return node == document->focusedElement() && node->shouldHaveFocusAppearance() && frame && frame->selection()->isFocusedAndActive(); 844 } 845 846 bool RenderTheme::isPressed(const RenderObject* o) const 847 { 848 if (!o->node()) 849 return false; 850 return o->node()->active(); 851 } 852 853 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const 854 { 855 Node* node = o->node(); 856 if (!node || !node->active() || !node->isElementNode() 857 || !toElement(node)->isSpinButtonElement()) 858 return false; 859 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 860 return element->upDownState() == SpinButtonElement::Up; 861 } 862 863 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const 864 { 865 Node* node = o->node(); 866 if (!node || !node->isElementNode()) 867 return false; 868 return toElement(node)->matchesReadOnlyPseudoClass(); 869 } 870 871 bool RenderTheme::isHovered(const RenderObject* o) const 872 { 873 Node* node = o->node(); 874 if (!node) 875 return false; 876 if (!node->isElementNode() || !toElement(node)->isSpinButtonElement()) 877 return node->hovered(); 878 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 879 return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate; 880 } 881 882 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const 883 { 884 Node* node = o->node(); 885 if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement()) 886 return false; 887 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 888 return element->upDownState() == SpinButtonElement::Up; 889 } 890 891 #if !USE(NEW_THEME) 892 893 void RenderTheme::adjustCheckboxStyle(RenderStyle* style, Element*) const 894 { 895 // A summary of the rules for checkbox designed to match WinIE: 896 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 897 // font-size - not honored (control has no text), but we use it to decide which control size to use. 898 setCheckboxSize(style); 899 900 // padding - not honored by WinIE, needs to be removed. 901 style->resetPadding(); 902 903 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 904 // for now, we will not honor it. 905 style->resetBorder(); 906 } 907 908 void RenderTheme::adjustRadioStyle(RenderStyle* style, Element*) const 909 { 910 // A summary of the rules for checkbox designed to match WinIE: 911 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 912 // font-size - not honored (control has no text), but we use it to decide which control size to use. 913 setRadioSize(style); 914 915 // padding - not honored by WinIE, needs to be removed. 916 style->resetPadding(); 917 918 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 919 // for now, we will not honor it. 920 style->resetBorder(); 921 } 922 923 void RenderTheme::adjustButtonStyle(RenderStyle* style, Element*) const 924 { 925 // Most platforms will completely honor all CSS, and so we have no need to 926 // adjust the style at all by default. We will still allow the theme a crack 927 // at setting up a desired vertical size. 928 setButtonSize(style); 929 } 930 931 void RenderTheme::adjustInnerSpinButtonStyle(RenderStyle*, Element*) const 932 { 933 } 934 #endif 935 936 void RenderTheme::adjustTextFieldStyle(RenderStyle*, Element*) const 937 { 938 } 939 940 void RenderTheme::adjustTextAreaStyle(RenderStyle*, Element*) const 941 { 942 } 943 944 void RenderTheme::adjustMenuListStyle(RenderStyle*, Element*) const 945 { 946 } 947 948 #if ENABLE(INPUT_SPEECH) 949 void RenderTheme::adjustInputFieldSpeechButtonStyle(RenderStyle* style, Element* element) const 950 { 951 RenderInputSpeech::adjustInputFieldSpeechButtonStyle(style, element); 952 } 953 954 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 955 { 956 return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect); 957 } 958 #endif 959 960 void RenderTheme::adjustMeterStyle(RenderStyle* style, Element*) const 961 { 962 } 963 964 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const 965 { 966 return bounds.size(); 967 } 968 969 bool RenderTheme::supportsMeter(ControlPart) const 970 { 971 return false; 972 } 973 974 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&) 975 { 976 return true; 977 } 978 979 LayoutUnit RenderTheme::sliderTickSnappingThreshold() const 980 { 981 return 5; 982 } 983 984 void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) 985 { 986 Node* node = o->node(); 987 if (!node || !node->hasTagName(inputTag)) 988 return; 989 990 HTMLInputElement* input = toHTMLInputElement(node); 991 HTMLDataListElement* dataList = input->dataList(); 992 if (!dataList) 993 return; 994 995 double min = input->minimum(); 996 double max = input->maximum(); 997 ControlPart part = o->style()->appearance(); 998 // We don't support ticks on alternate sliders like MediaVolumeSliders. 999 if (part != SliderHorizontalPart && part != SliderVerticalPart) 1000 return; 1001 bool isHorizontal = part == SliderHorizontalPart; 1002 1003 IntSize thumbSize; 1004 RenderObject* thumbRenderer = input->sliderThumbElement()->renderer(); 1005 if (thumbRenderer) { 1006 RenderStyle* thumbStyle = thumbRenderer->style(); 1007 int thumbWidth = thumbStyle->width().intValue(); 1008 int thumbHeight = thumbStyle->height().intValue(); 1009 thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight); 1010 thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth); 1011 } 1012 1013 IntSize tickSize = sliderTickSize(); 1014 float zoomFactor = o->style()->effectiveZoom(); 1015 FloatRect tickRect; 1016 int tickRegionSideMargin = 0; 1017 int tickRegionWidth = 0; 1018 IntRect trackBounds; 1019 RenderObject* trackRenderer = input->sliderTrackElement()->renderer(); 1020 // We can ignoring transforms because transform is handled by the graphics context. 1021 if (trackRenderer) 1022 trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms(); 1023 IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms(); 1024 1025 // Make position relative to the transformed ancestor element. 1026 trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x()); 1027 trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y()); 1028 1029 if (isHorizontal) { 1030 tickRect.setWidth(floor(tickSize.width() * zoomFactor)); 1031 tickRect.setHeight(floor(tickSize.height() * zoomFactor)); 1032 tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); 1033 tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; 1034 tickRegionWidth = trackBounds.width() - thumbSize.width(); 1035 } else { 1036 tickRect.setWidth(floor(tickSize.height() * zoomFactor)); 1037 tickRect.setHeight(floor(tickSize.width() * zoomFactor)); 1038 tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); 1039 tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; 1040 tickRegionWidth = trackBounds.height() - thumbSize.width(); 1041 } 1042 RefPtr<HTMLCollection> options = dataList->options(); 1043 GraphicsContextStateSaver stateSaver(*paintInfo.context); 1044 paintInfo.context->setFillColor(o->resolveColor(CSSPropertyColor)); 1045 for (unsigned i = 0; Node* node = options->item(i); i++) { 1046 ASSERT(node->hasTagName(optionTag)); 1047 HTMLOptionElement* optionElement = toHTMLOptionElement(node); 1048 String value = optionElement->value(); 1049 if (!input->isValidValue(value)) 1050 continue; 1051 double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); 1052 double tickFraction = (parsedValue - min) / (max - min); 1053 double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; 1054 double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); 1055 if (isHorizontal) 1056 tickRect.setX(tickPosition); 1057 else 1058 tickRect.setY(tickPosition); 1059 paintInfo.context->fillRect(tickRect); 1060 } 1061 } 1062 1063 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const 1064 { 1065 return 0; 1066 } 1067 1068 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const 1069 { 1070 return 0; 1071 } 1072 1073 void RenderTheme::adjustProgressBarStyle(RenderStyle*, Element*) const 1074 { 1075 } 1076 1077 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const 1078 { 1079 return inputElement->isSteppable() && !inputElement->isRangeControl(); 1080 } 1081 1082 void RenderTheme::adjustMenuListButtonStyle(RenderStyle*, Element*) const 1083 { 1084 } 1085 1086 void RenderTheme::adjustMediaControlStyle(RenderStyle*, Element*) const 1087 { 1088 } 1089 1090 void RenderTheme::adjustSliderTrackStyle(RenderStyle*, Element*) const 1091 { 1092 } 1093 1094 void RenderTheme::adjustSliderThumbStyle(RenderStyle* style, Element* element) const 1095 { 1096 adjustSliderThumbSize(style, element); 1097 } 1098 1099 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const 1100 { 1101 } 1102 1103 void RenderTheme::adjustSearchFieldStyle(RenderStyle*, Element*) const 1104 { 1105 } 1106 1107 void RenderTheme::adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const 1108 { 1109 } 1110 1111 void RenderTheme::adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const 1112 { 1113 } 1114 1115 void RenderTheme::adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const 1116 { 1117 } 1118 1119 void RenderTheme::platformColorsDidChange() 1120 { 1121 m_selectionColorsValid = 0; 1122 Page::scheduleForcedStyleRecalcForAllPages(); 1123 } 1124 1125 Color RenderTheme::systemColor(CSSValueID cssValueId) const 1126 { 1127 switch (cssValueId) { 1128 case CSSValueActiveborder: 1129 return 0xFFFFFFFF; 1130 case CSSValueActivecaption: 1131 return 0xFFCCCCCC; 1132 case CSSValueAppworkspace: 1133 return 0xFFFFFFFF; 1134 case CSSValueBackground: 1135 return 0xFF6363CE; 1136 case CSSValueButtonface: 1137 return 0xFFC0C0C0; 1138 case CSSValueButtonhighlight: 1139 return 0xFFDDDDDD; 1140 case CSSValueButtonshadow: 1141 return 0xFF888888; 1142 case CSSValueButtontext: 1143 return 0xFF000000; 1144 case CSSValueCaptiontext: 1145 return 0xFF000000; 1146 case CSSValueGraytext: 1147 return 0xFF808080; 1148 case CSSValueHighlight: 1149 return 0xFFB5D5FF; 1150 case CSSValueHighlighttext: 1151 return 0xFF000000; 1152 case CSSValueInactiveborder: 1153 return 0xFFFFFFFF; 1154 case CSSValueInactivecaption: 1155 return 0xFFFFFFFF; 1156 case CSSValueInactivecaptiontext: 1157 return 0xFF7F7F7F; 1158 case CSSValueInfobackground: 1159 return 0xFFFBFCC5; 1160 case CSSValueInfotext: 1161 return 0xFF000000; 1162 case CSSValueMenu: 1163 return 0xFFC0C0C0; 1164 case CSSValueMenutext: 1165 return 0xFF000000; 1166 case CSSValueScrollbar: 1167 return 0xFFFFFFFF; 1168 case CSSValueText: 1169 return 0xFF000000; 1170 case CSSValueThreeddarkshadow: 1171 return 0xFF666666; 1172 case CSSValueThreedface: 1173 return 0xFFC0C0C0; 1174 case CSSValueThreedhighlight: 1175 return 0xFFDDDDDD; 1176 case CSSValueThreedlightshadow: 1177 return 0xFFC0C0C0; 1178 case CSSValueThreedshadow: 1179 return 0xFF888888; 1180 case CSSValueWindow: 1181 return 0xFFFFFFFF; 1182 case CSSValueWindowframe: 1183 return 0xFFCCCCCC; 1184 case CSSValueWindowtext: 1185 return 0xFF000000; 1186 case CSSValueInternalActiveListBoxSelection: 1187 return activeListBoxSelectionBackgroundColor(); 1188 break; 1189 case CSSValueInternalActiveListBoxSelectionText: 1190 return activeListBoxSelectionForegroundColor(); 1191 break; 1192 case CSSValueInternalInactiveListBoxSelection: 1193 return inactiveListBoxSelectionBackgroundColor(); 1194 break; 1195 case CSSValueInternalInactiveListBoxSelectionText: 1196 return inactiveListBoxSelectionForegroundColor(); 1197 break; 1198 default: 1199 break; 1200 } 1201 return Color(); 1202 } 1203 1204 Color RenderTheme::platformActiveTextSearchHighlightColor() const 1205 { 1206 return Color(255, 150, 50); // Orange. 1207 } 1208 1209 Color RenderTheme::platformInactiveTextSearchHighlightColor() const 1210 { 1211 return Color(255, 255, 0); // Yellow. 1212 } 1213 1214 Color RenderTheme::tapHighlightColor() 1215 { 1216 return defaultTheme()->platformTapHighlightColor(); 1217 } 1218 1219 void RenderTheme::setCustomFocusRingColor(const Color& c) 1220 { 1221 customFocusRingColor() = c; 1222 } 1223 1224 Color RenderTheme::focusRingColor() 1225 { 1226 return customFocusRingColor().isValid() ? customFocusRingColor().color() : defaultTheme()->platformFocusRingColor(); 1227 } 1228 1229 String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const 1230 { 1231 if (multipleFilesAllowed) 1232 return fileButtonNoFilesSelectedLabel(); 1233 return fileButtonNoFileSelectedLabel(); 1234 } 1235 1236 String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const 1237 { 1238 if (width <= 0) 1239 return String(); 1240 1241 String string; 1242 if (fileList->isEmpty()) 1243 string = fileListDefaultLabel(multipleFilesAllowed); 1244 else if (fileList->length() == 1) 1245 string = fileList->item(0)->name(); 1246 else 1247 return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks); 1248 1249 return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks); 1250 } 1251 1252 bool RenderTheme::shouldOpenPickerWithF4Key() const 1253 { 1254 return false; 1255 } 1256 1257 bool RenderTheme::supportsDataListUI(const AtomicString& type) const 1258 { 1259 return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url() 1260 || type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number() 1261 || type == InputTypeNames::color() 1262 || type == InputTypeNames::date() 1263 || type == InputTypeNames::datetime() 1264 || type == InputTypeNames::datetimelocal() 1265 || type == InputTypeNames::month() 1266 || type == InputTypeNames::week() 1267 || type == InputTypeNames::time() 1268 || type == InputTypeNames::range(); 1269 } 1270 1271 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 1272 bool RenderTheme::supportsCalendarPicker(const AtomicString& type) const 1273 { 1274 return type == InputTypeNames::date() 1275 || type == InputTypeNames::datetime() 1276 || type == InputTypeNames::datetimelocal() 1277 || type == InputTypeNames::month() 1278 || type == InputTypeNames::week(); 1279 } 1280 #endif 1281 1282 bool RenderTheme::shouldUseFallbackTheme(RenderStyle*) const 1283 { 1284 return false; 1285 } 1286 1287 void RenderTheme::adjustStyleUsingFallbackTheme(RenderStyle* style, Element* e) 1288 { 1289 ControlPart part = style->appearance(); 1290 switch (part) { 1291 case CheckboxPart: 1292 return adjustCheckboxStyleUsingFallbackTheme(style, e); 1293 case RadioPart: 1294 return adjustRadioStyleUsingFallbackTheme(style, e); 1295 default: 1296 break; 1297 } 1298 } 1299 1300 bool RenderTheme::paintUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1301 { 1302 ControlPart part = o->style()->appearance(); 1303 switch (part) { 1304 case CheckboxPart: 1305 return paintCheckboxUsingFallbackTheme(o, i, r); 1306 case RadioPart: 1307 return paintRadioUsingFallbackTheme(o, i, r); 1308 default: 1309 break; 1310 } 1311 return true; 1312 } 1313 1314 // static 1315 void RenderTheme::setSizeIfAuto(RenderStyle* style, const IntSize& size) 1316 { 1317 if (style->width().isIntrinsicOrAuto()) 1318 style->setWidth(Length(size.width(), Fixed)); 1319 if (style->height().isAuto()) 1320 style->setHeight(Length(size.height(), Fixed)); 1321 } 1322 1323 bool RenderTheme::paintCheckboxUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1324 { 1325 WebKit::WebFallbackThemeEngine::ExtraParams extraParams; 1326 WebKit::WebCanvas* canvas = i.context->canvas(); 1327 extraParams.button.checked = isChecked(o); 1328 extraParams.button.indeterminate = isIndeterminate(o); 1329 1330 float zoomLevel = o->style()->effectiveZoom(); 1331 GraphicsContextStateSaver stateSaver(*i.context); 1332 IntRect unzoomedRect = r; 1333 if (zoomLevel != 1) { 1334 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1335 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1336 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1337 i.context->scale(FloatSize(zoomLevel, zoomLevel)); 1338 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1339 } 1340 1341 WebKit::Platform::current()->fallbackThemeEngine()->paint(canvas, WebKit::WebFallbackThemeEngine::PartCheckbox, getWebFallbackThemeState(this, o), WebKit::WebRect(unzoomedRect), &extraParams); 1342 return false; 1343 } 1344 1345 void RenderTheme::adjustCheckboxStyleUsingFallbackTheme(RenderStyle* style, Element*) const 1346 { 1347 // If the width and height are both specified, then we have nothing to do. 1348 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1349 return; 1350 1351 IntSize size = WebKit::Platform::current()->fallbackThemeEngine()->getSize(WebKit::WebFallbackThemeEngine::PartCheckbox); 1352 float zoomLevel = style->effectiveZoom(); 1353 size.setWidth(size.width() * zoomLevel); 1354 size.setHeight(size.height() * zoomLevel); 1355 setSizeIfAuto(style, size); 1356 1357 // padding - not honored by WinIE, needs to be removed. 1358 style->resetPadding(); 1359 1360 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 1361 // for now, we will not honor it. 1362 style->resetBorder(); 1363 } 1364 1365 bool RenderTheme::paintRadioUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1366 { 1367 WebKit::WebFallbackThemeEngine::ExtraParams extraParams; 1368 WebKit::WebCanvas* canvas = i.context->canvas(); 1369 extraParams.button.checked = isChecked(o); 1370 extraParams.button.indeterminate = isIndeterminate(o); 1371 1372 float zoomLevel = o->style()->effectiveZoom(); 1373 GraphicsContextStateSaver stateSaver(*i.context); 1374 IntRect unzoomedRect = r; 1375 if (zoomLevel != 1) { 1376 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1377 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1378 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1379 i.context->scale(FloatSize(zoomLevel, zoomLevel)); 1380 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1381 } 1382 1383 WebKit::Platform::current()->fallbackThemeEngine()->paint(canvas, WebKit::WebFallbackThemeEngine::PartRadio, getWebFallbackThemeState(this, o), WebKit::WebRect(unzoomedRect), &extraParams); 1384 return false; 1385 } 1386 1387 void RenderTheme::adjustRadioStyleUsingFallbackTheme(RenderStyle* style, Element*) const 1388 { 1389 // If the width and height are both specified, then we have nothing to do. 1390 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1391 return; 1392 1393 IntSize size = WebKit::Platform::current()->fallbackThemeEngine()->getSize(WebKit::WebFallbackThemeEngine::PartRadio); 1394 float zoomLevel = style->effectiveZoom(); 1395 size.setWidth(size.width() * zoomLevel); 1396 size.setHeight(size.height() * zoomLevel); 1397 setSizeIfAuto(style, size); 1398 1399 // padding - not honored by WinIE, needs to be removed. 1400 style->resetPadding(); 1401 1402 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 1403 // for now, we will not honor it. 1404 style->resetBorder(); 1405 } 1406 1407 } // namespace WebCore 1408