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