summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/rendering/RenderThemeChromiumWin.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/rendering/RenderThemeChromiumWin.cpp')
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumWin.cpp770
1 files changed, 770 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
new file mode 100644
index 0000000..be670ff
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -0,0 +1,770 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumWin.h"
+
+#include <windows.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+
+#include "CSSValueKeywords.h"
+#include "ChromiumBridge.h"
+#include "CurrentTime.h"
+#include "FontSelector.h"
+#include "FontUtilsChromiumWin.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "MediaControlElements.h"
+#include "RenderBox.h"
+#include "RenderProgress.h"
+#include "RenderSlider.h"
+#include "ScrollbarTheme.h"
+#include "TransparencyWin.h"
+#include "WindowsVersion.h"
+
+// FIXME: This dependency should eventually be removed.
+#include <skia/ext/skia_utils_win.h>
+
+#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
+ offsetof(structName, member) + \
+ (sizeof static_cast<structName*>(0)->member)
+#define NONCLIENTMETRICS_SIZE_PRE_VISTA \
+ SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
+
+namespace WebCore {
+
+// The standard width for the menu list drop-down button when run under
+// layout test mode. Use the value that's currently captured in most baselines.
+static const int kStandardMenuListButtonWidth = 17;
+
+namespace {
+class ThemePainter {
+public:
+ ThemePainter(GraphicsContext* context, const IntRect& r)
+ {
+ TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM());
+ m_helper.init(context, getLayerMode(context, transformMode), transformMode, r);
+
+ if (!m_helper.context()) {
+ // TransparencyWin doesn't have well-defined copy-ctor nor op=()
+ // so we re-initialize it instead of assigning a fresh istance.
+ // On the reinitialization, we fallback to use NoLayer mode.
+ // Note that the original initialization failure can be caused by
+ // a failure of an internal buffer allocation and NoLayer mode
+ // does not have such buffer allocations.
+ m_helper.~TransparencyWin();
+ new (&m_helper) TransparencyWin();
+ m_helper.init(context, TransparencyWin::NoLayer, transformMode, r);
+ }
+ }
+
+ ~ThemePainter()
+ {
+ m_helper.composite();
+ }
+
+ GraphicsContext* context() { return m_helper.context(); }
+ const IntRect& drawRect() { return m_helper.drawRect(); }
+
+private:
+
+ static bool canvasHasMultipleLayers(const SkCanvas* canvas)
+ {
+ SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
+ iter.next(); // There is always at least one layer.
+ return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
+ }
+
+ static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
+ {
+ if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
+ return TransparencyWin::WhiteLayer;
+ if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help.
+ return TransparencyWin::OpaqueCompositeLayer;
+ // Nothing interesting.
+ return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
+ }
+
+ static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix)
+ {
+ if (matrix.b() || matrix.c()) // Skew.
+ return TransparencyWin::Untransform;
+ if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
+ return TransparencyWin::ScaleTransform;
+ // Nothing interesting.
+ return TransparencyWin::KeepTransform;
+ }
+
+ TransparencyWin m_helper;
+};
+
+} // namespace
+
+static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
+{
+ static UINT size = isVistaOrNewer() ?
+ sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
+ metrics->cbSize = size;
+ bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
+ ASSERT(success);
+}
+
+static FontDescription smallSystemFont;
+static FontDescription menuFont;
+static FontDescription labelFont;
+
+// Internal static helper functions. We don't put them in an anonymous
+// namespace so they have easier access to the WebCore namespace.
+
+static bool supportsFocus(ControlPart appearance)
+{
+ switch (appearance) {
+ case PushButtonPart:
+ case ButtonPart:
+ case DefaultButtonPart:
+ case SearchFieldPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ return true;
+ }
+ return false;
+}
+
+// Return the height of system font |font| in pixels. We use this size by
+// default for some non-form-control elements.
+static float systemFontSize(const LOGFONT& font)
+{
+ float size = -font.lfHeight;
+ if (size < 0) {
+ HFONT hFont = CreateFontIndirect(&font);
+ if (hFont) {
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ if (hdc) {
+ HGDIOBJ hObject = SelectObject(hdc, hFont);
+ TEXTMETRIC tm;
+ GetTextMetrics(hdc, &tm);
+ SelectObject(hdc, hObject);
+ ReleaseDC(0, hdc);
+ size = tm.tmAscent;
+ }
+ DeleteObject(hFont);
+ }
+ }
+
+ // The "codepage 936" bit here is from Gecko; apparently this helps make
+ // fonts more legible in Simplified Chinese where the default font size is
+ // too small.
+ //
+ // FIXME: http://b/1119883 Since this is only used for "small caption",
+ // "menu", and "status bar" objects, I'm not sure how much this even
+ // matters. Plus the Gecko patch went in back in 2002, and maybe this
+ // isn't even relevant anymore. We should investigate whether this should
+ // be removed, or perhaps broadened to be "any CJK locale".
+ //
+ return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
+}
+
+// Converts |points| to pixels. One point is 1/72 of an inch.
+static float pointsToPixels(float points)
+{
+ static float pixelsPerInch = 0.0f;
+ if (!pixelsPerInch) {
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ if (hdc) { // Can this ever actually be NULL?
+ pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(0, hdc);
+ } else {
+ pixelsPerInch = 96.0f;
+ }
+ }
+
+ static const float pointsPerInch = 72.0f;
+ return points / pointsPerInch * pixelsPerInch;
+}
+
+static double querySystemBlinkInterval(double defaultInterval)
+{
+ UINT blinkTime = GetCaretBlinkTime();
+ if (!blinkTime)
+ return defaultInterval;
+ if (blinkTime == INFINITE)
+ return 0;
+ return blinkTime / 1000.0;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
+{
+ return adoptRef(new RenderThemeChromiumWin);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumWin::create().releaseRef();
+ return rt;
+}
+
+bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
+{
+ // Let webkit draw one of its halo rings around any focused element,
+ // except push buttons. For buttons we use the windows PBS_DEFAULTED
+ // styling to give it a blue border.
+ return style->appearance() == ButtonPart
+ || style->appearance() == PushButtonPart;
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0x00, 0x00, 0xff); // Royal blue.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0x99, 0x99, 0x99); // Medium gray.
+ COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0xff, 0xff, 0xcc); // Pale yellow.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
+{
+ return Color(0xff, 0x96, 0x32); // Orange.
+}
+
+Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
+{
+ return Color(0xff, 0xff, 0x96); // Yellow.
+}
+
+void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const
+{
+ // This logic owes much to RenderThemeSafari.cpp.
+ FontDescription* cachedDesc = 0;
+ AtomicString faceName;
+ float fontSize = 0;
+ switch (propId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont;
+ if (!smallSystemFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfSmCaptionFont);
+ }
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont;
+ if (!menuFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfMenuFont);
+ }
+ break;
+ case CSSValueStatusBar:
+ cachedDesc = &labelFont;
+ if (!labelFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = metrics.lfStatusFont.lfFaceName;
+ fontSize = systemFontSize(metrics.lfStatusFont);
+ }
+ break;
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ faceName = defaultGUIFont();
+ // Why 2 points smaller? Because that's what Gecko does.
+ fontSize = defaultFontSize - pointsToPixels(2);
+ break;
+ default:
+ faceName = defaultGUIFont();
+ fontSize = defaultFontSize;
+ break;
+ }
+
+ if (!cachedDesc)
+ cachedDesc = &fontDescription;
+
+ if (fontSize) {
+ cachedDesc->firstFamily().setFamily(faceName);
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->setSpecifiedSize(fontSize);
+ cachedDesc->setWeight(FontWeightNormal);
+ cachedDesc->setItalic(false);
+ }
+ fontDescription = *cachedDesc;
+}
+
+// Map a CSSValue* system color to an index understood by GetSysColor().
+static int cssValueIdToSysColorIndex(int cssValueId)
+{
+ switch (cssValueId) {
+ case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
+ case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
+ case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
+ case CSSValueBackground: return COLOR_BACKGROUND;
+ case CSSValueButtonface: return COLOR_BTNFACE;
+ case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
+ case CSSValueButtonshadow: return COLOR_BTNSHADOW;
+ case CSSValueButtontext: return COLOR_BTNTEXT;
+ case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
+ case CSSValueGraytext: return COLOR_GRAYTEXT;
+ case CSSValueHighlight: return COLOR_HIGHLIGHT;
+ case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
+ case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
+ case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
+ case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
+ case CSSValueInfobackground: return COLOR_INFOBK;
+ case CSSValueInfotext: return COLOR_INFOTEXT;
+ case CSSValueMenu: return COLOR_MENU;
+ case CSSValueMenutext: return COLOR_MENUTEXT;
+ case CSSValueScrollbar: return COLOR_SCROLLBAR;
+ case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
+ case CSSValueThreedface: return COLOR_3DFACE;
+ case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
+ case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
+ case CSSValueThreedshadow: return COLOR_3DSHADOW;
+ case CSSValueWindow: return COLOR_WINDOW;
+ case CSSValueWindowframe: return COLOR_WINDOWFRAME;
+ case CSSValueWindowtext: return COLOR_WINDOWTEXT;
+ default: return -1; // Unsupported CSSValue
+ }
+}
+
+Color RenderThemeChromiumWin::systemColor(int cssValueId) const
+{
+ int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
+ if (ChromiumBridge::layoutTestMode() || (sysColorIndex == -1))
+ return RenderTheme::systemColor(cssValueId);
+
+ COLORREF color = GetSysColor(sysColorIndex);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color));
+}
+
+void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const
+{
+ // These sizes match what WinXP draws for various menus.
+ const int sliderThumbAlongAxis = 11;
+ const int sliderThumbAcrossAxis = 21;
+ if (o->style()->appearance() == SliderThumbHorizontalPart) {
+ o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed));
+ o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed));
+ } else if (o->style()->appearance() == SliderThumbVerticalPart) {
+ o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed));
+ o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed));
+ } else
+ RenderThemeChromiumSkia::adjustSliderThumbSize(o);
+}
+
+bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintButton(o, i, r);
+}
+bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintButton(o, i, r);
+}
+
+bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ const ThemeData& themeData = getThemeData(o);
+
+ ThemePainter painter(i.context, r);
+ ChromiumBridge::paintButton(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect());
+ return false;
+}
+
+bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintTextFieldInternal(o, i, r, true);
+}
+
+bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ const ThemeData& themeData = getThemeData(o);
+
+ ThemePainter painter(i.context, r);
+ ChromiumBridge::paintTrackbar(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect());
+ return false;
+}
+
+bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintSliderTrack(o, i, r);
+}
+
+static int menuListButtonWidth()
+{
+ static int width = ChromiumBridge::layoutTestMode() ? kStandardMenuListButtonWidth : GetSystemMetrics(SM_CXVSCROLL);
+ return width;
+}
+
+// Used to paint unstyled menulists (i.e. with the default border)
+bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ if (!o->isBox())
+ return false;
+
+ const RenderBox* box = toRenderBox(o);
+ int borderRight = box->borderRight();
+ int borderLeft = box->borderLeft();
+ int borderTop = box->borderTop();
+ int borderBottom = box->borderBottom();
+
+ // If all the borders are 0, then tell skia not to paint the border on the
+ // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not
+ // draw individual borders and then pass that to skia so we can avoid
+ // drawing any borders that are set to 0. For non-zero borders, we draw the
+ // border, but webkit just draws over it.
+ bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom);
+
+ paintTextFieldInternal(o, i, r, drawEdges);
+
+ // Take padding and border into account. If the MenuList is smaller than
+ // the size of a button, make sure to shrink it appropriately and not put
+ // its x position to the left of the menulist.
+ const int buttonWidth = menuListButtonWidth();
+ int spacingLeft = borderLeft + box->paddingLeft();
+ int spacingRight = borderRight + box->paddingRight();
+ int spacingTop = borderTop + box->paddingTop();
+ int spacingBottom = borderBottom + box->paddingBottom();
+
+ int buttonX;
+ if (r.right() - r.x() < buttonWidth)
+ buttonX = r.x();
+ else
+ buttonX = o->style()->direction() == LTR ? r.right() - spacingRight - buttonWidth : r.x() + spacingLeft;
+
+ // Compute the rectangle of the button in the destination image.
+ IntRect rect(buttonX,
+ r.y() + spacingTop,
+ std::min(buttonWidth, r.right() - r.x()),
+ r.height() - (spacingTop + spacingBottom));
+
+ // Get the correct theme data for a textfield and paint the menu.
+ ThemePainter painter(i.context, rect);
+ ChromiumBridge::paintMenuList(painter.context(),
+ CP_DROPDOWNBUTTON,
+ determineState(o),
+ determineClassicState(o),
+ painter.drawRect());
+ return false;
+}
+
+// static
+void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
+{
+ RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
+
+ // Reset cached fonts.
+ smallSystemFont = menuFont = labelFont = FontDescription();
+}
+
+double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
+{
+ // This involves a system call, so we cache the result.
+ static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+ return blinkInterval;
+}
+
+unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart)
+{
+ unsigned result = TS_NORMAL;
+ ControlPart appearance = o->style()->appearance();
+ if (!isEnabled(o))
+ result = TS_DISABLED;
+ else if (isReadOnlyControl(o))
+ result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED;
+ // Active overrides hover and focused.
+ else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
+ result = TS_PRESSED;
+ else if (supportsFocus(appearance) && isFocused(o))
+ result = ETS_FOCUSED;
+ else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
+ result = TS_HOT;
+
+ // CBS_UNCHECKED*: 1-4
+ // CBS_CHECKED*: 5-8
+ // CBS_MIXED*: 9-12
+ if (isIndeterminate(o))
+ result += 8;
+ else if (isChecked(o))
+ result += 4;
+ return result;
+}
+
+unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
+{
+ unsigned result = TUS_NORMAL;
+ if (!isEnabled(o->parent()))
+ result = TUS_DISABLED;
+ else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
+ result = TUS_FOCUSED;
+ else if (toRenderSlider(o->parent())->inDragMode())
+ result = TUS_PRESSED;
+ else if (isHovered(o))
+ result = TUS_HOT;
+ return result;
+}
+
+unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart)
+{
+ unsigned result = 0;
+
+ ControlPart part = o->style()->appearance();
+
+ // Sliders are always in the normal state.
+ if (part == SliderHorizontalPart || part == SliderVerticalPart)
+ return result;
+
+ // So are readonly text fields.
+ if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart))
+ return result;
+
+ if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
+ if (!isEnabled(o->parent()))
+ result = DFCS_INACTIVE;
+ else if (toRenderSlider(o->parent())->inDragMode()) // Active supersedes hover
+ result = DFCS_PUSHED;
+ else if (isHovered(o))
+ result = DFCS_HOT;
+ } else {
+ if (!isEnabled(o) || isReadOnlyControl(o))
+ result = DFCS_INACTIVE;
+ // Active supersedes hover
+ else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
+ result = DFCS_PUSHED;
+ else if (supportsFocus(part) && isFocused(o)) // So does focused
+ result = 0;
+ else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
+ result = DFCS_HOT;
+ // Classic theme can't represent indeterminate states. Use unchecked appearance.
+ if (isChecked(o) && !isIndeterminate(o))
+ result |= DFCS_CHECKED;
+ }
+ return result;
+}
+
+ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart)
+{
+ ThemeData result;
+ switch (o->style()->appearance()) {
+ case CheckboxPart:
+ result.m_part = BP_CHECKBOX;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONCHECK;
+ break;
+ case RadioPart:
+ result.m_part = BP_RADIOBUTTON;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONRADIO;
+ break;
+ case PushButtonPart:
+ case ButtonPart:
+ result.m_part = BP_PUSHBUTTON;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONPUSH;
+ break;
+ case SliderHorizontalPart:
+ result.m_part = TKP_TRACK;
+ result.m_state = TRS_NORMAL;
+ break;
+ case SliderVerticalPart:
+ result.m_part = TKP_TRACKVERT;
+ result.m_state = TRVS_NORMAL;
+ break;
+ case SliderThumbHorizontalPart:
+ result.m_part = TKP_THUMBBOTTOM;
+ result.m_state = determineSliderThumbState(o);
+ break;
+ case SliderThumbVerticalPart:
+ result.m_part = TKP_THUMBVERT;
+ result.m_state = determineSliderThumbState(o);
+ break;
+ case ListboxPart:
+ case MenulistPart:
+ case MenulistButtonPart:
+ case SearchFieldPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ result.m_part = EP_EDITTEXT;
+ result.m_state = determineState(o);
+ break;
+ case InnerSpinButtonPart:
+ result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
+ result.m_state = determineState(o, subPart);
+ result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
+ break;
+ }
+
+ result.m_classicState |= determineClassicState(o, subPart);
+
+ return result;
+}
+
+bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
+ const PaintInfo& i,
+ const IntRect& r,
+ bool drawEdges)
+{
+ // Fallback to white if the specified color object is invalid.
+ // (Note ChromiumBridge::paintTextField duplicates this check).
+ Color backgroundColor(Color::white);
+ if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
+ backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+
+ // If we have background-image, don't fill the content area to expose the
+ // parent's background. Also, we shouldn't fill the content area if the
+ // alpha of the color is 0. The API of Windows GDI ignores the alpha.
+ //
+ // Note that we should paint the content area white if we have neither the
+ // background color nor background image explicitly specified to keep the
+ // appearance of select element consistent with other browsers.
+ bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
+
+ if (o->style()->hasBorderRadius()) {
+ // If the style has rounded borders, setup the context to clip the
+ // background (themed or filled) appropriately.
+ // FIXME: make sure we do the right thing if css background-clip is set.
+ i.context->save();
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+ o->style()->getBorderRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight);
+ i.context->addRoundedRectClip(r, topLeft, topRight, bottomLeft, bottomRight);
+ }
+ {
+ const ThemeData& themeData = getThemeData(o);
+ ThemePainter painter(i.context, r);
+ ChromiumBridge::paintTextField(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect(),
+ backgroundColor,
+ fillContentArea,
+ drawEdges);
+ // End of block commits the painter before restoring context.
+ }
+ if (o->style()->hasBorderRadius())
+ i.context->restore();
+ return false;
+}
+
+void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ int width = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+ style->setWidth(Length(width, Fixed));
+ style->setMinWidth(Length(width, Fixed));
+}
+
+bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ IntRect half = rect;
+
+ half.setHeight(rect.height() / 2);
+ const ThemeData& upThemeData = getThemeData(object, SpinButtonUp);
+ ThemePainter upPainter(info.context, half);
+ ChromiumBridge::paintSpinButton(upPainter.context(),
+ upThemeData.m_part,
+ upThemeData.m_state,
+ upThemeData.m_classicState,
+ upPainter.drawRect());
+
+ half.setY(rect.y() + rect.height() / 2);
+ const ThemeData& downThemeData = getThemeData(object, SpinButtonDown);
+ ThemePainter downPainter(info.context, half);
+ ChromiumBridge::paintSpinButton(downPainter.context(),
+ downThemeData.m_part,
+ downThemeData.m_state,
+ downThemeData.m_classicState,
+ downPainter.drawRect());
+ return false;
+}
+
+#if ENABLE(PROGRESS_TAG)
+
+// MSDN says that update intervals for the bar is 30ms.
+// http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx
+static const double progressAnimationFrameRate = 0.033;
+
+double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+ return progressAnimationFrameRate;
+}
+
+double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+ // On Chromium Windows port, animationProgress() and associated values aren't used.
+ // So here we can return arbitrary positive value.
+ return progressAnimationFrameRate;
+}
+
+void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ if (!o->isProgress())
+ return true;
+
+ RenderProgress* renderProgress = toRenderProgress(o);
+ // For indeterminate bar, valueRect is ignored and it is computed by the theme engine
+ // because the animation is a platform detail and WebKit doesn't need to know how.
+ IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0);
+ double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0;
+ ThemePainter painter(i.context, r);
+ ChromiumBridge::paintProgressBar(painter.context(), r, valueRect, renderProgress->isDeterminate(), animatedSeconds);
+ return false;
+}
+
+#endif
+
+} // namespace WebCore