1 /*
2  * Copyright (C) 2007 Apple Inc.
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2008 Collabora Ltd.
5  * Copyright (C) 2008, 2009 Google Inc.
6  * Copyright (C) 2009 Kenneth Rohde Christiansen
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "config.h"
26 #include "RenderThemeChromiumLinux.h"
27 
28 #include "CSSValueKeywords.h"
29 #include "Color.h"
30 #include "PaintInfo.h"
31 #include "PlatformBridge.h"
32 #include "RenderObject.h"
33 #include "RenderProgress.h"
34 #include "RenderSlider.h"
35 #include "ScrollbarTheme.h"
36 #include "UserAgentStyleSheets.h"
37 
38 namespace WebCore {
39 
40 unsigned RenderThemeChromiumLinux::m_activeSelectionBackgroundColor =
41     0xff1e90ff;
42 unsigned RenderThemeChromiumLinux::m_activeSelectionForegroundColor =
43     Color::black;
44 unsigned RenderThemeChromiumLinux::m_inactiveSelectionBackgroundColor =
45     0xffc8c8c8;
46 unsigned RenderThemeChromiumLinux::m_inactiveSelectionForegroundColor =
47     0xff323232;
48 
49 double RenderThemeChromiumLinux::m_caretBlinkInterval;
50 
51 static const unsigned defaultButtonBackgroundColor = 0xffdddddd;
52 
getWebThemeState(const RenderTheme * theme,const RenderObject * o)53 static PlatformBridge::ThemePaintState getWebThemeState(const RenderTheme* theme, const RenderObject* o)
54 {
55     if (!theme->isEnabled(o))
56         return PlatformBridge::StateDisabled;
57     if (theme->isPressed(o))
58         return PlatformBridge::StatePressed;
59     if (theme->isHovered(o))
60         return PlatformBridge::StateHover;
61 
62     return PlatformBridge::StateNormal;
63 }
64 
65 
create()66 PassRefPtr<RenderTheme> RenderThemeChromiumLinux::create()
67 {
68     return adoptRef(new RenderThemeChromiumLinux());
69 }
70 
themeForPage(Page * page)71 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
72 {
73     static RenderTheme* rt = RenderThemeChromiumLinux::create().releaseRef();
74     return rt;
75 }
76 
RenderThemeChromiumLinux()77 RenderThemeChromiumLinux::RenderThemeChromiumLinux()
78 {
79     m_caretBlinkInterval = RenderTheme::caretBlinkInterval();
80 }
81 
~RenderThemeChromiumLinux()82 RenderThemeChromiumLinux::~RenderThemeChromiumLinux()
83 {
84 }
85 
systemColor(int cssValueId) const86 Color RenderThemeChromiumLinux::systemColor(int cssValueId) const
87 {
88     static const Color linuxButtonGrayColor(0xffdddddd);
89 
90     if (cssValueId == CSSValueButtonface)
91         return linuxButtonGrayColor;
92     return RenderTheme::systemColor(cssValueId);
93 }
94 
extraDefaultStyleSheet()95 String RenderThemeChromiumLinux::extraDefaultStyleSheet()
96 {
97     return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
98            String(themeChromiumLinuxUserAgentStyleSheet, sizeof(themeChromiumLinuxUserAgentStyleSheet));
99 }
100 
controlSupportsTints(const RenderObject * o) const101 bool RenderThemeChromiumLinux::controlSupportsTints(const RenderObject* o) const
102 {
103     return isEnabled(o);
104 }
105 
activeListBoxSelectionBackgroundColor() const106 Color RenderThemeChromiumLinux::activeListBoxSelectionBackgroundColor() const
107 {
108     return Color(0x28, 0x28, 0x28);
109 }
110 
activeListBoxSelectionForegroundColor() const111 Color RenderThemeChromiumLinux::activeListBoxSelectionForegroundColor() const
112 {
113     return Color::black;
114 }
115 
inactiveListBoxSelectionBackgroundColor() const116 Color RenderThemeChromiumLinux::inactiveListBoxSelectionBackgroundColor() const
117 {
118     return Color(0xc8, 0xc8, 0xc8);
119 }
120 
inactiveListBoxSelectionForegroundColor() const121 Color RenderThemeChromiumLinux::inactiveListBoxSelectionForegroundColor() const
122 {
123     return Color(0x32, 0x32, 0x32);
124 }
125 
platformActiveSelectionBackgroundColor() const126 Color RenderThemeChromiumLinux::platformActiveSelectionBackgroundColor() const
127 {
128     return m_activeSelectionBackgroundColor;
129 }
130 
platformInactiveSelectionBackgroundColor() const131 Color RenderThemeChromiumLinux::platformInactiveSelectionBackgroundColor() const
132 {
133     return m_inactiveSelectionBackgroundColor;
134 }
135 
platformActiveSelectionForegroundColor() const136 Color RenderThemeChromiumLinux::platformActiveSelectionForegroundColor() const
137 {
138     return m_activeSelectionForegroundColor;
139 }
140 
platformInactiveSelectionForegroundColor() const141 Color RenderThemeChromiumLinux::platformInactiveSelectionForegroundColor() const
142 {
143     return m_inactiveSelectionForegroundColor;
144 }
145 
adjustSliderThumbSize(RenderObject * o) const146 void RenderThemeChromiumLinux::adjustSliderThumbSize(RenderObject* o) const
147 {
148     IntSize size = PlatformBridge::getThemePartSize(PlatformBridge::PartSliderThumb);
149 
150     if (o->style()->appearance() == SliderThumbHorizontalPart) {
151         o->style()->setWidth(Length(size.width(), Fixed));
152         o->style()->setHeight(Length(size.height(), Fixed));
153     } else if (o->style()->appearance() == SliderThumbVerticalPart) {
154         o->style()->setWidth(Length(size.height(), Fixed));
155         o->style()->setHeight(Length(size.width(), Fixed));
156     } else
157         RenderThemeChromiumSkia::adjustSliderThumbSize(o);
158 }
159 
supportsControlTints() const160 bool RenderThemeChromiumLinux::supportsControlTints() const
161 {
162     return true;
163 }
164 
setCaretBlinkInterval(double interval)165 void RenderThemeChromiumLinux::setCaretBlinkInterval(double interval)
166 {
167     m_caretBlinkInterval = interval;
168 }
169 
caretBlinkIntervalInternal() const170 double RenderThemeChromiumLinux::caretBlinkIntervalInternal() const
171 {
172     return m_caretBlinkInterval;
173 }
174 
setSelectionColors(unsigned activeBackgroundColor,unsigned activeForegroundColor,unsigned inactiveBackgroundColor,unsigned inactiveForegroundColor)175 void RenderThemeChromiumLinux::setSelectionColors(
176     unsigned activeBackgroundColor,
177     unsigned activeForegroundColor,
178     unsigned inactiveBackgroundColor,
179     unsigned inactiveForegroundColor)
180 {
181     m_activeSelectionBackgroundColor = activeBackgroundColor;
182     m_activeSelectionForegroundColor = activeForegroundColor;
183     m_inactiveSelectionBackgroundColor = inactiveBackgroundColor;
184     m_inactiveSelectionForegroundColor = inactiveForegroundColor;
185 }
186 
paintCheckbox(RenderObject * o,const PaintInfo & i,const IntRect & rect)187 bool RenderThemeChromiumLinux::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
188 {
189     PlatformBridge::ThemePaintExtraParams extraParams;
190     extraParams.button.checked = isChecked(o);
191     extraParams.button.indeterminate = isIndeterminate(o);
192 
193     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartCheckbox, getWebThemeState(this, o), rect, &extraParams);
194     return false;
195 }
196 
setCheckboxSize(RenderStyle * style) const197 void RenderThemeChromiumLinux::setCheckboxSize(RenderStyle* style) const
198 {
199     // If the width and height are both specified, then we have nothing to do.
200     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
201         return;
202 
203     IntSize size = PlatformBridge::getThemePartSize(PlatformBridge::PartCheckbox);
204     setSizeIfAuto(style, size);
205 }
206 
paintRadio(RenderObject * o,const PaintInfo & i,const IntRect & rect)207 bool RenderThemeChromiumLinux::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
208 {
209     PlatformBridge::ThemePaintExtraParams extraParams;
210     extraParams.button.checked = isChecked(o);
211 
212     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartRadio, getWebThemeState(this, o), rect, &extraParams);
213     return false;
214 }
215 
setRadioSize(RenderStyle * style) const216 void RenderThemeChromiumLinux::setRadioSize(RenderStyle* style) const
217 {
218     // If the width and height are both specified, then we have nothing to do.
219     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
220         return;
221 
222     IntSize size = PlatformBridge::getThemePartSize(PlatformBridge::PartRadio);
223     setSizeIfAuto(style, size);
224 }
225 
paintButton(RenderObject * o,const PaintInfo & i,const IntRect & rect)226 bool RenderThemeChromiumLinux::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
227 {
228     PlatformBridge::ThemePaintExtraParams extraParams;
229     extraParams.button.isDefault = isDefault(o);
230     extraParams.button.hasBorder = true;
231     extraParams.button.backgroundColor = defaultButtonBackgroundColor;
232     if (o->hasBackground())
233         extraParams.button.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
234 
235     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartButton, getWebThemeState(this, o), rect, &extraParams);
236     return false;
237 }
238 
paintTextField(RenderObject * o,const PaintInfo & i,const IntRect & rect)239 bool RenderThemeChromiumLinux::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
240 {
241     // WebThemeEngine does not handle border rounded corner and background image
242     // so return true to draw CSS border and background.
243     if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage())
244         return true;
245 
246     ControlPart part = o->style()->appearance();
247 
248     PlatformBridge::ThemePaintExtraParams extraParams;
249     extraParams.textField.isTextArea = part == TextAreaPart;
250     extraParams.textField.isListbox = part == ListboxPart;
251 
252     // Fallback to white if the specified color object is invalid.
253     Color backgroundColor(Color::white);
254     if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
255         backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
256     extraParams.textField.backgroundColor = backgroundColor.rgb();
257 
258     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartTextField, getWebThemeState(this, o), rect, &extraParams);
259     return false;
260 }
261 
paintMenuList(RenderObject * o,const PaintInfo & i,const IntRect & rect)262 bool RenderThemeChromiumLinux::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
263 {
264     if (!o->isBox())
265         return false;
266 
267     const int right = rect.x() + rect.width();
268     const int middle = rect.y() + rect.height() / 2;
269 
270     PlatformBridge::ThemePaintExtraParams extraParams;
271     extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
272     extraParams.menuList.arrowY = middle;
273     const RenderBox* box = toRenderBox(o);
274     // Match Chromium Win behaviour of showing all borders if any are shown.
275     extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() || box->borderTop() || box->borderBottom();
276     extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
277     // Fallback to transparent if the specified color object is invalid.
278     extraParams.menuList.backgroundColor = Color::transparent;
279     if (o->hasBackground())
280         extraParams.menuList.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
281 
282     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartMenuList, getWebThemeState(this, o), rect, &extraParams);
283     return false;
284 }
285 
paintSliderTrack(RenderObject * o,const PaintInfo & i,const IntRect & rect)286 bool RenderThemeChromiumLinux::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& rect)
287 {
288     PlatformBridge::ThemePaintExtraParams extraParams;
289     extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart;
290 
291     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartSliderTrack, getWebThemeState(this, o), rect, &extraParams);
292     return false;
293 }
294 
paintSliderThumb(RenderObject * o,const PaintInfo & i,const IntRect & rect)295 bool RenderThemeChromiumLinux::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
296 {
297     PlatformBridge::ThemePaintExtraParams extraParams;
298     extraParams.slider.vertical = o->style()->appearance() == SliderThumbVerticalPart;
299     extraParams.slider.inDrag = toRenderSlider(o->parent())->inDragMode();
300 
301     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartSliderThumb, getWebThemeState(this, o), rect, &extraParams);
302     return false;
303 }
304 
adjustInnerSpinButtonStyle(CSSStyleSelector *,RenderStyle * style,Element *) const305 void RenderThemeChromiumLinux::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
306 {
307     IntSize size = PlatformBridge::getThemePartSize(PlatformBridge::PartInnerSpinButton);
308 
309     style->setWidth(Length(size.width(), Fixed));
310     style->setMinWidth(Length(size.width(), Fixed));
311 }
312 
paintInnerSpinButton(RenderObject * o,const PaintInfo & i,const IntRect & rect)313 bool RenderThemeChromiumLinux::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
314 {
315     PlatformBridge::ThemePaintExtraParams extraParams;
316     extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState);
317     extraParams.innerSpin.readOnly = isReadOnlyControl(o);
318 
319     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartInnerSpinButton, getWebThemeState(this, o), rect, &extraParams);
320     return false;
321 }
322 
323 #if ENABLE(PROGRESS_TAG)
324 
paintProgressBar(RenderObject * o,const PaintInfo & i,const IntRect & rect)325 bool RenderThemeChromiumLinux::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& rect)
326 {
327     if (!o->isProgress())
328         return true;
329 
330     RenderProgress* renderProgress = toRenderProgress(o);
331     IntRect valueRect = progressValueRectFor(renderProgress, rect);
332 
333     PlatformBridge::ThemePaintExtraParams extraParams;
334     extraParams.progressBar.determinate = renderProgress->isDeterminate();
335     extraParams.progressBar.valueRectX = valueRect.x();
336     extraParams.progressBar.valueRectY = valueRect.y();
337     extraParams.progressBar.valueRectWidth = valueRect.width();
338     extraParams.progressBar.valueRectHeight = valueRect.height();
339 
340     PlatformBridge::paintThemePart(i.context, PlatformBridge::PartProgressBar, getWebThemeState(this, o), rect, &extraParams);
341     return false;
342 }
343 
344 #endif
345 
346 } // namespace WebCore
347