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
customFocusRingColor()58 static Color& customFocusRingColor()
59 {
60 DEFINE_STATIC_LOCAL(Color, color, ());
61 return color;
62 }
63
RenderTheme()64 RenderTheme::RenderTheme()
65 #if USE(NEW_THEME)
66 : m_theme(platformTheme())
67 #endif
68 {
69 }
70
adjustStyle(CSSStyleSelector * selector,RenderStyle * style,Element * e,bool UAHasAppearance,const BorderData & border,const FillLayer & background,const Color & backgroundColor)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
paint(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)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
paintBorderOnly(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)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
paintDecorations(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)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
formatMediaControlsTime(float time) const489 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
formatMediaControlsCurrentTime(float currentTime,float) const507 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
508 {
509 return formatMediaControlsTime(currentTime);
510 }
511
formatMediaControlsRemainingTime(float currentTime,float duration) const512 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
513 {
514 return formatMediaControlsTime(currentTime - duration);
515 }
516
volumeSliderOffsetFromMuteButton(RenderBox * muteButtonBox,const IntSize & size) const517 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
activeSelectionBackgroundColor() const528 Color RenderTheme::activeSelectionBackgroundColor() const
529 {
530 if (!m_activeSelectionBackgroundColor.isValid())
531 m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
532 return m_activeSelectionBackgroundColor;
533 }
534
inactiveSelectionBackgroundColor() const535 Color RenderTheme::inactiveSelectionBackgroundColor() const
536 {
537 if (!m_inactiveSelectionBackgroundColor.isValid())
538 m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
539 return m_inactiveSelectionBackgroundColor;
540 }
541
activeSelectionForegroundColor() const542 Color RenderTheme::activeSelectionForegroundColor() const
543 {
544 if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
545 m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
546 return m_activeSelectionForegroundColor;
547 }
548
inactiveSelectionForegroundColor() const549 Color RenderTheme::inactiveSelectionForegroundColor() const
550 {
551 if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
552 m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
553 return m_inactiveSelectionForegroundColor;
554 }
555
activeListBoxSelectionBackgroundColor() const556 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
557 {
558 if (!m_activeListBoxSelectionBackgroundColor.isValid())
559 m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
560 return m_activeListBoxSelectionBackgroundColor;
561 }
562
inactiveListBoxSelectionBackgroundColor() const563 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
564 {
565 if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
566 m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
567 return m_inactiveListBoxSelectionBackgroundColor;
568 }
569
activeListBoxSelectionForegroundColor() const570 Color RenderTheme::activeListBoxSelectionForegroundColor() const
571 {
572 if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
573 m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
574 return m_activeListBoxSelectionForegroundColor;
575 }
576
inactiveListBoxSelectionForegroundColor() const577 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
578 {
579 if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
580 m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
581 return m_inactiveListBoxSelectionForegroundColor;
582 }
583
platformActiveSelectionBackgroundColor() const584 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
platformActiveSelectionForegroundColor() const590 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
platformInactiveSelectionBackgroundColor() const596 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
platformInactiveSelectionForegroundColor() const603 Color RenderTheme::platformInactiveSelectionForegroundColor() const
604 {
605 // Use a black color by default.
606 return Color::black;
607 }
608
platformActiveListBoxSelectionBackgroundColor() const609 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
610 {
611 return platformActiveSelectionBackgroundColor();
612 }
613
platformActiveListBoxSelectionForegroundColor() const614 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
615 {
616 return platformActiveSelectionForegroundColor();
617 }
618
platformInactiveListBoxSelectionBackgroundColor() const619 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
620 {
621 return platformInactiveSelectionBackgroundColor();
622 }
623
platformInactiveListBoxSelectionForegroundColor() const624 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
625 {
626 return platformInactiveSelectionForegroundColor();
627 }
628
baselinePosition(const RenderObject * o) const629 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
isControlContainer(ControlPart appearance) const643 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
isControlStyled(const RenderStyle * style,const BorderData & border,const FillLayer & background,const Color & backgroundColor) const650 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
adjustRepaintRect(const RenderObject * o,IntRect & r)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
supportsFocusRing(const RenderStyle * style) const686 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
stateChanged(RenderObject * o,ControlState state) const691 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
controlStatesForRenderer(const RenderObject * o) const706 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
isActive(const RenderObject * o) const736 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
isChecked(const RenderObject * o) const753 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
isIndeterminate(const RenderObject * o) const765 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
isEnabled(const RenderObject * o) const777 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
isFocused(const RenderObject * o) const785 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
isPressed(const RenderObject * o) const795 bool RenderTheme::isPressed(const RenderObject* o) const
796 {
797 if (!o->node())
798 return false;
799 return o->node()->active();
800 }
801
isSpinUpButtonPartPressed(const RenderObject * o) const802 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
isReadOnlyControl(const RenderObject * o) const812 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
isHovered(const RenderObject * o) const820 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
isSpinUpButtonPartHovered(const RenderObject * o) const831 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
isDefault(const RenderObject * o) const840 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
adjustCheckboxStyle(CSSStyleSelector *,RenderStyle * style,Element *) const858 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
adjustRadioStyle(CSSStyleSelector *,RenderStyle * style,Element *) const875 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
adjustButtonStyle(CSSStyleSelector *,RenderStyle * style,Element *) const892 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
adjustInnerSpinButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const899 void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
900 {
901 }
902
adjustOuterSpinButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const903 void RenderTheme::adjustOuterSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
904 {
905 }
906
907 #endif
908
adjustTextFieldStyle(CSSStyleSelector *,RenderStyle *,Element *) const909 void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
910 {
911 }
912
adjustTextAreaStyle(CSSStyleSelector *,RenderStyle *,Element *) const913 void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
914 {
915 }
916
adjustMenuListStyle(CSSStyleSelector *,RenderStyle *,Element *) const917 void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
918 {
919 }
920
921 #if ENABLE(INPUT_SPEECH)
adjustInputFieldSpeechButtonStyle(CSSStyleSelector * selector,RenderStyle * style,Element * element) const922 void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
923 {
924 RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element);
925 }
926
paintInputFieldSpeechButton(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)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)
adjustMeterStyle(CSSStyleSelector *,RenderStyle * style,Element *) const934 void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
935 {
936 style->setBoxShadow(0);
937 }
938
meterSizeForBounds(const RenderMeter *,const IntRect & bounds) const939 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
940 {
941 return bounds.size();
942 }
943
supportsMeter(ControlPart) const944 bool RenderTheme::supportsMeter(ControlPart) const
945 {
946 return false;
947 }
948
paintMeter(RenderObject *,const PaintInfo &,const IntRect &)949 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
950 {
951 return true;
952 }
953
954 #endif
955
956 #if ENABLE(PROGRESS_TAG)
animationRepeatIntervalForProgressBar(RenderProgress *) const957 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
958 {
959 return 0;
960 }
961
animationDurationForProgressBar(RenderProgress *) const962 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
963 {
964 return 0;
965 }
966
adjustProgressBarStyle(CSSStyleSelector *,RenderStyle *,Element *) const967 void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
968 {
969 }
970 #endif
971
adjustMenuListButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const972 void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
973 {
974 }
975
adjustSliderTrackStyle(CSSStyleSelector *,RenderStyle *,Element *) const976 void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
977 {
978 }
979
adjustSliderThumbStyle(CSSStyleSelector *,RenderStyle *,Element *) const980 void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const
981 {
982 }
983
adjustSliderThumbSize(RenderObject *) const984 void RenderTheme::adjustSliderThumbSize(RenderObject*) const
985 {
986 }
987
adjustSearchFieldStyle(CSSStyleSelector *,RenderStyle *,Element *) const988 void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
989 {
990 }
991
adjustSearchFieldCancelButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const992 void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
993 {
994 }
995
adjustSearchFieldDecorationStyle(CSSStyleSelector *,RenderStyle *,Element *) const996 void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
997 {
998 }
999
adjustSearchFieldResultsDecorationStyle(CSSStyleSelector *,RenderStyle *,Element *) const1000 void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1001 {
1002 }
1003
adjustSearchFieldResultsButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const1004 void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1005 {
1006 }
1007
platformColorsDidChange()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
systemColor(int cssValueId) const1023 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
platformActiveTextSearchHighlightColor() const1088 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1089 {
1090 return Color(255, 150, 50); // Orange.
1091 }
1092
platformInactiveTextSearchHighlightColor() const1093 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1094 {
1095 return Color(255, 255, 0); // Yellow.
1096 }
1097
setCustomFocusRingColor(const Color & c)1098 void RenderTheme::setCustomFocusRingColor(const Color& c)
1099 {
1100 customFocusRingColor() = c;
1101 }
1102
focusRingColor()1103 Color RenderTheme::focusRingColor()
1104 {
1105 return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1106 }
1107
1108 } // namespace WebCore
1109