diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
commit | f5b16fed647e941aa66933178da85db2860d639b (patch) | |
tree | f00e9856c04aad3b558a140955e7674add33f051 /webkit/port/rendering | |
parent | 920c091ac3ee15079194c82ae8a7a18215f3f23c (diff) | |
download | chromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2 |
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port/rendering')
-rw-r--r-- | webkit/port/rendering/RenderThemeWin.cpp | 864 | ||||
-rw-r--r-- | webkit/port/rendering/RenderThemeWin.h | 133 |
2 files changed, 997 insertions, 0 deletions
diff --git a/webkit/port/rendering/RenderThemeWin.cpp b/webkit/port/rendering/RenderThemeWin.cpp new file mode 100644 index 0000000..d0509e1 --- /dev/null +++ b/webkit/port/rendering/RenderThemeWin.cpp @@ -0,0 +1,864 @@ +/* + * 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; + + if (dominantScript != USCRIPT_INVALID_CODE) { + family = gfx::GetFontFamilyForScript(dominantScript, + gfx::GenericFamilyType::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 CSS_VAL_SMALL_CAPTION: + 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 CSS_VAL_MENU: + 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 CSS_VAL_STATUS_BAR: + 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 CSS_VAL__WEBKIT_MINI_CONTROL: + 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 CSS_VAL__WEBKIT_SMALL_CONTROL: + if (webkit_glue::IsLayoutTestMode()) { + fontSize = systemFontSizeForControlSize(SmallControlSize); + } else { + faceName = defaultGUIFont(document); + fontSize = DefaultFontSize - pointsToPixels(2); + } + break; + case CSS_VAL__WEBKIT_CONTROL: + 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->setBold(false); + 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. + PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); + SkIRect rect; + WebCoreRectToSkiaRect(r, &rect); + skia->paintButton(rect, 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. + PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); + SkIRect rect; + WebCoreRectToSkiaRect(r, &rect); + skia->paintTextField(rect, 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. + PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); + SkIRect rect; + WebCoreRectToSkiaRect(buttonRect, &rect); + skia->paintMenuListArrowButton(rect, 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(); +} + +} diff --git a/webkit/port/rendering/RenderThemeWin.h b/webkit/port/rendering/RenderThemeWin.h new file mode 100644 index 0000000..bd4db98 --- /dev/null +++ b/webkit/port/rendering/RenderThemeWin.h @@ -0,0 +1,133 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderThemeWin_h +#define RenderThemeWin_h + +#include "RenderTheme.h" +#include "ThemeData.h" + +#if WIN32 +typedef void* HANDLE; +typedef struct HINSTANCE__* HINSTANCE; +typedef HINSTANCE HMODULE; +#endif + +namespace WebCore { + +class RenderThemeWin : public RenderTheme { +public: + RenderThemeWin(); + ~RenderThemeWin(); + + // A method asking if the theme's controls actually care about redrawing when hovered. + virtual bool supportsHover(const RenderStyle*) const { return true; } + + virtual bool supportsFocusRing(const RenderStyle*) const; + + virtual Color platformActiveSelectionBackgroundColor() const; + virtual Color platformInactiveSelectionBackgroundColor() const; + virtual Color platformActiveSelectionForegroundColor() const; + virtual Color platformInactiveSelectionForegroundColor() const; + + virtual double caretBlinkFrequency() const; + + // System fonts. + virtual void systemFont(int propId, Document*, FontDescription&) const; + + virtual int minimumMenuListSize(RenderStyle*) const; + + virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) + { return paintButton(o, i, r); } + virtual void setCheckboxSize(RenderStyle*) const; + + virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) + { return paintButton(o, i, r); } + virtual void setRadioSize(RenderStyle* style) const; + + virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual bool paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) + { return paintTextField(o, i, r); } + + // MenuList refers to an unstyled menulist (meaning a menulist without + // background-color or border set) and MenuListButton refers to a styled + // menulist (a menulist with background-color or border set). They have + // this distinction to support showing aqua style themes whenever they + // possibly can, which is something we don't want to replicate. + // + // In short, we either go down the MenuList code path or the MenuListButton + // codepath. We never go down both. And in both cases, they render the + // entire menulist. + virtual void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const; + virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const; + virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + // These methods define the padding for the MenuList's inner block. + virtual int popupInternalPaddingLeft(RenderStyle*) const; + virtual int popupInternalPaddingRight(RenderStyle*) const; + virtual int popupInternalPaddingTop(RenderStyle*) const; + virtual int popupInternalPaddingBottom(RenderStyle*) const; + + virtual void adjustButtonInnerStyle(RenderStyle* style) const; + + virtual void adjustSliderThumbSize(RenderObject*) const; + + virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + + virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + // Provide a way to pass the default font size from the Settings object to + // the render theme. TODO(tc): http://b/1129186 A cleaner way would be to + // remove the default font size from this object and have callers that need + // the value to get it directly from the appropriate Settings object. + static void setDefaultFontSize(int); + +private: + void addIntrinsicMargins(RenderStyle*) const; + + unsigned determineState(RenderObject*); + unsigned determineClassicState(RenderObject*); + bool supportsFocus(EAppearance); + + ThemeData getThemeData(RenderObject*); + + bool paintTextFieldInternal(RenderObject*, const RenderObject::PaintInfo&, const IntRect&, bool); + + void setButtonPadding(RenderStyle* style) const; + + // Gets the minimal x button padding according to the current theme. + void getMinimalButtonPadding(Length* minXPadding) const; + + int menuListInternalPadding(RenderStyle* style, int paddingType) const; +}; + +}; + +#endif |