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(nullptr);
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 case MenulistPart:
203 return adjustMenuListStyle(selector, style, e);
204 case MenulistButtonPart:
205 return adjustMenuListButtonStyle(selector, style, e);
206 case MediaSliderPart:
207 case MediaVolumeSliderPart:
208 case SliderHorizontalPart:
209 case SliderVerticalPart:
210 return adjustSliderTrackStyle(selector, style, e);
211 case SliderThumbHorizontalPart:
212 case SliderThumbVerticalPart:
213 return adjustSliderThumbStyle(selector, style, e);
214 case SearchFieldPart:
215 return adjustSearchFieldStyle(selector, style, e);
216 case SearchFieldCancelButtonPart:
217 return adjustSearchFieldCancelButtonStyle(selector, style, e);
218 case SearchFieldDecorationPart:
219 return adjustSearchFieldDecorationStyle(selector, style, e);
220 case SearchFieldResultsDecorationPart:
221 return adjustSearchFieldResultsDecorationStyle(selector, style, e);
222 case SearchFieldResultsButtonPart:
223 return adjustSearchFieldResultsButtonStyle(selector, style, e);
224 #if ENABLE(PROGRESS_TAG)
225 case ProgressBarPart:
226 return adjustProgressBarStyle(selector, style, e);
227 #endif
228 #if ENABLE(METER_TAG)
229 case MeterPart:
230 case RelevancyLevelIndicatorPart:
231 case ContinuousCapacityLevelIndicatorPart:
232 case DiscreteCapacityLevelIndicatorPart:
233 case RatingLevelIndicatorPart:
234 return adjustMeterStyle(selector, style, e);
235 #endif
236 #if ENABLE(INPUT_SPEECH)
237 case InputSpeechButtonPart:
238 return adjustInputFieldSpeechButtonStyle(selector, style, e);
239 #endif
240 default:
241 break;
242 }
243 }
244
paint(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)245 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
246 {
247 // If painting is disabled, but we aren't updating control tints, then just bail.
248 // If we are updating control tints, just schedule a repaint if the theme supports tinting
249 // for that control.
250 if (paintInfo.context->updatingControlTints()) {
251 if (controlSupportsTints(o))
252 o->repaint();
253 return false;
254 }
255 if (paintInfo.context->paintingDisabled())
256 return false;
257
258 ControlPart part = o->style()->appearance();
259
260 #if USE(NEW_THEME)
261 switch (part) {
262 case CheckboxPart:
263 case RadioPart:
264 case PushButtonPart:
265 case SquareButtonPart:
266 case ListButtonPart:
267 case DefaultButtonPart:
268 case ButtonPart:
269 case InnerSpinButtonPart:
270 case OuterSpinButtonPart:
271 m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView());
272 return false;
273 default:
274 break;
275 }
276 #endif
277
278 // Call the appropriate paint method based off the appearance value.
279 switch (part) {
280 #if !USE(NEW_THEME)
281 case CheckboxPart:
282 return paintCheckbox(o, paintInfo, r);
283 case RadioPart:
284 return paintRadio(o, paintInfo, r);
285 case PushButtonPart:
286 case SquareButtonPart:
287 case ListButtonPart:
288 case DefaultButtonPart:
289 case ButtonPart:
290 return paintButton(o, paintInfo, r);
291 case InnerSpinButtonPart:
292 return paintInnerSpinButton(o, paintInfo, r);
293 case OuterSpinButtonPart:
294 return paintOuterSpinButton(o, paintInfo, r);
295 #endif
296 case MenulistPart:
297 return paintMenuList(o, paintInfo, r);
298 #if ENABLE(METER_TAG)
299 case MeterPart:
300 case RelevancyLevelIndicatorPart:
301 case ContinuousCapacityLevelIndicatorPart:
302 case DiscreteCapacityLevelIndicatorPart:
303 case RatingLevelIndicatorPart:
304 return paintMeter(o, paintInfo, r);
305 #endif
306 #if ENABLE(PROGRESS_TAG)
307 case ProgressBarPart:
308 return paintProgressBar(o, paintInfo, r);
309 #endif
310 case SliderHorizontalPart:
311 case SliderVerticalPart:
312 return paintSliderTrack(o, paintInfo, r);
313 case SliderThumbHorizontalPart:
314 case SliderThumbVerticalPart:
315 if (o->parent()->isSlider())
316 return paintSliderThumb(o, paintInfo, r);
317 // We don't support drawing a slider thumb without a parent slider
318 break;
319 case MediaFullscreenButtonPart:
320 return paintMediaFullscreenButton(o, paintInfo, r);
321 case MediaPlayButtonPart:
322 return paintMediaPlayButton(o, paintInfo, r);
323 case MediaMuteButtonPart:
324 return paintMediaMuteButton(o, paintInfo, r);
325 case MediaSeekBackButtonPart:
326 return paintMediaSeekBackButton(o, paintInfo, r);
327 case MediaSeekForwardButtonPart:
328 return paintMediaSeekForwardButton(o, paintInfo, r);
329 case MediaRewindButtonPart:
330 return paintMediaRewindButton(o, paintInfo, r);
331 case MediaReturnToRealtimeButtonPart:
332 return paintMediaReturnToRealtimeButton(o, paintInfo, r);
333 case MediaToggleClosedCaptionsButtonPart:
334 return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
335 case MediaSliderPart:
336 return paintMediaSliderTrack(o, paintInfo, r);
337 case MediaSliderThumbPart:
338 if (o->parent()->isSlider())
339 return paintMediaSliderThumb(o, paintInfo, r);
340 break;
341 case MediaVolumeSliderMuteButtonPart:
342 return paintMediaMuteButton(o, paintInfo, r);
343 case MediaVolumeSliderContainerPart:
344 return paintMediaVolumeSliderContainer(o, paintInfo, r);
345 case MediaVolumeSliderPart:
346 return paintMediaVolumeSliderTrack(o, paintInfo, r);
347 case MediaVolumeSliderThumbPart:
348 if (o->parent()->isSlider())
349 return paintMediaVolumeSliderThumb(o, paintInfo, r);
350 break;
351 case MediaTimeRemainingPart:
352 return paintMediaTimeRemaining(o, paintInfo, r);
353 case MediaCurrentTimePart:
354 return paintMediaCurrentTime(o, paintInfo, r);
355 case MediaControlsBackgroundPart:
356 return paintMediaControlsBackground(o, paintInfo, r);
357 case MenulistButtonPart:
358 case TextFieldPart:
359 case TextAreaPart:
360 case ListboxPart:
361 return true;
362 case SearchFieldPart:
363 return paintSearchField(o, paintInfo, r);
364 case SearchFieldCancelButtonPart:
365 return paintSearchFieldCancelButton(o, paintInfo, r);
366 case SearchFieldDecorationPart:
367 return paintSearchFieldDecoration(o, paintInfo, r);
368 case SearchFieldResultsDecorationPart:
369 return paintSearchFieldResultsDecoration(o, paintInfo, r);
370 case SearchFieldResultsButtonPart:
371 return paintSearchFieldResultsButton(o, paintInfo, r);
372 #if ENABLE(INPUT_SPEECH)
373 case InputSpeechButtonPart:
374 return paintInputFieldSpeechButton(o, paintInfo, r);
375 #endif
376 default:
377 break;
378 }
379
380 return true; // We don't support the appearance, so let the normal background/border paint.
381 }
382
paintBorderOnly(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)383 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
384 {
385 if (paintInfo.context->paintingDisabled())
386 return false;
387
388 // Call the appropriate paint method based off the appearance value.
389 switch (o->style()->appearance()) {
390 case TextFieldPart:
391 return paintTextField(o, paintInfo, r);
392 case ListboxPart:
393 case TextAreaPart:
394 return paintTextArea(o, paintInfo, r);
395 case MenulistButtonPart:
396 case SearchFieldPart:
397 return true;
398 case CheckboxPart:
399 case RadioPart:
400 case PushButtonPart:
401 case SquareButtonPart:
402 case ListButtonPart:
403 case DefaultButtonPart:
404 case ButtonPart:
405 case MenulistPart:
406 #if ENABLE(METER_TAG)
407 case MeterPart:
408 case RelevancyLevelIndicatorPart:
409 case ContinuousCapacityLevelIndicatorPart:
410 case DiscreteCapacityLevelIndicatorPart:
411 case RatingLevelIndicatorPart:
412 #endif
413 #if ENABLE(PROGRESS_TAG)
414 case ProgressBarPart:
415 #endif
416 case SliderHorizontalPart:
417 case SliderVerticalPart:
418 case SliderThumbHorizontalPart:
419 case SliderThumbVerticalPart:
420 case SearchFieldCancelButtonPart:
421 case SearchFieldDecorationPart:
422 case SearchFieldResultsDecorationPart:
423 case SearchFieldResultsButtonPart:
424 #if ENABLE(INPUT_SPEECH)
425 case InputSpeechButtonPart:
426 #endif
427 default:
428 break;
429 }
430
431 return false;
432 }
433
paintDecorations(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)434 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
435 {
436 if (paintInfo.context->paintingDisabled())
437 return false;
438
439 // Call the appropriate paint method based off the appearance value.
440 switch (o->style()->appearance()) {
441 case MenulistButtonPart:
442 return paintMenuListButton(o, paintInfo, r);
443 case TextFieldPart:
444 case TextAreaPart:
445 case ListboxPart:
446 case CheckboxPart:
447 case RadioPart:
448 case PushButtonPart:
449 case SquareButtonPart:
450 case ListButtonPart:
451 case DefaultButtonPart:
452 case ButtonPart:
453 case MenulistPart:
454 #if ENABLE(METER_TAG)
455 case MeterPart:
456 case RelevancyLevelIndicatorPart:
457 case ContinuousCapacityLevelIndicatorPart:
458 case DiscreteCapacityLevelIndicatorPart:
459 case RatingLevelIndicatorPart:
460 #endif
461 #if ENABLE(PROGRESS_TAG)
462 case ProgressBarPart:
463 #endif
464 case SliderHorizontalPart:
465 case SliderVerticalPart:
466 case SliderThumbHorizontalPart:
467 case SliderThumbVerticalPart:
468 case SearchFieldPart:
469 case SearchFieldCancelButtonPart:
470 case SearchFieldDecorationPart:
471 case SearchFieldResultsDecorationPart:
472 case SearchFieldResultsButtonPart:
473 #if ENABLE(INPUT_SPEECH)
474 case InputSpeechButtonPart:
475 #endif
476 default:
477 break;
478 }
479
480 return false;
481 }
482
483 #if ENABLE(VIDEO)
484
formatMediaControlsTime(float time) const485 String RenderTheme::formatMediaControlsTime(float time) const
486 {
487 if (!isfinite(time))
488 time = 0;
489 int seconds = (int)fabsf(time);
490 int hours = seconds / (60 * 60);
491 int minutes = (seconds / 60) % 60;
492 seconds %= 60;
493 if (hours) {
494 if (hours > 9)
495 return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
496
497 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
498 }
499
500 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
501 }
502
formatMediaControlsCurrentTime(float currentTime,float) const503 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
504 {
505 return formatMediaControlsTime(currentTime);
506 }
507
formatMediaControlsRemainingTime(float currentTime,float duration) const508 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
509 {
510 return formatMediaControlsTime(currentTime - duration);
511 }
512
volumeSliderOffsetFromMuteButton(RenderBox * muteButtonBox,const IntSize & size) const513 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
514 {
515 int y = -size.height();
516 FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true);
517 if (absPoint.y() < 0)
518 y = muteButtonBox->height();
519 return IntPoint(0, y);
520 }
521
522 #endif
523
activeSelectionBackgroundColor() const524 Color RenderTheme::activeSelectionBackgroundColor() const
525 {
526 if (!m_activeSelectionBackgroundColor.isValid())
527 m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
528 return m_activeSelectionBackgroundColor;
529 }
530
inactiveSelectionBackgroundColor() const531 Color RenderTheme::inactiveSelectionBackgroundColor() const
532 {
533 if (!m_inactiveSelectionBackgroundColor.isValid())
534 m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
535 return m_inactiveSelectionBackgroundColor;
536 }
537
activeSelectionForegroundColor() const538 Color RenderTheme::activeSelectionForegroundColor() const
539 {
540 if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
541 m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
542 return m_activeSelectionForegroundColor;
543 }
544
inactiveSelectionForegroundColor() const545 Color RenderTheme::inactiveSelectionForegroundColor() const
546 {
547 if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
548 m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
549 return m_inactiveSelectionForegroundColor;
550 }
551
activeListBoxSelectionBackgroundColor() const552 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
553 {
554 if (!m_activeListBoxSelectionBackgroundColor.isValid())
555 m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
556 return m_activeListBoxSelectionBackgroundColor;
557 }
558
inactiveListBoxSelectionBackgroundColor() const559 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
560 {
561 if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
562 m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
563 return m_inactiveListBoxSelectionBackgroundColor;
564 }
565
activeListBoxSelectionForegroundColor() const566 Color RenderTheme::activeListBoxSelectionForegroundColor() const
567 {
568 if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
569 m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
570 return m_activeListBoxSelectionForegroundColor;
571 }
572
inactiveListBoxSelectionForegroundColor() const573 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
574 {
575 if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
576 m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
577 return m_inactiveListBoxSelectionForegroundColor;
578 }
579
platformActiveSelectionBackgroundColor() const580 Color RenderTheme::platformActiveSelectionBackgroundColor() const
581 {
582 // Use a blue color by default if the platform theme doesn't define anything.
583 return Color(0, 0, 255);
584 }
585
platformActiveSelectionForegroundColor() const586 Color RenderTheme::platformActiveSelectionForegroundColor() const
587 {
588 // Use a white color by default if the platform theme doesn't define anything.
589 return Color::white;
590 }
591
platformInactiveSelectionBackgroundColor() const592 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
593 {
594 // Use a grey color by default if the platform theme doesn't define anything.
595 // This color matches Firefox's inactive color.
596 return Color(176, 176, 176);
597 }
598
platformInactiveSelectionForegroundColor() const599 Color RenderTheme::platformInactiveSelectionForegroundColor() const
600 {
601 // Use a black color by default.
602 return Color::black;
603 }
604
platformActiveListBoxSelectionBackgroundColor() const605 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
606 {
607 return platformActiveSelectionBackgroundColor();
608 }
609
platformActiveListBoxSelectionForegroundColor() const610 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
611 {
612 return platformActiveSelectionForegroundColor();
613 }
614
platformInactiveListBoxSelectionBackgroundColor() const615 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
616 {
617 return platformInactiveSelectionBackgroundColor();
618 }
619
platformInactiveListBoxSelectionForegroundColor() const620 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
621 {
622 return platformInactiveSelectionForegroundColor();
623 }
624
baselinePosition(const RenderObject * o) const625 int RenderTheme::baselinePosition(const RenderObject* o) const
626 {
627 if (!o->isBox())
628 return 0;
629
630 const RenderBox* box = toRenderBox(o);
631
632 #if USE(NEW_THEME)
633 return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
634 #else
635 return box->height() + box->marginTop();
636 #endif
637 }
638
isControlContainer(ControlPart appearance) const639 bool RenderTheme::isControlContainer(ControlPart appearance) const
640 {
641 // There are more leaves than this, but we'll patch this function as we add support for
642 // more controls.
643 return appearance != CheckboxPart && appearance != RadioPart;
644 }
645
isControlStyled(const RenderStyle * style,const BorderData & border,const FillLayer & background,const Color & backgroundColor) const646 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background,
647 const Color& backgroundColor) const
648 {
649 switch (style->appearance()) {
650 case PushButtonPart:
651 case SquareButtonPart:
652 case DefaultButtonPart:
653 case ButtonPart:
654 case ListboxPart:
655 case MenulistPart:
656 case ProgressBarPart:
657 case MeterPart:
658 case RelevancyLevelIndicatorPart:
659 case ContinuousCapacityLevelIndicatorPart:
660 case DiscreteCapacityLevelIndicatorPart:
661 case RatingLevelIndicatorPart:
662 // FIXME: Uncomment this when making search fields style-able.
663 // case SearchFieldPart:
664 case TextFieldPart:
665 case TextAreaPart:
666 // Test the style to see if the UA border and background match.
667 return (style->border() != border ||
668 *style->backgroundLayers() != background ||
669 style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
670 default:
671 return false;
672 }
673 }
674
adjustRepaintRect(const RenderObject * o,IntRect & r)675 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
676 {
677 #if USE(NEW_THEME)
678 m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
679 #endif
680 }
681
supportsFocusRing(const RenderStyle * style) const682 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
683 {
684 return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
685 }
686
stateChanged(RenderObject * o,ControlState state) const687 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
688 {
689 // Default implementation assumes the controls don't respond to changes in :hover state
690 if (state == HoverState && !supportsHover(o->style()))
691 return false;
692
693 // Assume pressed state is only responded to if the control is enabled.
694 if (state == PressedState && !isEnabled(o))
695 return false;
696
697 // Repaint the control.
698 o->repaint();
699 return true;
700 }
701
controlStatesForRenderer(const RenderObject * o) const702 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
703 {
704 ControlStates result = 0;
705 if (isHovered(o)) {
706 result |= HoverState;
707 if (isSpinUpButtonPartHovered(o))
708 result |= SpinUpState;
709 }
710 if (isPressed(o)) {
711 result |= PressedState;
712 if (isSpinUpButtonPartPressed(o))
713 result |= SpinUpState;
714 }
715 if (isFocused(o) && o->style()->outlineStyleIsAuto())
716 result |= FocusState;
717 if (isEnabled(o))
718 result |= EnabledState;
719 if (isChecked(o))
720 result |= CheckedState;
721 if (isReadOnlyControl(o))
722 result |= ReadOnlyState;
723 if (isDefault(o))
724 result |= DefaultState;
725 if (!isActive(o))
726 result |= WindowInactiveState;
727 if (isIndeterminate(o))
728 result |= IndeterminateState;
729 return result;
730 }
731
isActive(const RenderObject * o) const732 bool RenderTheme::isActive(const RenderObject* o) const
733 {
734 Node* node = o->node();
735 if (!node)
736 return false;
737
738 Frame* frame = node->document()->frame();
739 if (!frame)
740 return false;
741
742 Page* page = frame->page();
743 if (!page)
744 return false;
745
746 return page->focusController()->isActive();
747 }
748
isChecked(const RenderObject * o) const749 bool RenderTheme::isChecked(const RenderObject* o) const
750 {
751 if (!o->node())
752 return false;
753
754 InputElement* inputElement = o->node()->toInputElement();
755 if (!inputElement)
756 return false;
757
758 return inputElement->isChecked();
759 }
760
isIndeterminate(const RenderObject * o) const761 bool RenderTheme::isIndeterminate(const RenderObject* o) const
762 {
763 if (!o->node())
764 return false;
765
766 InputElement* inputElement = o->node()->toInputElement();
767 if (!inputElement)
768 return false;
769
770 return inputElement->isIndeterminate();
771 }
772
isEnabled(const RenderObject * o) const773 bool RenderTheme::isEnabled(const RenderObject* o) const
774 {
775 Node* node = o->node();
776 if (!node || !node->isElementNode())
777 return true;
778 return static_cast<Element*>(node)->isEnabledFormControl();
779 }
780
isFocused(const RenderObject * o) const781 bool RenderTheme::isFocused(const RenderObject* o) const
782 {
783 Node* node = o->node();
784 if (!node)
785 return false;
786 Document* document = node->document();
787 Frame* frame = document->frame();
788 return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive();
789 }
790
isPressed(const RenderObject * o) const791 bool RenderTheme::isPressed(const RenderObject* o) const
792 {
793 if (!o->node())
794 return false;
795 return o->node()->active();
796 }
797
isSpinUpButtonPartPressed(const RenderObject * o) const798 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
799 {
800 Node* node = o->node();
801 if (!node || !node->active() || !node->isElementNode()
802 || !static_cast<Element*>(node)->isSpinButtonElement())
803 return false;
804 SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
805 return element->upDownState() == SpinButtonElement::Up;
806 }
807
isReadOnlyControl(const RenderObject * o) const808 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
809 {
810 Node* node = o->node();
811 if (!node || !node->isElementNode())
812 return false;
813 return static_cast<Element*>(node)->isReadOnlyFormControl();
814 }
815
isHovered(const RenderObject * o) const816 bool RenderTheme::isHovered(const RenderObject* o) const
817 {
818 Node* node = o->node();
819 if (!node)
820 return false;
821 if (!node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
822 return node->hovered();
823 SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
824 return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
825 }
826
isSpinUpButtonPartHovered(const RenderObject * o) const827 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
828 {
829 Node* node = o->node();
830 if (!node || !node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
831 return false;
832 SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
833 return element->upDownState() == SpinButtonElement::Up;
834 }
835
isDefault(const RenderObject * o) const836 bool RenderTheme::isDefault(const RenderObject* o) const
837 {
838 // A button should only have the default appearance if the page is active
839 if (!isActive(o))
840 return false;
841
842 if (!o->document())
843 return false;
844
845 Settings* settings = o->document()->settings();
846 if (!settings || !settings->inApplicationChromeMode())
847 return false;
848
849 return o->style()->appearance() == DefaultButtonPart;
850 }
851
852 #if !USE(NEW_THEME)
853
adjustCheckboxStyle(CSSStyleSelector *,RenderStyle * style,Element *) const854 void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
855 {
856 // A summary of the rules for checkbox designed to match WinIE:
857 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
858 // font-size - not honored (control has no text), but we use it to decide which control size to use.
859 setCheckboxSize(style);
860
861 // padding - not honored by WinIE, needs to be removed.
862 style->resetPadding();
863
864 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
865 // for now, we will not honor it.
866 style->resetBorder();
867
868 style->setBoxShadow(nullptr);
869 }
870
adjustRadioStyle(CSSStyleSelector *,RenderStyle * style,Element *) const871 void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
872 {
873 // A summary of the rules for checkbox designed to match WinIE:
874 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
875 // font-size - not honored (control has no text), but we use it to decide which control size to use.
876 setRadioSize(style);
877
878 // padding - not honored by WinIE, needs to be removed.
879 style->resetPadding();
880
881 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
882 // for now, we will not honor it.
883 style->resetBorder();
884
885 style->setBoxShadow(nullptr);
886 }
887
adjustButtonStyle(CSSStyleSelector *,RenderStyle * style,Element *) const888 void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
889 {
890 // Most platforms will completely honor all CSS, and so we have no need to adjust the style
891 // at all by default. We will still allow the theme a crack at setting up a desired vertical size.
892 setButtonSize(style);
893 }
894
adjustInnerSpinButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const895 void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
896 {
897 }
898
adjustOuterSpinButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const899 void RenderTheme::adjustOuterSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
900 {
901 }
902
903 #endif
904
adjustTextFieldStyle(CSSStyleSelector *,RenderStyle *,Element *) const905 void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
906 {
907 }
908
adjustTextAreaStyle(CSSStyleSelector *,RenderStyle *,Element *) const909 void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
910 {
911 }
912
adjustMenuListStyle(CSSStyleSelector *,RenderStyle *,Element *) const913 void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
914 {
915 }
916
917 #if ENABLE(INPUT_SPEECH)
adjustInputFieldSpeechButtonStyle(CSSStyleSelector * selector,RenderStyle * style,Element * element) const918 void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
919 {
920 RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element);
921 }
922
paintInputFieldSpeechButton(RenderObject * object,const PaintInfo & paintInfo,const IntRect & rect)923 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
924 {
925 return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
926 }
927 #endif
928
929 #if ENABLE(METER_TAG)
adjustMeterStyle(CSSStyleSelector *,RenderStyle * style,Element *) const930 void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
931 {
932 style->setBoxShadow(nullptr);
933 }
934
meterSizeForBounds(const RenderMeter *,const IntRect & bounds) const935 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
936 {
937 return bounds.size();
938 }
939
supportsMeter(ControlPart) const940 bool RenderTheme::supportsMeter(ControlPart) const
941 {
942 return false;
943 }
944
paintMeter(RenderObject *,const PaintInfo &,const IntRect &)945 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
946 {
947 return true;
948 }
949
950 #endif
951
952 #if ENABLE(PROGRESS_TAG)
animationRepeatIntervalForProgressBar(RenderProgress *) const953 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
954 {
955 return 0;
956 }
957
animationDurationForProgressBar(RenderProgress *) const958 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
959 {
960 return 0;
961 }
962
adjustProgressBarStyle(CSSStyleSelector *,RenderStyle *,Element *) const963 void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
964 {
965 }
966 #endif
967
shouldHaveSpinButton(InputElement * inputElement) const968 bool RenderTheme::shouldHaveSpinButton(InputElement* inputElement) const
969 {
970 return inputElement->isSteppable() && !inputElement->isRangeControl();
971 }
972
adjustMenuListButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const973 void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
974 {
975 }
976
adjustSliderTrackStyle(CSSStyleSelector *,RenderStyle *,Element *) const977 void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
978 {
979 }
980
adjustSliderThumbStyle(CSSStyleSelector *,RenderStyle *,Element *) const981 void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const
982 {
983 }
984
adjustSliderThumbSize(RenderObject *) const985 void RenderTheme::adjustSliderThumbSize(RenderObject*) const
986 {
987 }
988
adjustSearchFieldStyle(CSSStyleSelector *,RenderStyle *,Element *) const989 void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
990 {
991 }
992
adjustSearchFieldCancelButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const993 void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
994 {
995 }
996
adjustSearchFieldDecorationStyle(CSSStyleSelector *,RenderStyle *,Element *) const997 void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
998 {
999 }
1000
adjustSearchFieldResultsDecorationStyle(CSSStyleSelector *,RenderStyle *,Element *) const1001 void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1002 {
1003 }
1004
adjustSearchFieldResultsButtonStyle(CSSStyleSelector *,RenderStyle *,Element *) const1005 void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
1006 {
1007 }
1008
platformColorsDidChange()1009 void RenderTheme::platformColorsDidChange()
1010 {
1011 m_activeSelectionForegroundColor = Color();
1012 m_inactiveSelectionForegroundColor = Color();
1013 m_activeSelectionBackgroundColor = Color();
1014 m_inactiveSelectionBackgroundColor = Color();
1015
1016 m_activeListBoxSelectionForegroundColor = Color();
1017 m_inactiveListBoxSelectionForegroundColor = Color();
1018 m_activeListBoxSelectionBackgroundColor = Color();
1019 m_inactiveListBoxSelectionForegroundColor = Color();
1020
1021 Page::scheduleForcedStyleRecalcForAllPages();
1022 }
1023
systemColor(int cssValueId) const1024 Color RenderTheme::systemColor(int cssValueId) const
1025 {
1026 switch (cssValueId) {
1027 case CSSValueActiveborder:
1028 return 0xFFFFFFFF;
1029 case CSSValueActivecaption:
1030 return 0xFFCCCCCC;
1031 case CSSValueAppworkspace:
1032 return 0xFFFFFFFF;
1033 case CSSValueBackground:
1034 return 0xFF6363CE;
1035 case CSSValueButtonface:
1036 return 0xFFC0C0C0;
1037 case CSSValueButtonhighlight:
1038 return 0xFFDDDDDD;
1039 case CSSValueButtonshadow:
1040 return 0xFF888888;
1041 case CSSValueButtontext:
1042 return 0xFF000000;
1043 case CSSValueCaptiontext:
1044 return 0xFF000000;
1045 case CSSValueGraytext:
1046 return 0xFF808080;
1047 case CSSValueHighlight:
1048 return 0xFFB5D5FF;
1049 case CSSValueHighlighttext:
1050 return 0xFF000000;
1051 case CSSValueInactiveborder:
1052 return 0xFFFFFFFF;
1053 case CSSValueInactivecaption:
1054 return 0xFFFFFFFF;
1055 case CSSValueInactivecaptiontext:
1056 return 0xFF7F7F7F;
1057 case CSSValueInfobackground:
1058 return 0xFFFBFCC5;
1059 case CSSValueInfotext:
1060 return 0xFF000000;
1061 case CSSValueMenu:
1062 return 0xFFC0C0C0;
1063 case CSSValueMenutext:
1064 return 0xFF000000;
1065 case CSSValueScrollbar:
1066 return 0xFFFFFFFF;
1067 case CSSValueText:
1068 return 0xFF000000;
1069 case CSSValueThreeddarkshadow:
1070 return 0xFF666666;
1071 case CSSValueThreedface:
1072 return 0xFFC0C0C0;
1073 case CSSValueThreedhighlight:
1074 return 0xFFDDDDDD;
1075 case CSSValueThreedlightshadow:
1076 return 0xFFC0C0C0;
1077 case CSSValueThreedshadow:
1078 return 0xFF888888;
1079 case CSSValueWindow:
1080 return 0xFFFFFFFF;
1081 case CSSValueWindowframe:
1082 return 0xFFCCCCCC;
1083 case CSSValueWindowtext:
1084 return 0xFF000000;
1085 }
1086 return Color();
1087 }
1088
platformActiveTextSearchHighlightColor() const1089 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1090 {
1091 return Color(255, 150, 50); // Orange.
1092 }
1093
platformInactiveTextSearchHighlightColor() const1094 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1095 {
1096 return Color(255, 255, 0); // Yellow.
1097 }
1098
setCustomFocusRingColor(const Color & c)1099 void RenderTheme::setCustomFocusRingColor(const Color& c)
1100 {
1101 customFocusRingColor() = c;
1102 }
1103
focusRingColor()1104 Color RenderTheme::focusRingColor()
1105 {
1106 return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1107 }
1108
1109 } // namespace WebCore
1110