blob: d1bc89c356017d77fa135a5616a470e81fd77021 [file] [log] [blame]
/*
* This file is part of the WebKit project.
*
* Copyright (C) 2006 Apple Computer, Inc.
*
* 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 "RenderThemeWin.h"
#include <windows.h>
#include <uxtheme.h>
#include <vssym32.h>
#include "CSSValueKeywords.h"
#include "Document.h"
#include "FontSelector.h"
#include "GraphicsContext.h"
#include "PlatformScrollBar.h"
#include "SkiaUtils.h"
#include "base/gfx/native_theme.h"
#include "base/gfx/font_utils.h"
#include "base/win_util.h"
#include "webkit/glue/webkit_glue.h"
// These enums correspond to similarly named values defined by SafariTheme.h
enum ControlSize {
RegularControlSize,
SmallControlSize,
MiniControlSize
};
enum PaddingType {
TopPadding,
RightPadding,
BottomPadding,
LeftPadding
};
namespace {
const int kDefaultButtonPadding = 2;
// These magic numbers come from Apple's version of RenderThemeWin.cpp.
const int kMenuListPadding[4] = { 1, 2, 1, 2 };
// The kLayoutTest* constants are metrics used only in layout test mode,
// so as to match RenderThemeMac.mm and to remain consistent despite any
// theme or font changes.
const int kLayoutTestControlHeight[3] = { 21, 18, 15 };
const int kLayoutTestButtonPadding[4] = { 0, 8, 0, 8 };
const int kLayoutTestStyledMenuListInternalPadding[4] = { 1, 0, 2, 8 };
const int kLayoutTestMenuListInternalPadding[3][4] =
{
{ 2, 26, 3, 8 },
{ 2, 23, 3, 8 },
{ 2, 22, 3, 10 }
};
const int kLayoutTestMenuListMinimumWidth[3] = { 9, 5, 0 };
const float kLayoutTestBaseFontSize = 11.0f;
const float kLayoutTestStatusBarFontSize = 10.0f;
const float kLayoutTestSystemFontSize = 13.0f;
const int kLayoutTestSliderThumbWidth = 15;
const int kLayoutTestSliderThumbHeight = 15;
const int kLayoutTestMenuListButtonWidth = 15;
const int kLayoutTestButtonMinHeight = 15;
const int kLayoutTestSearchFieldHeight[3] = { 22, 19, 17 };
const int kLayoutTestEmptyResultsOffset = 9;
const int kLayoutTestResultsArrowWidth = 5;
const short kLayoutTestSearchFieldBorderWidth = 2;
const int kLayoutTestSearchFieldPadding = 1;
// Constants that are used in non-layout-test mode.
const int kStyledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
// The default variable-width font size. We use this as the default font
// size for the "system font", and as a base size (which we then shrink) for
// form control fonts.
float DefaultFontSize = 16.0;
WebCore::FontDescription SmallSystemFont;
WebCore::FontDescription MenuFont;
WebCore::FontDescription LabelFont;
}
namespace WebCore {
static void setFixedPadding(RenderStyle* style, const int padding[4])
{
style->setPaddingLeft(Length(padding[LeftPadding], Fixed));
style->setPaddingRight(Length(padding[RightPadding], Fixed));
style->setPaddingTop(Length(padding[TopPadding], Fixed));
style->setPaddingBottom(Length(padding[BottomPadding], Fixed));
}
// This is logic from RenderThemeMac.mm, and is used by layout test mode.
static ControlSize controlSizeForFont(RenderStyle* style)
{
if (style->fontSize() >= 16) {
return RegularControlSize;
} else if (style->fontSize() >= 11) {
return SmallControlSize;
}
return MiniControlSize;
}
RenderTheme* theme()
{
static RenderThemeWin winTheme;
return &winTheme;
}
RenderThemeWin::RenderThemeWin()
{
}
RenderThemeWin::~RenderThemeWin()
{
}
Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
{
if (webkit_glue::IsLayoutTestMode())
return Color("#0000FF"); // Royal blue
COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
{
if (webkit_glue::IsLayoutTestMode())
return Color("#999999"); // Medium grey
COLORREF color = GetSysColor(COLOR_GRAYTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
Color RenderThemeWin::platformActiveSelectionForegroundColor() const
{
if (webkit_glue::IsLayoutTestMode())
return Color("#FFFFCC"); // Pale yellow
COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
}
Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
{
return Color::white;
}
static float systemFontSizeForControlSize(ControlSize controlSize)
{
static float sizes[] = { 13.0f, 11.0f, 9.0f };
return sizes[controlSize];
}
// This is basically RenderThemeMac::setFontFromControlSize
static int layoutTestSetFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style)
{
FontDescription fontDescription;
fontDescription.setIsAbsoluteSize(true);
fontDescription.setGenericFamily(FontDescription::SerifFamily);
float fontSize = systemFontSizeForControlSize(controlSizeForFont(style));
fontDescription.firstFamily().setFamily("Lucida Grande");
fontDescription.setComputedSize(fontSize);
fontDescription.setSpecifiedSize(fontSize);
// Reset line height
style->setLineHeight(RenderStyle::initialLineHeight());
style->setFontDescription(fontDescription);
style->font().update(0);
return 0;
}
// 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.
// TODO(pkasting): 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;
}
// We aim to match IE here.
// -IE uses a font based on the encoding as the default font for form controls.
// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
// which returns MS Shell Dlg)
// -Safari uses Lucida Grande.
//
// TODO(ojan): Fix this!
// The only case where we know we don't match IE is for ANSI encodings. IE uses
// MS Shell Dlg there, which we render incorrectly at certain pixel sizes
// (e.g. 15px). So, for now we just use Arial.
static wchar_t* defaultGUIFont(Document* document)
{
UScriptCode dominantScript = document->dominantScript();
const wchar_t* family = NULL;
// TODO(jungshik) : Special-casing of Latin/Greeek/Cyrillic should go away
// once GetFontFamilyForScript is enhanced to support GenericFamilyType for real.
// For now, we make sure that we use Arial to match IE for those scripts.
if (dominantScript != USCRIPT_LATIN && dominantScript != USCRIPT_CYRILLIC &&
dominantScript != USCRIPT_GREEK && dominantScript != USCRIPT_INVALID_CODE) {
family = gfx::GetFontFamilyForScript(dominantScript,
gfx::GENERIC_FAMILY_NONE);
if (family)
return const_cast<wchar_t*>(family);
}
return L"Arial";
}
// 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 POINTS_PER_INCH = 72.0f;
return points / POINTS_PER_INCH * pixelsPerInch;
}
double RenderThemeWin::caretBlinkFrequency() const
{
// Disable the blinking caret in layout test mode, as it introduces
// a race condition for the pixel tests. http://b/1198440
if (webkit_glue::IsLayoutTestMode())
return 0;
// TODO(ericroman): this should be using the platform's blink frequency.
return RenderTheme::caretBlinkFrequency();
}
void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& fontDescription) const
{
// This logic owes much to RenderThemeSafari.cpp.
FontDescription* cachedDesc = NULL;
wchar_t* faceName = 0;
float fontSize = 0;
switch (propId) {
case CSSValueSmallCaption:
cachedDesc = &SmallSystemFont;
if (!SmallSystemFont.isAbsoluteSize()) {
if (webkit_glue::IsLayoutTestMode()) {
fontSize = systemFontSizeForControlSize(SmallControlSize);
} else {
NONCLIENTMETRICS metrics;
win_util::GetNonClientMetrics(&metrics);
faceName = metrics.lfSmCaptionFont.lfFaceName;
fontSize = systemFontSize(metrics.lfSmCaptionFont);
}
}
break;
case CSSValueMenu:
cachedDesc = &MenuFont;
if (!MenuFont.isAbsoluteSize()) {
if (webkit_glue::IsLayoutTestMode()) {
fontSize = systemFontSizeForControlSize(RegularControlSize);
} else {
NONCLIENTMETRICS metrics;
win_util::GetNonClientMetrics(&metrics);
faceName = metrics.lfMenuFont.lfFaceName;
fontSize = systemFontSize(metrics.lfMenuFont);
}
}
break;
case CSSValueStatusBar:
cachedDesc = &LabelFont;
if (!LabelFont.isAbsoluteSize()) {
if (webkit_glue::IsLayoutTestMode()) {
fontSize = kLayoutTestStatusBarFontSize;
} else {
NONCLIENTMETRICS metrics;
win_util::GetNonClientMetrics(&metrics);
faceName = metrics.lfStatusFont.lfFaceName;
fontSize = systemFontSize(metrics.lfStatusFont);
}
}
break;
case CSSValueWebkitMiniControl:
if (webkit_glue::IsLayoutTestMode()) {
fontSize = systemFontSizeForControlSize(MiniControlSize);
} else {
faceName = defaultGUIFont(document);
// Why 2 points smaller? Because that's what Gecko does.
// Also see 2 places below.
fontSize = DefaultFontSize - pointsToPixels(2);
}
break;
case CSSValueWebkitSmallControl:
if (webkit_glue::IsLayoutTestMode()) {
fontSize = systemFontSizeForControlSize(SmallControlSize);
} else {
faceName = defaultGUIFont(document);
fontSize = DefaultFontSize - pointsToPixels(2);
}
break;
case CSSValueWebkitControl:
if (webkit_glue::IsLayoutTestMode()) {
fontSize = systemFontSizeForControlSize(RegularControlSize);
} else {
faceName = defaultGUIFont(document);
fontSize = DefaultFontSize - pointsToPixels(2);
}
break;
default:
if (webkit_glue::IsLayoutTestMode()) {
fontSize = kLayoutTestSystemFontSize;
} else {
faceName = defaultGUIFont(document);
fontSize = DefaultFontSize;
}
}
if (!cachedDesc)
cachedDesc = &fontDescription;
if (fontSize) {
if (webkit_glue::IsLayoutTestMode()) {
cachedDesc->firstFamily().setFamily("Lucida Grande");
} else {
ASSERT(faceName);
cachedDesc->firstFamily().setFamily(AtomicString(faceName,
wcslen(faceName)));
}
cachedDesc->setIsAbsoluteSize(true);
cachedDesc->setGenericFamily(FontDescription::NoFamily);
cachedDesc->setSpecifiedSize(fontSize);
cachedDesc->setWeight(FontWeightNormal);
cachedDesc->setItalic(false);
}
fontDescription = *cachedDesc;
}
bool RenderThemeWin::supportsFocus(EAppearance appearance)
{
switch (appearance) {
case PushButtonAppearance:
case ButtonAppearance:
case TextFieldAppearance:
case TextAreaAppearance:
return true;
default:
return false;
}
return false;
}
bool RenderThemeWin::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() == ButtonAppearance ||
style->appearance() == PushButtonAppearance;
}
unsigned RenderThemeWin::determineState(RenderObject* o)
{
unsigned result = TS_NORMAL;
if (!isEnabled(o))
result = TS_DISABLED;
else if (isReadOnlyControl(o))
result = ETS_READONLY; // Readonly is supported on textfields.
else if (supportsFocus(o->style()->appearance()) && isFocused(o))
result = TS_CHECKED;
else if (isPressed(o)) // Active overrides hover.
result = TS_PRESSED;
else if (isHovered(o))
result = TS_HOT;
if (isChecked(o))
result += 4; // 4 unchecked states, 4 checked states.
return result;
}
unsigned RenderThemeWin::determineClassicState(RenderObject* o)
{
unsigned result = 0;
if (!isEnabled(o) || isReadOnlyControl(o))
result = DFCS_INACTIVE;
else if (isPressed(o)) // Active supersedes hover
result = DFCS_PUSHED;
else if (isHovered(o))
result = DFCS_HOT;
if (isChecked(o))
result |= DFCS_CHECKED;
return result;
}
ThemeData RenderThemeWin::getThemeData(RenderObject* o)
{
ThemeData result;
switch (o->style()->appearance()) {
case PushButtonAppearance:
case ButtonAppearance:
result.m_part = BP_PUSHBUTTON;
result.m_classicState = DFCS_BUTTONPUSH;
break;
case CheckboxAppearance:
result.m_part = BP_CHECKBOX;
result.m_classicState = DFCS_BUTTONCHECK;
break;
case RadioAppearance:
result.m_part = BP_RADIOBUTTON;
result.m_classicState = DFCS_BUTTONRADIO;
break;
case ListboxAppearance:
case MenulistAppearance:
case TextFieldAppearance:
case TextAreaAppearance:
result.m_part = ETS_NORMAL;
break;
}
result.m_state = determineState(o);
result.m_classicState |= determineClassicState(o);
return result;
}
bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
// Get the correct theme data for a button and paint the button.
i.context->platformContext()->paintButton(r, getThemeData(o));
return false;
}
static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
{
if (style->width().isIntrinsicOrAuto())
style->setWidth(Length(size.width(), Fixed));
if (style->height().isAuto())
style->setHeight(Length(size.height(), Fixed));
}
int RenderThemeWin::minimumMenuListSize(RenderStyle* style) const
{
if (webkit_glue::IsLayoutTestMode()) {
return kLayoutTestMenuListMinimumWidth[controlSizeForFont(style)];
} else {
return 0;
}
}
static IntSize layoutTestCheckboxSize(RenderStyle* style)
{
static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
return sizes[controlSizeForFont(style)];
}
static IntSize layoutTestRadioboxSize(RenderStyle* style)
{
static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
return sizes[controlSizeForFont(style)];
}
void RenderThemeWin::setCheckboxSize(RenderStyle* style) const
{
// If the width and height are both specified, then we have nothing to do.
if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
return;
// FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox.
// At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
// the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
// metrics.
const IntSize size = webkit_glue::IsLayoutTestMode() ?
layoutTestCheckboxSize(style) : IntSize(13, 13);
setSizeIfAuto(style, size);
}
void RenderThemeWin::setRadioSize(RenderStyle* style) const
{
if (webkit_glue::IsLayoutTestMode()) {
setSizeIfAuto(style, layoutTestRadioboxSize(style));
} else {
// Use same sizing for radio box as checkbox.
setCheckboxSize(style);
}
}
bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
return paintTextFieldInternal(o, i, r, true);
}
bool RenderThemeWin::paintTextFieldInternal(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r, bool drawEdges)
{
// Nasty hack to make us not paint the border on text fields with a border-radius.
// Webkit paints elements with border-radius for us.
// TODO(ojan): Get rid of this if-check once we can properly clip rounded borders
// http://b/1112604 and http://b/1108635
// TODO(ojan): make sure we do the right thing if css background-clip is set.
if (o->style()->hasBorderRadius())
return false;
// Get the correct theme data for a textfield and paint the text field.
i.context->platformContext()->paintTextField(r, getThemeData(o), o->style()->backgroundColor().rgb(), drawEdges);
return false;
}
bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
return paintTextField(o, i, r);
}
void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
// Height is locked to auto on all browsers.
style->setLineHeight(RenderStyle::initialLineHeight());
if (webkit_glue::IsLayoutTestMode()) {
style->resetBorder();
style->setHeight(Length(Auto));
// Select one of the 3 fixed heights for controls
style->resetPadding();
if (style->height().isAuto()) {
// RenderThemeMac locks the size to 3 distinct values (NSControlSize).
// We on the other hand, base the height off the font.
int fixedHeight = kLayoutTestControlHeight[controlSizeForFont(style)];
style->setHeight(Length(fixedHeight, Fixed));
}
layoutTestSetFontFromControlSize(selector, style);
}
}
void RenderThemeWin::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
adjustMenuListStyle(selector, style, e);
}
// Used to paint unstyled menulists (i.e. with the default border)
bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
int borderRight = o->borderRight();
int borderLeft = o->borderLeft();
int borderTop = o->borderTop();
int borderBottom = o->borderBottom();
// If all the borders are 0, then tell skia not to paint the border on the textfield.
// TODO(ojan): 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.
// TODO(ojan): layout-test-mode removes borders, so we end up never drawing
// edges in layout-test-mode. See adjustMenuListStyle, style->resetBorder().
// We really need to remove the layout-test-mode only hacks.
bool drawEdges = !(borderRight == 0 && borderLeft == 0 && borderTop == 0 && borderBottom == 0);
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 = webkit_glue::IsLayoutTestMode() ?
kLayoutTestMenuListButtonWidth : GetSystemMetrics(SM_CXVSCROLL);
int spacingLeft = borderLeft + o->paddingLeft();
int spacingRight = borderRight + o->paddingRight();
int spacingTop = borderTop + o->paddingTop();
int spacingBottom = borderBottom + o->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;
}
IntRect buttonRect(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.
i.context->platformContext()->paintMenuListArrowButton(buttonRect, determineState(o), determineClassicState(o));
return false;
}
// Used to paint styled menulists (i.e. with a non-default border)
bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
return paintMenuList(o, i, r);
}
int RenderThemeWin::popupInternalPaddingLeft(RenderStyle* style) const
{
return menuListInternalPadding(style, LeftPadding);
}
int RenderThemeWin::popupInternalPaddingRight(RenderStyle* style) const
{
return menuListInternalPadding(style, RightPadding);
}
int RenderThemeWin::popupInternalPaddingTop(RenderStyle* style) const
{
return menuListInternalPadding(style, TopPadding);
}
int RenderThemeWin::popupInternalPaddingBottom(RenderStyle* style) const
{
return menuListInternalPadding(style, BottomPadding);
}
// Hacks for using Mac menu list metrics when in layout test mode.
static int layoutTestMenuListInternalPadding(RenderStyle* style, int paddingType)
{
if (style->appearance() == MenulistAppearance) {
return kLayoutTestMenuListInternalPadding[controlSizeForFont(style)][paddingType];
}
if (style->appearance() == MenulistButtonAppearance) {
if (paddingType == RightPadding) {
const float baseArrowWidth = 5.0f;
float fontScale = style->fontSize() / kLayoutTestBaseFontSize;
float arrowWidth = ceilf(baseArrowWidth * fontScale);
int arrowPaddingLeft = 6;
int arrowPaddingRight = 6;
int paddingBeforeSeparator = 4;
// Add 2 for separator space, seems to match RenderThemeMac::paintMenuListButton.
return static_cast<int>(arrowWidth + arrowPaddingLeft + arrowPaddingRight +
paddingBeforeSeparator);
} else {
return kLayoutTestStyledMenuListInternalPadding[paddingType];
}
}
return 0;
}
int RenderThemeWin::menuListInternalPadding(RenderStyle* style, int paddingType) const
{
if (webkit_glue::IsLayoutTestMode()) {
return layoutTestMenuListInternalPadding(style, paddingType);
}
// This internal padding is in addition to the user-supplied padding.
// Matches the FF behavior.
int padding = kStyledMenuListInternalPadding[paddingType];
// Reserve the space for right arrow here. The rest of the padding is
// set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
// RenderMenuList to lay out the individual items in the popup.
// If the MenuList actually has appearance "NoAppearance", then that means
// we don't draw a button, so don't reserve space for it.
const int bar_type = style->direction() == LTR ? RightPadding : LeftPadding;
if (paddingType == bar_type && style->appearance() != NoAppearance)
padding += PlatformScrollbar::verticalScrollbarWidth();
return padding;
}
void RenderThemeWin::adjustButtonInnerStyle(RenderStyle* style) const
{
// This inner padding matches Firefox.
style->setPaddingTop(Length(1, Fixed));
style->setPaddingRight(Length(3, Fixed));
style->setPaddingBottom(Length(1, Fixed));
style->setPaddingLeft(Length(3, Fixed));
}
void RenderThemeWin::setButtonPadding(RenderStyle* style) const
{
if (webkit_glue::IsLayoutTestMode()) {
setFixedPadding(style, kLayoutTestButtonPadding);
} else if (!style->width().isAuto()) {
// We need to set the minimum padding for the buttons, or else they
// render too small and clip the button face text. The right way to do
// this is to ask window's theme manager to give us the minimum
// (TS_MIN) size for the part. As a failsafe we set at least
// kDefaultButtonPadding because zero just looks bad.
Length minXPadding(kDefaultButtonPadding, Fixed);
Length minYPadding(kDefaultButtonPadding, Fixed);
// Find minimum padding.
getMinimalButtonPadding(&minXPadding);
// Set the minimum padding.
if (style->paddingLeft().value() < minXPadding.value()) {
style->setPaddingLeft(minXPadding);
}
if (style->paddingRight().value() < minXPadding.value()) {
style->setPaddingRight(minXPadding);
}
if (style->paddingBottom().value() < minYPadding.value()) {
style->setPaddingBottom(minYPadding);
}
if (style->paddingTop().value() < minYPadding.value()) {
style->setPaddingTop(minYPadding);
}
}
}
void RenderThemeWin::adjustSliderThumbSize(RenderObject* o) const
{
if (webkit_glue::IsLayoutTestMode()) {
if (o->style()->appearance() == SliderThumbHorizontalAppearance ||
o->style()->appearance() == SliderThumbVerticalAppearance) {
o->style()->setWidth(Length(kLayoutTestSliderThumbWidth, Fixed));
o->style()->setHeight(Length(kLayoutTestSliderThumbHeight, Fixed));
}
}
}
void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
if (webkit_glue::IsLayoutTestMode()) {
// Override border.
style->resetBorder();
style->setBorderLeftWidth(kLayoutTestSearchFieldBorderWidth);
style->setBorderLeftStyle(INSET);
style->setBorderRightWidth(kLayoutTestSearchFieldBorderWidth);
style->setBorderRightStyle(INSET);
style->setBorderBottomWidth(kLayoutTestSearchFieldBorderWidth);
style->setBorderBottomStyle(INSET);
style->setBorderTopWidth(kLayoutTestSearchFieldBorderWidth);
style->setBorderTopStyle(INSET);
// Override height.
style->setHeight(Length(
kLayoutTestSearchFieldHeight[controlSizeForFont(style)],
Fixed));
// Override padding size to match AppKit text positioning.
style->setPaddingLeft(Length(kLayoutTestSearchFieldPadding, Fixed));
style->setPaddingRight(Length(kLayoutTestSearchFieldPadding, Fixed));
style->setPaddingTop(Length(kLayoutTestSearchFieldPadding, Fixed));
style->setPaddingBottom(Length(kLayoutTestSearchFieldPadding, Fixed));
style->setBoxShadow(0);
}
}
static const IntSize* layoutTestCancelButtonSizes()
{
static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
return sizes;
}
static const IntSize* layoutTestResultsButtonSizes()
{
static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
return sizes;
}
void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
if (webkit_glue::IsLayoutTestMode()) {
IntSize size = layoutTestCancelButtonSizes()[controlSizeForFont(style)];
style->setWidth(Length(size.width(), Fixed));
style->setHeight(Length(size.height(), Fixed));
style->setBoxShadow(0);
}
}
void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
if (webkit_glue::IsLayoutTestMode()) {
IntSize size = layoutTestResultsButtonSizes()[controlSizeForFont(style)];
style->setWidth(Length(size.width() - kLayoutTestEmptyResultsOffset, Fixed));
style->setHeight(Length(size.height(), Fixed));
style->setBoxShadow(0);
}
}
void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
if (webkit_glue::IsLayoutTestMode()) {
IntSize size = layoutTestResultsButtonSizes()[controlSizeForFont(style)];
style->setWidth(Length(size.width(), Fixed));
style->setHeight(Length(size.height(), Fixed));
style->setBoxShadow(0);
}
}
void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
if (webkit_glue::IsLayoutTestMode()) {
IntSize size = layoutTestResultsButtonSizes()[controlSizeForFont(style)];
style->setWidth(Length(size.width() + kLayoutTestResultsArrowWidth, Fixed));
style->setHeight(Length(size.height(), Fixed));
style->setBoxShadow(0);
}
}
void RenderThemeWin::getMinimalButtonPadding(Length* minXPadding) const {
// TODO(maruel): This get messy if 1. the theme change; 2. we are serializing.
SIZE size;
if (SUCCEEDED(gfx::NativeTheme::instance()->GetThemePartSize(
gfx::NativeTheme::BUTTON, 0, BP_PUSHBUTTON, PBS_NORMAL, 0, TS_MIN,
&size))) {
*minXPadding = Length(size.cx, Fixed);
}
}
// static
void RenderThemeWin::setDefaultFontSize(int fontSize) {
DefaultFontSize = static_cast<float>(fontSize);
// Reset cached fonts.
SmallSystemFont = MenuFont = LabelFont = FontDescription();
}
}