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 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 "RenderTheme.h" 24 25 #include "CSSValueKeywords.h" 26 #include "Document.h" 27 #include "FloatConversion.h" 28 #include "FocusController.h" 29 #include "FontSelector.h" 30 #include "Frame.h" 31 #include "GraphicsContext.h" 32 #include "HTMLInputElement.h" 33 #include "HTMLNames.h" 34 #include "MediaControlElements.h" 35 #include "Page.h" 36 #include "PaintInfo.h" 37 #include "RenderStyle.h" 38 #include "RenderView.h" 39 #include "SelectionController.h" 40 #include "Settings.h" 41 #include "TextControlInnerElements.h" 42 43 #if ENABLE(METER_TAG) 44 #include "HTMLMeterElement.h" 45 #include "RenderMeter.h" 46 #endif 47 48 #if ENABLE(INPUT_SPEECH) 49 #include "RenderInputSpeech.h" 50 #endif 51 52 // The methods in this file are shared by all themes on every platform. 53 54 namespace WebCore { 55 56 using namespace HTMLNames; 57 58 static Color& customFocusRingColor() 59 { 60 DEFINE_STATIC_LOCAL(Color, color, ()); 61 return color; 62 } 63 64 RenderTheme::RenderTheme() 65 #if USE(NEW_THEME) 66 : m_theme(platformTheme()) 67 #endif 68 { 69 } 70 71 void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e, 72 bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor) 73 { 74 // Force inline and table display styles to be inline-block (except for table- which is block) 75 ControlPart part = style->appearance(); 76 if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP || 77 style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP || 78 style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN || 79 style->display() == TABLE_CELL || style->display() == TABLE_CAPTION) 80 style->setDisplay(INLINE_BLOCK); 81 else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE) 82 style->setDisplay(BLOCK); 83 84 if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) { 85 if (part == MenulistPart) { 86 style->setAppearance(MenulistButtonPart); 87 part = MenulistButtonPart; 88 } else 89 style->setAppearance(NoControlPart); 90 } 91 92 if (!style->hasAppearance()) 93 return; 94 95 // Never support box-shadow on native controls. 96 style->setBoxShadow(0); 97 98 #if USE(NEW_THEME) 99 switch (part) { 100 case ListButtonPart: 101 case CheckboxPart: 102 case InnerSpinButtonPart: 103 case OuterSpinButtonPart: 104 case RadioPart: 105 case PushButtonPart: 106 case SquareButtonPart: 107 case DefaultButtonPart: 108 case ButtonPart: { 109 // Border 110 LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth()); 111 borderBox = m_theme->controlBorder(part, style->font(), borderBox, style->effectiveZoom()); 112 if (borderBox.top().value() != style->borderTopWidth()) { 113 if (borderBox.top().value()) 114 style->setBorderTopWidth(borderBox.top().value()); 115 else 116 style->resetBorderTop(); 117 } 118 if (borderBox.right().value() != style->borderRightWidth()) { 119 if (borderBox.right().value()) 120 style->setBorderRightWidth(borderBox.right().value()); 121 else 122 style->resetBorderRight(); 123 } 124 if (borderBox.bottom().value() != style->borderBottomWidth()) { 125 style->setBorderBottomWidth(borderBox.bottom().value()); 126 if (borderBox.bottom().value()) 127 style->setBorderBottomWidth(borderBox.bottom().value()); 128 else 129 style->resetBorderBottom(); 130 } 131 if (borderBox.left().value() != style->borderLeftWidth()) { 132 style->setBorderLeftWidth(borderBox.left().value()); 133 if (borderBox.left().value()) 134 style->setBorderLeftWidth(borderBox.left().value()); 135 else 136 style->resetBorderLeft(); 137 } 138 139 // Padding 140 LengthBox paddingBox = m_theme->controlPadding(part, style->font(), style->paddingBox(), style->effectiveZoom()); 141 if (paddingBox != style->paddingBox()) 142 style->setPaddingBox(paddingBox); 143 144 // Whitespace 145 if (m_theme->controlRequiresPreWhiteSpace(part)) 146 style->setWhiteSpace(PRE); 147 148 // Width / Height 149 // The width and height here are affected by the zoom. 150 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. 151 LengthSize controlSize = m_theme->controlSize(part, style->font(), LengthSize(style->width(), style->height()), style->effectiveZoom()); 152 if (controlSize.width() != style->width()) 153 style->setWidth(controlSize.width()); 154 if (controlSize.height() != style->height()) 155 style->setHeight(controlSize.height()); 156 157 // Min-Width / Min-Height 158 LengthSize minControlSize = m_theme->minimumControlSize(part, style->font(), style->effectiveZoom()); 159 if (minControlSize.width() != style->minWidth()) 160 style->setMinWidth(minControlSize.width()); 161 if (minControlSize.height() != style->minHeight()) 162 style->setMinHeight(minControlSize.height()); 163 164 // Font 165 FontDescription controlFont = m_theme->controlFont(part, style->font(), style->effectiveZoom()); 166 if (controlFont != style->font().fontDescription()) { 167 // Reset our line-height 168 style->setLineHeight(RenderStyle::initialLineHeight()); 169 170 // Now update our font. 171 if (style->setFontDescription(controlFont)) 172 style->font().update(0); 173 } 174 } 175 default: 176 break; 177 } 178 #endif 179 180 // Call the appropriate style adjustment method based off the appearance value. 181 switch (style->appearance()) { 182 #if !USE(NEW_THEME) 183 case CheckboxPart: 184 return adjustCheckboxStyle(selector, style, e); 185 case RadioPart: 186 return adjustRadioStyle(selector, style, e); 187 case PushButtonPart: 188 case SquareButtonPart: 189 case ListButtonPart: 190 case DefaultButtonPart: 191 case ButtonPart: 192 return adjustButtonStyle(selector, style, e); 193 case InnerSpinButtonPart: 194 return adjustInnerSpinButtonStyle(selector, style, e); 195 case OuterSpinButtonPart: 196 return adjustOuterSpinButtonStyle(selector, style, e); 197 #endif 198 case TextFieldPart: 199 return adjustTextFieldStyle(selector, style, e); 200 case TextAreaPart: 201 return adjustTextAreaStyle(selector, style, e); 202 #if ENABLE(NO_LISTBOX_RENDERING) 203 case ListboxPart: 204 return adjustListboxStyle(selector, style, e); 205 #endif 206 case MenulistPart: 207 return adjustMenuListStyle(selector, style, e); 208 case MenulistButtonPart: 209 return adjustMenuListButtonStyle(selector, style, e); 210 case MediaSliderPart: 211 case MediaVolumeSliderPart: 212 case SliderHorizontalPart: 213 case SliderVerticalPart: 214 return adjustSliderTrackStyle(selector, style, e); 215 case SliderThumbHorizontalPart: 216 case SliderThumbVerticalPart: 217 return adjustSliderThumbStyle(selector, style, e); 218 case SearchFieldPart: 219 return adjustSearchFieldStyle(selector, style, e); 220 case SearchFieldCancelButtonPart: 221 return adjustSearchFieldCancelButtonStyle(selector, style, e); 222 case SearchFieldDecorationPart: 223 return adjustSearchFieldDecorationStyle(selector, style, e); 224 case SearchFieldResultsDecorationPart: 225 return adjustSearchFieldResultsDecorationStyle(selector, style, e); 226 case SearchFieldResultsButtonPart: 227 return adjustSearchFieldResultsButtonStyle(selector, style, e); 228 #if ENABLE(PROGRESS_TAG) 229 case ProgressBarPart: 230 return adjustProgressBarStyle(selector, style, e); 231 #endif 232 #if ENABLE(METER_TAG) 233 case MeterPart: 234 case RelevancyLevelIndicatorPart: 235 case ContinuousCapacityLevelIndicatorPart: 236 case DiscreteCapacityLevelIndicatorPart: 237 case RatingLevelIndicatorPart: 238 return adjustMeterStyle(selector, style, e); 239 #endif 240 #if ENABLE(INPUT_SPEECH) 241 case InputSpeechButtonPart: 242 return adjustInputFieldSpeechButtonStyle(selector, style, e); 243 #endif 244 default: 245 break; 246 } 247 } 248 249 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 250 { 251 // If painting is disabled, but we aren't updating control tints, then just bail. 252 // If we are updating control tints, just schedule a repaint if the theme supports tinting 253 // for that control. 254 if (paintInfo.context->updatingControlTints()) { 255 if (controlSupportsTints(o)) 256 o->repaint(); 257 return false; 258 } 259 if (paintInfo.context->paintingDisabled()) 260 return false; 261 262 ControlPart part = o->style()->appearance(); 263 264 #if USE(NEW_THEME) 265 switch (part) { 266 case CheckboxPart: 267 case RadioPart: 268 case PushButtonPart: 269 case SquareButtonPart: 270 case ListButtonPart: 271 case DefaultButtonPart: 272 case ButtonPart: 273 case InnerSpinButtonPart: 274 case OuterSpinButtonPart: 275 m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView()); 276 return false; 277 default: 278 break; 279 } 280 #endif 281 282 // Call the appropriate paint method based off the appearance value. 283 switch (part) { 284 #if !USE(NEW_THEME) 285 case CheckboxPart: 286 return paintCheckbox(o, paintInfo, r); 287 case RadioPart: 288 return paintRadio(o, paintInfo, r); 289 case PushButtonPart: 290 case SquareButtonPart: 291 case ListButtonPart: 292 case DefaultButtonPart: 293 case ButtonPart: 294 return paintButton(o, paintInfo, r); 295 case InnerSpinButtonPart: 296 return paintInnerSpinButton(o, paintInfo, r); 297 case OuterSpinButtonPart: 298 return paintOuterSpinButton(o, paintInfo, r); 299 #endif 300 case MenulistPart: 301 return paintMenuList(o, paintInfo, r); 302 #if ENABLE(METER_TAG) 303 case MeterPart: 304 case RelevancyLevelIndicatorPart: 305 case ContinuousCapacityLevelIndicatorPart: 306 case DiscreteCapacityLevelIndicatorPart: 307 case RatingLevelIndicatorPart: 308 return paintMeter(o, paintInfo, r); 309 #endif 310 #if ENABLE(PROGRESS_TAG) 311 case ProgressBarPart: 312 return paintProgressBar(o, paintInfo, r); 313 #endif 314 case SliderHorizontalPart: 315 case SliderVerticalPart: 316 return paintSliderTrack(o, paintInfo, r); 317 case SliderThumbHorizontalPart: 318 case SliderThumbVerticalPart: 319 if (o->parent()->isSlider()) 320 return paintSliderThumb(o, paintInfo, r); 321 // We don't support drawing a slider thumb without a parent slider 322 break; 323 case MediaFullscreenButtonPart: 324 return paintMediaFullscreenButton(o, paintInfo, r); 325 case MediaPlayButtonPart: 326 return paintMediaPlayButton(o, paintInfo, r); 327 case MediaMuteButtonPart: 328 return paintMediaMuteButton(o, paintInfo, r); 329 case MediaSeekBackButtonPart: 330 return paintMediaSeekBackButton(o, paintInfo, r); 331 case MediaSeekForwardButtonPart: 332 return paintMediaSeekForwardButton(o, paintInfo, r); 333 case MediaRewindButtonPart: 334 return paintMediaRewindButton(o, paintInfo, r); 335 case MediaReturnToRealtimeButtonPart: 336 return paintMediaReturnToRealtimeButton(o, paintInfo, r); 337 case MediaToggleClosedCaptionsButtonPart: 338 return paintMediaToggleClosedCaptionsButton(o, paintInfo, r); 339 case MediaSliderPart: 340 return paintMediaSliderTrack(o, paintInfo, r); 341 case MediaSliderThumbPart: 342 if (o->parent()->isSlider()) 343 return paintMediaSliderThumb(o, paintInfo, r); 344 break; 345 case MediaVolumeSliderMuteButtonPart: 346 return paintMediaMuteButton(o, paintInfo, r); 347 case MediaVolumeSliderContainerPart: 348 return paintMediaVolumeSliderContainer(o, paintInfo, r); 349 case MediaVolumeSliderPart: 350 return paintMediaVolumeSliderTrack(o, paintInfo, r); 351 case MediaVolumeSliderThumbPart: 352 if (o->parent()->isSlider()) 353 return paintMediaVolumeSliderThumb(o, paintInfo, r); 354 break; 355 case MediaTimeRemainingPart: 356 return paintMediaTimeRemaining(o, paintInfo, r); 357 case MediaCurrentTimePart: 358 return paintMediaCurrentTime(o, paintInfo, r); 359 case MediaControlsBackgroundPart: 360 return paintMediaControlsBackground(o, paintInfo, r); 361 case MenulistButtonPart: 362 case TextFieldPart: 363 case TextAreaPart: 364 case ListboxPart: 365 return true; 366 case SearchFieldPart: 367 return paintSearchField(o, paintInfo, r); 368 case SearchFieldCancelButtonPart: 369 return paintSearchFieldCancelButton(o, paintInfo, r); 370 case SearchFieldDecorationPart: 371 return paintSearchFieldDecoration(o, paintInfo, r); 372 case SearchFieldResultsDecorationPart: 373 return paintSearchFieldResultsDecoration(o, paintInfo, r); 374 case SearchFieldResultsButtonPart: 375 return paintSearchFieldResultsButton(o, paintInfo, r); 376 #if ENABLE(INPUT_SPEECH) 377 case InputSpeechButtonPart: 378 return paintInputFieldSpeechButton(o, paintInfo, r); 379 #endif 380 default: 381 break; 382 } 383 384 return true; // We don't support the appearance, so let the normal background/border paint. 385 } 386 387 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 388 { 389 if (paintInfo.context->paintingDisabled()) 390 return false; 391 392 // Call the appropriate paint method based off the appearance value. 393 switch (o->style()->appearance()) { 394 case TextFieldPart: 395 return paintTextField(o, paintInfo, r); 396 case ListboxPart: 397 case TextAreaPart: 398 return paintTextArea(o, paintInfo, r); 399 case MenulistButtonPart: 400 case SearchFieldPart: 401 return true; 402 case CheckboxPart: 403 case RadioPart: 404 case PushButtonPart: 405 case SquareButtonPart: 406 case ListButtonPart: 407 case DefaultButtonPart: 408 case ButtonPart: 409 case MenulistPart: 410 #if ENABLE(METER_TAG) 411 case MeterPart: 412 case RelevancyLevelIndicatorPart: 413 case ContinuousCapacityLevelIndicatorPart: 414 case DiscreteCapacityLevelIndicatorPart: 415 case RatingLevelIndicatorPart: 416 #endif 417 #if ENABLE(PROGRESS_TAG) 418 case ProgressBarPart: 419 #endif 420 case SliderHorizontalPart: 421 case SliderVerticalPart: 422 case SliderThumbHorizontalPart: 423 case SliderThumbVerticalPart: 424 case SearchFieldCancelButtonPart: 425 case SearchFieldDecorationPart: 426 case SearchFieldResultsDecorationPart: 427 case SearchFieldResultsButtonPart: 428 #if ENABLE(INPUT_SPEECH) 429 case InputSpeechButtonPart: 430 #endif 431 default: 432 break; 433 } 434 435 return false; 436 } 437 438 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 439 { 440 if (paintInfo.context->paintingDisabled()) 441 return false; 442 443 // Call the appropriate paint method based off the appearance value. 444 switch (o->style()->appearance()) { 445 case MenulistButtonPart: 446 return paintMenuListButton(o, paintInfo, r); 447 case TextFieldPart: 448 case TextAreaPart: 449 case ListboxPart: 450 case CheckboxPart: 451 case RadioPart: 452 case PushButtonPart: 453 case SquareButtonPart: 454 case ListButtonPart: 455 case DefaultButtonPart: 456 case ButtonPart: 457 case MenulistPart: 458 #if ENABLE(METER_TAG) 459 case MeterPart: 460 case RelevancyLevelIndicatorPart: 461 case ContinuousCapacityLevelIndicatorPart: 462 case DiscreteCapacityLevelIndicatorPart: 463 case RatingLevelIndicatorPart: 464 #endif 465 #if ENABLE(PROGRESS_TAG) 466 case ProgressBarPart: 467 #endif 468 case SliderHorizontalPart: 469 case SliderVerticalPart: 470 case SliderThumbHorizontalPart: 471 case SliderThumbVerticalPart: 472 case SearchFieldPart: 473 case SearchFieldCancelButtonPart: 474 case SearchFieldDecorationPart: 475 case SearchFieldResultsDecorationPart: 476 case SearchFieldResultsButtonPart: 477 #if ENABLE(INPUT_SPEECH) 478 case InputSpeechButtonPart: 479 #endif 480 default: 481 break; 482 } 483 484 return false; 485 } 486 487 #if ENABLE(VIDEO) 488 489 String RenderTheme::formatMediaControlsTime(float time) const 490 { 491 if (!isfinite(time)) 492 time = 0; 493 int seconds = (int)fabsf(time); 494 int hours = seconds / (60 * 60); 495 int minutes = (seconds / 60) % 60; 496 seconds %= 60; 497 if (hours) { 498 if (hours > 9) 499 return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 500 501 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 502 } 503 504 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); 505 } 506 507 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const 508 { 509 return formatMediaControlsTime(currentTime); 510 } 511 512 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const 513 { 514 return formatMediaControlsTime(currentTime - duration); 515 } 516 517 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const 518 { 519 int y = -size.height(); 520 FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true); 521 if (absPoint.y() < 0) 522 y = muteButtonBox->height(); 523 return IntPoint(0, y); 524 } 525 526 #endif 527 528 Color RenderTheme::activeSelectionBackgroundColor() const 529 { 530 if (!m_activeSelectionBackgroundColor.isValid()) 531 m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite(); 532 return m_activeSelectionBackgroundColor; 533 } 534 535 Color RenderTheme::inactiveSelectionBackgroundColor() const 536 { 537 if (!m_inactiveSelectionBackgroundColor.isValid()) 538 m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite(); 539 return m_inactiveSelectionBackgroundColor; 540 } 541 542 Color RenderTheme::activeSelectionForegroundColor() const 543 { 544 if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors()) 545 m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor(); 546 return m_activeSelectionForegroundColor; 547 } 548 549 Color RenderTheme::inactiveSelectionForegroundColor() const 550 { 551 if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors()) 552 m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor(); 553 return m_inactiveSelectionForegroundColor; 554 } 555 556 Color RenderTheme::activeListBoxSelectionBackgroundColor() const 557 { 558 if (!m_activeListBoxSelectionBackgroundColor.isValid()) 559 m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor(); 560 return m_activeListBoxSelectionBackgroundColor; 561 } 562 563 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const 564 { 565 if (!m_inactiveListBoxSelectionBackgroundColor.isValid()) 566 m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor(); 567 return m_inactiveListBoxSelectionBackgroundColor; 568 } 569 570 Color RenderTheme::activeListBoxSelectionForegroundColor() const 571 { 572 if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors()) 573 m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor(); 574 return m_activeListBoxSelectionForegroundColor; 575 } 576 577 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const 578 { 579 if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors()) 580 m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor(); 581 return m_inactiveListBoxSelectionForegroundColor; 582 } 583 584 Color RenderTheme::platformActiveSelectionBackgroundColor() const 585 { 586 // Use a blue color by default if the platform theme doesn't define anything. 587 return Color(0, 0, 255); 588 } 589 590 Color RenderTheme::platformActiveSelectionForegroundColor() const 591 { 592 // Use a white color by default if the platform theme doesn't define anything. 593 return Color::white; 594 } 595 596 Color RenderTheme::platformInactiveSelectionBackgroundColor() const 597 { 598 // Use a grey color by default if the platform theme doesn't define anything. 599 // This color matches Firefox's inactive color. 600 return Color(176, 176, 176); 601 } 602 603 Color RenderTheme::platformInactiveSelectionForegroundColor() const 604 { 605 // Use a black color by default. 606 return Color::black; 607 } 608 609 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const 610 { 611 return platformActiveSelectionBackgroundColor(); 612 } 613 614 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const 615 { 616 return platformActiveSelectionForegroundColor(); 617 } 618 619 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const 620 { 621 return platformInactiveSelectionBackgroundColor(); 622 } 623 624 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const 625 { 626 return platformInactiveSelectionForegroundColor(); 627 } 628 629 int RenderTheme::baselinePosition(const RenderObject* o) const 630 { 631 if (!o->isBox()) 632 return 0; 633 634 const RenderBox* box = toRenderBox(o); 635 636 #if USE(NEW_THEME) 637 return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom(); 638 #else 639 return box->height() + box->marginTop(); 640 #endif 641 } 642 643 bool RenderTheme::isControlContainer(ControlPart appearance) const 644 { 645 // There are more leaves than this, but we'll patch this function as we add support for 646 // more controls. 647 return appearance != CheckboxPart && appearance != RadioPart; 648 } 649 650 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background, 651 const Color& backgroundColor) const 652 { 653 switch (style->appearance()) { 654 case PushButtonPart: 655 case SquareButtonPart: 656 case DefaultButtonPart: 657 case ButtonPart: 658 case ListboxPart: 659 case MenulistPart: 660 case ProgressBarPart: 661 case MeterPart: 662 case RelevancyLevelIndicatorPart: 663 case ContinuousCapacityLevelIndicatorPart: 664 case DiscreteCapacityLevelIndicatorPart: 665 case RatingLevelIndicatorPart: 666 // FIXME: Uncomment this when making search fields style-able. 667 // case SearchFieldPart: 668 case TextFieldPart: 669 case TextAreaPart: 670 // Test the style to see if the UA border and background match. 671 return (style->border() != border || 672 *style->backgroundLayers() != background || 673 style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor); 674 default: 675 return false; 676 } 677 } 678 679 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r) 680 { 681 #if USE(NEW_THEME) 682 m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom()); 683 #endif 684 } 685 686 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const 687 { 688 return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart); 689 } 690 691 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const 692 { 693 // Default implementation assumes the controls don't respond to changes in :hover state 694 if (state == HoverState && !supportsHover(o->style())) 695 return false; 696 697 // Assume pressed state is only responded to if the control is enabled. 698 if (state == PressedState && !isEnabled(o)) 699 return false; 700 701 // Repaint the control. 702 o->repaint(); 703 return true; 704 } 705 706 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const 707 { 708 ControlStates result = 0; 709 if (isHovered(o)) { 710 result |= HoverState; 711 if (isSpinUpButtonPartHovered(o)) 712 result |= SpinUpState; 713 } 714 if (isPressed(o)) { 715 result |= PressedState; 716 if (isSpinUpButtonPartPressed(o)) 717 result |= SpinUpState; 718 } 719 if (isFocused(o) && o->style()->outlineStyleIsAuto()) 720 result |= FocusState; 721 if (isEnabled(o)) 722 result |= EnabledState; 723 if (isChecked(o)) 724 result |= CheckedState; 725 if (isReadOnlyControl(o)) 726 result |= ReadOnlyState; 727 if (isDefault(o)) 728 result |= DefaultState; 729 if (!isActive(o)) 730 result |= WindowInactiveState; 731 if (isIndeterminate(o)) 732 result |= IndeterminateState; 733 return result; 734 } 735 736 bool RenderTheme::isActive(const RenderObject* o) const 737 { 738 Node* node = o->node(); 739 if (!node) 740 return false; 741 742 Frame* frame = node->document()->frame(); 743 if (!frame) 744 return false; 745 746 Page* page = frame->page(); 747 if (!page) 748 return false; 749 750 return page->focusController()->isActive(); 751 } 752 753 bool RenderTheme::isChecked(const RenderObject* o) const 754 { 755 if (!o->node()) 756 return false; 757 758 InputElement* inputElement = o->node()->toInputElement(); 759 if (!inputElement) 760 return false; 761 762 return inputElement->isChecked(); 763 } 764 765 bool RenderTheme::isIndeterminate(const RenderObject* o) const 766 { 767 if (!o->node()) 768 return false; 769 770 InputElement* inputElement = o->node()->toInputElement(); 771 if (!inputElement) 772 return false; 773 774 return inputElement->isIndeterminate(); 775 } 776 777 bool RenderTheme::isEnabled(const RenderObject* o) const 778 { 779 Node* node = o->node(); 780 if (!node || !node->isElementNode()) 781 return true; 782 return static_cast<Element*>(node)->isEnabledFormControl(); 783 } 784 785 bool RenderTheme::isFocused(const RenderObject* o) const 786 { 787 Node* node = o->node(); 788 if (!node) 789 return false; 790 Document* document = node->document(); 791 Frame* frame = document->frame(); 792 return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive(); 793 } 794 795 bool RenderTheme::isPressed(const RenderObject* o) const 796 { 797 if (!o->node()) 798 return false; 799 return o->node()->active(); 800 } 801 802 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const 803 { 804 Node* node = o->node(); 805 if (!node || !node->active() || !node->isElementNode() 806 || !static_cast<Element*>(node)->isSpinButtonElement()) 807 return false; 808 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 809 return element->upDownState() == SpinButtonElement::Up; 810 } 811 812 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const 813 { 814 Node* node = o->node(); 815 if (!node || !node->isElementNode()) 816 return false; 817 return static_cast<Element*>(node)->isReadOnlyFormControl(); 818 } 819 820 bool RenderTheme::isHovered(const RenderObject* o) const 821 { 822 Node* node = o->node(); 823 if (!node) 824 return false; 825 if (!node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement()) 826 return node->hovered(); 827 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 828 return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate; 829 } 830 831 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const 832 { 833 Node* node = o->node(); 834 if (!node || !node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement()) 835 return false; 836 SpinButtonElement* element = static_cast<SpinButtonElement*>(node); 837 return element->upDownState() == SpinButtonElement::Up; 838 } 839 840 bool RenderTheme::isDefault(const RenderObject* o) const 841 { 842 // A button should only have the default appearance if the page is active 843 if (!isActive(o)) 844 return false; 845 846 if (!o->document()) 847 return false; 848 849 Settings* settings = o->document()->settings(); 850 if (!settings || !settings->inApplicationChromeMode()) 851 return false; 852 853 return o->style()->appearance() == DefaultButtonPart; 854 } 855 856 #if !USE(NEW_THEME) 857 858 void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 859 { 860 // A summary of the rules for checkbox designed to match WinIE: 861 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 862 // font-size - not honored (control has no text), but we use it to decide which control size to use. 863 setCheckboxSize(style); 864 865 // padding - not honored by WinIE, needs to be removed. 866 style->resetPadding(); 867 868 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 869 // for now, we will not honor it. 870 style->resetBorder(); 871 872 style->setBoxShadow(0); 873 } 874 875 void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 876 { 877 // A summary of the rules for checkbox designed to match WinIE: 878 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 879 // font-size - not honored (control has no text), but we use it to decide which control size to use. 880 setRadioSize(style); 881 882 // padding - not honored by WinIE, needs to be removed. 883 style->resetPadding(); 884 885 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 886 // for now, we will not honor it. 887 style->resetBorder(); 888 889 style->setBoxShadow(0); 890 } 891 892 void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 893 { 894 // Most platforms will completely honor all CSS, and so we have no need to adjust the style 895 // at all by default. We will still allow the theme a crack at setting up a desired vertical size. 896 setButtonSize(style); 897 } 898 899 void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const 900 { 901 } 902 903 void RenderTheme::adjustOuterSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const 904 { 905 } 906 907 #endif 908 909 void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const 910 { 911 } 912 913 void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const 914 { 915 } 916 917 void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const 918 { 919 } 920 921 #if ENABLE(INPUT_SPEECH) 922 void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const 923 { 924 RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element); 925 } 926 927 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 928 { 929 return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect); 930 } 931 #endif 932 933 #if ENABLE(METER_TAG) 934 void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 935 { 936 style->setBoxShadow(0); 937 } 938 939 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const 940 { 941 return bounds.size(); 942 } 943 944 bool RenderTheme::supportsMeter(ControlPart) const 945 { 946 return false; 947 } 948 949 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&) 950 { 951 return true; 952 } 953 954 #endif 955 956 #if ENABLE(PROGRESS_TAG) 957 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const 958 { 959 return 0; 960 } 961 962 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const 963 { 964 return 0; 965 } 966 967 void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const 968 { 969 } 970 #endif 971 972 void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const 973 { 974 } 975 976 void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const 977 { 978 } 979 980 void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const 981 { 982 } 983 984 void RenderTheme::adjustSliderThumbSize(RenderObject*) const 985 { 986 } 987 988 void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const 989 { 990 } 991 992 void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const 993 { 994 } 995 996 void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const 997 { 998 } 999 1000 void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const 1001 { 1002 } 1003 1004 void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const 1005 { 1006 } 1007 1008 void RenderTheme::platformColorsDidChange() 1009 { 1010 m_activeSelectionForegroundColor = Color(); 1011 m_inactiveSelectionForegroundColor = Color(); 1012 m_activeSelectionBackgroundColor = Color(); 1013 m_inactiveSelectionBackgroundColor = Color(); 1014 1015 m_activeListBoxSelectionForegroundColor = Color(); 1016 m_inactiveListBoxSelectionForegroundColor = Color(); 1017 m_activeListBoxSelectionBackgroundColor = Color(); 1018 m_inactiveListBoxSelectionForegroundColor = Color(); 1019 1020 Page::scheduleForcedStyleRecalcForAllPages(); 1021 } 1022 1023 Color RenderTheme::systemColor(int cssValueId) const 1024 { 1025 switch (cssValueId) { 1026 case CSSValueActiveborder: 1027 return 0xFFFFFFFF; 1028 case CSSValueActivecaption: 1029 return 0xFFCCCCCC; 1030 case CSSValueAppworkspace: 1031 return 0xFFFFFFFF; 1032 case CSSValueBackground: 1033 return 0xFF6363CE; 1034 case CSSValueButtonface: 1035 return 0xFFC0C0C0; 1036 case CSSValueButtonhighlight: 1037 return 0xFFDDDDDD; 1038 case CSSValueButtonshadow: 1039 return 0xFF888888; 1040 case CSSValueButtontext: 1041 return 0xFF000000; 1042 case CSSValueCaptiontext: 1043 return 0xFF000000; 1044 case CSSValueGraytext: 1045 return 0xFF808080; 1046 case CSSValueHighlight: 1047 return 0xFFB5D5FF; 1048 case CSSValueHighlighttext: 1049 return 0xFF000000; 1050 case CSSValueInactiveborder: 1051 return 0xFFFFFFFF; 1052 case CSSValueInactivecaption: 1053 return 0xFFFFFFFF; 1054 case CSSValueInactivecaptiontext: 1055 return 0xFF7F7F7F; 1056 case CSSValueInfobackground: 1057 return 0xFFFBFCC5; 1058 case CSSValueInfotext: 1059 return 0xFF000000; 1060 case CSSValueMenu: 1061 return 0xFFC0C0C0; 1062 case CSSValueMenutext: 1063 return 0xFF000000; 1064 case CSSValueScrollbar: 1065 return 0xFFFFFFFF; 1066 case CSSValueText: 1067 return 0xFF000000; 1068 case CSSValueThreeddarkshadow: 1069 return 0xFF666666; 1070 case CSSValueThreedface: 1071 return 0xFFC0C0C0; 1072 case CSSValueThreedhighlight: 1073 return 0xFFDDDDDD; 1074 case CSSValueThreedlightshadow: 1075 return 0xFFC0C0C0; 1076 case CSSValueThreedshadow: 1077 return 0xFF888888; 1078 case CSSValueWindow: 1079 return 0xFFFFFFFF; 1080 case CSSValueWindowframe: 1081 return 0xFFCCCCCC; 1082 case CSSValueWindowtext: 1083 return 0xFF000000; 1084 } 1085 return Color(); 1086 } 1087 1088 Color RenderTheme::platformActiveTextSearchHighlightColor() const 1089 { 1090 return Color(255, 150, 50); // Orange. 1091 } 1092 1093 Color RenderTheme::platformInactiveTextSearchHighlightColor() const 1094 { 1095 return Color(255, 255, 0); // Yellow. 1096 } 1097 1098 void RenderTheme::setCustomFocusRingColor(const Color& c) 1099 { 1100 customFocusRingColor() = c; 1101 } 1102 1103 Color RenderTheme::focusRingColor() 1104 { 1105 return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor(); 1106 } 1107 1108 } // namespace WebCore 1109