RenderThemeWin.cpp [plain text]
#include "config.h"
#include "RenderThemeWin.h"
#include "CSSValueKeywords.h"
#include "Element.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "RenderSlider.h"
#include "Settings.h"
#include "SoftLinking.h"
#include "SystemInfo.h"
#include "UserAgentStyleSheets.h"
#if ENABLE(VIDEO)
#include "RenderMediaControls.h"
#endif
#include <tchar.h>
#define TS_NORMAL 1
#define TS_HOVER 2
#define TS_ACTIVE 3
#define TS_DISABLED 4
#define TS_FOCUSED 5
#define BP_BUTTON 1
#define BP_RADIO 2
#define BP_CHECKBOX 3
#define TFP_TEXTFIELD 1
#define EP_EDITBORDER_NOSCROLL 6
#define TFS_READONLY 6
#define CP_DROPDOWNBUTTON 1
#define CP_BORDER 4
#define CP_READONLY 5
#define CP_DROPDOWNBUTTONRIGHT 6
#define TKP_TRACK 1
#define TKP_TRACKVERT 2
#define TKP_THUMBBOTTOM 4
#define TKP_THUMBTOP 5
#define TKP_THUMBLEFT 7
#define TKP_THUMBRIGHT 8
#define TUS_NORMAL 1
#define TUS_HOT 2
#define TUS_PRESSED 3
#define TUS_FOCUSED 4
#define TUS_DISABLED 5
#define PBS_NORMAL 1
#define PBS_HOT 2
#define PBS_PRESSED 3
#define PBS_DISABLED 4
#define PBS_DEFAULTED 5
SOFT_LINK_LIBRARY(uxtheme)
SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect))
SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
static bool haveTheme;
static const unsigned vistaMenuListButtonOutset = 1;
using namespace std;
namespace WebCore {
static const int dropDownButtonWidth = 17;
static const int shell32MagnifierIconIndex = 22;
static const float defaultControlFontPixelSize = 13;
static const float defaultCancelButtonSize = 9;
static const float minCancelButtonSize = 5;
static const float maxCancelButtonSize = 21;
static const float defaultSearchFieldResultsDecorationSize = 13;
static const float minSearchFieldResultsDecorationSize = 9;
static const float maxSearchFieldResultsDecorationSize = 30;
static const float defaultSearchFieldResultsButtonWidth = 18;
static bool gWebKitIsBeingUnloaded;
static bool documentIsInApplicationChromeMode(const Document* document)
{
Settings* settings = document->settings();
return settings && settings->inApplicationChromeMode();
}
void RenderThemeWin::setWebKitIsBeingUnloaded()
{
gWebKitIsBeingUnloaded = true;
}
PassRefPtr<RenderTheme> RenderThemeWin::create()
{
return adoptRef(new RenderThemeWin);
}
#if !USE(SAFARI_THEME)
PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
static RenderTheme* winTheme = RenderThemeWin::create().releaseRef();
return winTheme;
}
#endif
RenderThemeWin::RenderThemeWin()
: m_buttonTheme(0)
, m_textFieldTheme(0)
, m_menuListTheme(0)
, m_sliderTheme(0)
{
haveTheme = uxthemeLibrary() && IsThemeActive();
}
RenderThemeWin::~RenderThemeWin()
{
if (gWebKitIsBeingUnloaded || !uxthemeLibrary())
return;
close();
}
HANDLE RenderThemeWin::buttonTheme() const
{
if (haveTheme && !m_buttonTheme)
m_buttonTheme = OpenThemeData(0, L"Button");
return m_buttonTheme;
}
HANDLE RenderThemeWin::textFieldTheme() const
{
if (haveTheme && !m_textFieldTheme)
m_textFieldTheme = OpenThemeData(0, L"Edit");
return m_textFieldTheme;
}
HANDLE RenderThemeWin::menuListTheme() const
{
if (haveTheme && !m_menuListTheme)
m_menuListTheme = OpenThemeData(0, L"ComboBox");
return m_menuListTheme;
}
HANDLE RenderThemeWin::sliderTheme() const
{
if (haveTheme && !m_sliderTheme)
m_sliderTheme = OpenThemeData(0, L"TrackBar");
return m_sliderTheme;
}
void RenderThemeWin::close()
{
if (m_buttonTheme)
CloseThemeData(m_buttonTheme);
if (m_textFieldTheme)
CloseThemeData(m_textFieldTheme);
if (m_menuListTheme)
CloseThemeData(m_menuListTheme);
if (m_sliderTheme)
CloseThemeData(m_sliderTheme);
m_buttonTheme = m_textFieldTheme = m_menuListTheme = m_sliderTheme = 0;
haveTheme = uxthemeLibrary() && IsThemeActive();
}
void RenderThemeWin::themeChanged()
{
close();
}
String RenderThemeWin::extraDefaultStyleSheet()
{
return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
}
String RenderThemeWin::extraQuirksStyleSheet()
{
return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
}
bool RenderThemeWin::supportsHover(const RenderStyle*) const
{
return haveTheme;
}
Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
{
COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
{
return Color(176, 176, 176);
}
Color RenderThemeWin::platformActiveSelectionForegroundColor() const
{
COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
{
return platformActiveSelectionForegroundColor();
}
static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont, float fontSize)
{
fontDescription.setIsAbsoluteSize(true);
fontDescription.setGenericFamily(FontDescription::NoFamily);
fontDescription.firstFamily().setFamily(String(logFont.lfFaceName));
fontDescription.setSpecifiedSize(fontSize);
fontDescription.setWeight(logFont.lfWeight >= 700 ? FontWeightBold : FontWeightNormal); fontDescription.setItalic(logFont.lfItalic);
}
static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont)
{
fillFontDescription(fontDescription, logFont, abs(logFont.lfHeight));
}
void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) const
{
static FontDescription captionFont;
static FontDescription controlFont;
static FontDescription smallCaptionFont;
static FontDescription menuFont;
static FontDescription iconFont;
static FontDescription messageBoxFont;
static FontDescription statusBarFont;
static FontDescription systemFont;
static bool initialized;
static NONCLIENTMETRICS ncm;
if (!initialized) {
initialized = true;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
}
switch (propId) {
case CSSValueIcon: {
if (!iconFont.isAbsoluteSize()) {
LOGFONT logFont;
::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0);
fillFontDescription(iconFont, logFont);
}
fontDescription = iconFont;
break;
}
case CSSValueMenu:
if (!menuFont.isAbsoluteSize())
fillFontDescription(menuFont, ncm.lfMenuFont);
fontDescription = menuFont;
break;
case CSSValueMessageBox:
if (!messageBoxFont.isAbsoluteSize())
fillFontDescription(messageBoxFont, ncm.lfMessageFont);
fontDescription = messageBoxFont;
break;
case CSSValueStatusBar:
if (!statusBarFont.isAbsoluteSize())
fillFontDescription(statusBarFont, ncm.lfStatusFont);
fontDescription = statusBarFont;
break;
case CSSValueCaption:
if (!captionFont.isAbsoluteSize())
fillFontDescription(captionFont, ncm.lfCaptionFont);
fontDescription = captionFont;
break;
case CSSValueSmallCaption:
if (!smallCaptionFont.isAbsoluteSize())
fillFontDescription(smallCaptionFont, ncm.lfSmCaptionFont);
fontDescription = smallCaptionFont;
break;
case CSSValueWebkitSmallControl:
case CSSValueWebkitMiniControl: case CSSValueWebkitControl: if (!controlFont.isAbsoluteSize()) {
HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
if (hGDI) {
LOGFONT logFont;
if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
fillFontDescription(controlFont, logFont, defaultControlFontPixelSize);
}
}
fontDescription = controlFont;
break;
default: { if (!systemFont.isAbsoluteSize()) {
HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
if (hGDI) {
LOGFONT logFont;
if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
fillFontDescription(systemFont, logFont);
}
}
fontDescription = systemFont;
}
}
}
bool RenderThemeWin::supportsFocus(ControlPart appearance) const
{
switch (appearance) {
case PushButtonPart:
case ButtonPart:
case DefaultButtonPart:
return true;
default:
return false;
}
}
bool RenderThemeWin::supportsFocusRing(const RenderStyle* style) const
{
return supportsFocus(style->appearance());
}
unsigned RenderThemeWin::determineClassicState(RenderObject* o)
{
unsigned state = 0;
switch (o->style()->appearance()) {
case PushButtonPart:
case ButtonPart:
case DefaultButtonPart:
state = DFCS_BUTTONPUSH;
if (!isEnabled(o))
state |= DFCS_INACTIVE;
else if (isPressed(o))
state |= DFCS_PUSHED;
break;
case RadioPart:
case CheckboxPart:
state = (o->style()->appearance() == RadioPart) ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK;
if (isChecked(o))
state |= DFCS_CHECKED;
if (!isEnabled(o))
state |= DFCS_INACTIVE;
else if (isPressed(o))
state |= DFCS_PUSHED;
break;
case MenulistPart:
state = DFCS_SCROLLCOMBOBOX;
if (!isEnabled(o))
state |= DFCS_INACTIVE;
else if (isPressed(o))
state |= DFCS_PUSHED;
default:
break;
}
return state;
}
unsigned RenderThemeWin::determineState(RenderObject* o)
{
unsigned result = TS_NORMAL;
ControlPart appearance = o->style()->appearance();
if (!isEnabled(o))
result = TS_DISABLED;
else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
result = TFS_READONLY; else if (isPressed(o)) result = TS_ACTIVE;
else if (supportsFocus(appearance) && isFocused(o))
result = TS_FOCUSED;
else if (isHovered(o))
result = TS_HOVER;
if (isChecked(o))
result += 4; return result;
}
unsigned RenderThemeWin::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 RenderThemeWin::determineButtonState(RenderObject* o)
{
unsigned result = PBS_NORMAL;
if (!isEnabled(o))
result = PBS_DISABLED;
else if (isPressed(o))
result = PBS_PRESSED;
else if (supportsFocus(o->style()->appearance()) && isFocused(o))
result = PBS_DEFAULTED;
else if (isHovered(o))
result = PBS_HOT;
else if (isDefault(o))
result = PBS_DEFAULTED;
return result;
}
ThemeData RenderThemeWin::getClassicThemeData(RenderObject* o)
{
ThemeData result;
switch (o->style()->appearance()) {
case PushButtonPart:
case ButtonPart:
case DefaultButtonPart:
case CheckboxPart:
case RadioPart:
result.m_part = DFC_BUTTON;
result.m_state = determineClassicState(o);
break;
case MenulistPart:
result.m_part = DFC_SCROLL;
result.m_state = determineClassicState(o);
break;
case SearchFieldPart:
case TextFieldPart:
case TextAreaPart:
result.m_part = TFP_TEXTFIELD;
result.m_state = determineState(o);
break;
case SliderHorizontalPart:
result.m_part = TKP_TRACK;
result.m_state = TS_NORMAL;
break;
case SliderVerticalPart:
result.m_part = TKP_TRACKVERT;
result.m_state = TS_NORMAL;
break;
case SliderThumbHorizontalPart:
result.m_part = TKP_THUMBBOTTOM;
result.m_state = determineSliderThumbState(o);
break;
case SliderThumbVerticalPart:
result.m_part = TKP_THUMBRIGHT;
result.m_state = determineSliderThumbState(o);
break;
default:
break;
}
return result;
}
ThemeData RenderThemeWin::getThemeData(RenderObject* o)
{
if (!haveTheme)
return getClassicThemeData(o);
ThemeData result;
switch (o->style()->appearance()) {
case PushButtonPart:
case ButtonPart:
case DefaultButtonPart:
result.m_part = BP_BUTTON;
result.m_state = determineButtonState(o);
break;
case CheckboxPart:
result.m_part = BP_CHECKBOX;
result.m_state = determineState(o);
break;
case MenulistPart:
case MenulistButtonPart:
result.m_part = isRunningOnVistaOrLater() ? CP_DROPDOWNBUTTONRIGHT : CP_DROPDOWNBUTTON;
if (isRunningOnVistaOrLater() && documentIsInApplicationChromeMode(o->document())) {
result.m_state = TS_NORMAL;
} else
result.m_state = determineState(o);
break;
case RadioPart:
result.m_part = BP_RADIO;
result.m_state = determineState(o);
break;
case SearchFieldPart:
case TextFieldPart:
case TextAreaPart:
result.m_part = isRunningOnVistaOrLater() ? EP_EDITBORDER_NOSCROLL : TFP_TEXTFIELD;
result.m_state = determineState(o);
break;
case SliderHorizontalPart:
result.m_part = TKP_TRACK;
result.m_state = TS_NORMAL;
break;
case SliderVerticalPart:
result.m_part = TKP_TRACKVERT;
result.m_state = TS_NORMAL;
break;
case SliderThumbHorizontalPart:
result.m_part = TKP_THUMBBOTTOM;
result.m_state = determineSliderThumbState(o);
break;
case SliderThumbVerticalPart:
result.m_part = TKP_THUMBRIGHT;
result.m_state = determineSliderThumbState(o);
break;
}
return result;
}
static void drawControl(GraphicsContext* context, RenderObject* o, HANDLE theme, const ThemeData& themeData, const IntRect& r)
{
bool alphaBlend = false;
if (theme)
alphaBlend = IsThemeBackgroundPartiallyTransparent(theme, themeData.m_part, themeData.m_state);
HDC hdc = context->getWindowsContext(r, alphaBlend);
RECT widgetRect = r;
if (theme)
DrawThemeBackground(theme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
else {
if (themeData.m_part == TFP_TEXTFIELD) {
::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
if (themeData.m_state == TS_DISABLED || themeData.m_state == TFS_READONLY)
::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_BTNFACE+1));
else
::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_WINDOW+1));
} else if (themeData.m_part == TKP_TRACK || themeData.m_part == TKP_TRACKVERT) {
::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
::FillRect(hdc, &widgetRect, (HBRUSH)GetStockObject(GRAY_BRUSH));
} else if ((o->style()->appearance() == SliderThumbHorizontalPart ||
o->style()->appearance() == SliderThumbVerticalPart) &&
(themeData.m_part == TKP_THUMBBOTTOM || themeData.m_part == TKP_THUMBTOP ||
themeData.m_part == TKP_THUMBLEFT || themeData.m_part == TKP_THUMBRIGHT)) {
::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
if (themeData.m_state == TUS_DISABLED) {
static WORD patternBits[8] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};
HBITMAP patternBmp = ::CreateBitmap(8, 8, 1, 1, patternBits);
if (patternBmp) {
HBRUSH brush = (HBRUSH) ::CreatePatternBrush(patternBmp);
COLORREF oldForeColor = ::SetTextColor(hdc, ::GetSysColor(COLOR_3DFACE));
COLORREF oldBackColor = ::SetBkColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
POINT p;
::GetViewportOrgEx(hdc, &p);
::SetBrushOrgEx(hdc, p.x + widgetRect.left, p.y + widgetRect.top, NULL);
HBRUSH oldBrush = (HBRUSH) ::SelectObject(hdc, brush);
::FillRect(hdc, &widgetRect, brush);
::SetTextColor(hdc, oldForeColor);
::SetBkColor(hdc, oldBackColor);
::SelectObject(hdc, oldBrush);
::DeleteObject(brush);
} else
::FillRect(hdc, &widgetRect, (HBRUSH)COLOR_3DHILIGHT);
::DeleteObject(patternBmp);
}
} else {
if (o->style()->appearance() == DefaultButtonPart) {
HBRUSH brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
::FrameRect(hdc, &widgetRect, brush);
::InflateRect(&widgetRect, -1, -1);
::DrawEdge(hdc, &widgetRect, BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE);
}
::DrawFrameControl(hdc, &widgetRect, themeData.m_part, themeData.m_state);
}
}
context->releaseWindowsContext(hdc, r, alphaBlend);
}
bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
drawControl(i.context, o, buttonTheme(), getThemeData(o), r);
return false;
}
void RenderThemeWin::setCheckboxSize(RenderStyle* style) const
{
if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
return;
if (style->width().isIntrinsicOrAuto())
style->setWidth(Length(13, Fixed));
if (style->height().isAuto())
style->setHeight(Length(13, Fixed));
}
bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
drawControl(i.context, o, textFieldTheme(), getThemeData(o), r);
return false;
}
bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
HANDLE theme;
int part;
if (haveTheme && isRunningOnVistaOrLater()) {
theme = menuListTheme();
if (documentIsInApplicationChromeMode(o->document()))
part = CP_READONLY;
else
part = CP_BORDER;
} else {
theme = textFieldTheme();
part = TFP_TEXTFIELD;
}
drawControl(i.context, o, theme, ThemeData(part, determineState(o)), r);
return paintMenuListButton(o, i, r);
}
void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
style->resetBorder();
adjustMenuListButtonStyle(selector, style, e);
}
void RenderThemeWin::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
const int dropDownBoxPaddingTop = 2;
const int dropDownBoxPaddingRight = style->direction() == LTR ? 4 + dropDownButtonWidth : 4;
const int dropDownBoxPaddingBottom = 2;
const int dropDownBoxPaddingLeft = style->direction() == LTR ? 4 : 4 + dropDownButtonWidth;
const int dropDownBoxMinHeight = 12;
style->setPaddingTop(Length(dropDownBoxPaddingTop, Fixed));
style->setPaddingRight(Length(dropDownBoxPaddingRight, Fixed));
style->setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed));
style->setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed));
style->setHeight(Length(Auto));
int minHeight = style->font().height();
minHeight = max(minHeight, dropDownBoxMinHeight);
style->setMinHeight(Length(minHeight, Fixed));
style->setWhiteSpace(PRE);
}
bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
int borderThickness = haveTheme ? 1 : 2;
IntRect buttonRect(r);
buttonRect.inflate(-borderThickness);
if (o->style()->direction() == LTR)
buttonRect.setX(buttonRect.right() - dropDownButtonWidth);
buttonRect.setWidth(dropDownButtonWidth);
if (isRunningOnVistaOrLater()) {
buttonRect.setY(buttonRect.y() - vistaMenuListButtonOutset);
buttonRect.setHeight(buttonRect.height() + 2 * vistaMenuListButtonOutset);
buttonRect.setWidth(buttonRect.width() + vistaMenuListButtonOutset);
}
drawControl(i.context, o, menuListTheme(), getThemeData(o), buttonRect);
return false;
}
const int trackWidth = 4;
bool RenderThemeWin::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
IntRect bounds = r;
if (o->style()->appearance() == SliderHorizontalPart) {
bounds.setHeight(trackWidth);
bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
} else if (o->style()->appearance() == SliderVerticalPart) {
bounds.setWidth(trackWidth);
bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
}
drawControl(i.context, o, sliderTheme(), getThemeData(o), bounds);
return false;
}
bool RenderThemeWin::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
drawControl(i.context, o, sliderTheme(), getThemeData(o), r);
return false;
}
const int sliderThumbWidth = 7;
const int sliderThumbHeight = 15;
void RenderThemeWin::adjustSliderThumbSize(RenderObject* o) const
{
if (o->style()->appearance() == SliderThumbVerticalPart) {
o->style()->setWidth(Length(sliderThumbHeight, Fixed));
o->style()->setHeight(Length(sliderThumbWidth, Fixed));
} else if (o->style()->appearance() == SliderThumbHorizontalPart) {
o->style()->setWidth(Length(sliderThumbWidth, Fixed));
o->style()->setHeight(Length(sliderThumbHeight, Fixed));
}
#if ENABLE(VIDEO)
else if (o->style()->appearance() == MediaSliderThumbPart)
RenderMediaControls::adjustMediaSliderThumbSize(o);
#endif
}
int RenderThemeWin::buttonInternalPaddingLeft() const
{
return 3;
}
int RenderThemeWin::buttonInternalPaddingRight() const
{
return 3;
}
int RenderThemeWin::buttonInternalPaddingTop() const
{
return 1;
}
int RenderThemeWin::buttonInternalPaddingBottom() const
{
return 1;
}
bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
return paintTextField(o, i, r);
}
void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
const int padding = 1;
style->setPaddingLeft(Length(padding, Fixed));
style->setPaddingRight(Length(padding, Fixed));
style->setPaddingTop(Length(padding, Fixed));
style->setPaddingBottom(Length(padding, Fixed));
if (e && e->focused() && e->document()->frame()->selection()->isFocusedAndActive())
style->setOutlineOffset(-2);
}
bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent() || !o->parent()->isBox())
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
IntRect parentBox = parentRenderBox->absoluteContentBox();
bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
bounds.setWidth(bounds.height());
bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o->style()->colorSpace(), bounds);
return false;
}
void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
float fontScale = style->fontSize() / defaultControlFontPixelSize;
int cancelButtonSize = lroundf(min(max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
style->setWidth(Length(cancelButtonSize, Fixed));
style->setHeight(Length(cancelButtonSize, Fixed));
}
void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
IntSize emptySize(1, 11);
style->setWidth(Length(emptySize.width(), Fixed));
style->setHeight(Length(emptySize.height(), Fixed));
}
void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
float fontScale = style->fontSize() / defaultControlFontPixelSize;
int magnifierSize = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
maxSearchFieldResultsDecorationSize));
style->setWidth(Length(magnifierSize, Fixed));
style->setHeight(Length(magnifierSize, Fixed));
}
bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent() || !o->parent()->isBox())
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
IntRect parentBox = parentRenderBox->absoluteContentBox();
bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
bounds.setWidth(bounds.height());
bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
paintInfo.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds);
return false;
}
void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
float fontScale = style->fontSize() / defaultControlFontPixelSize;
int magnifierHeight = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
maxSearchFieldResultsDecorationSize));
int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
style->setWidth(Length(magnifierWidth, Fixed));
style->setHeight(Length(magnifierHeight, Fixed));
}
bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent())
return false;
if (!o->parent() || !o->parent()->isBox())
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
IntRect parentBox = parentRenderBox->absoluteContentBox();
bounds.setHeight(min(parentBox.height(), bounds.height()));
bounds.setWidth(min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
paintInfo.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds);
return false;
}
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; }
}
Color RenderThemeWin::systemColor(int cssValueId) const
{
int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
if (sysColorIndex == -1)
return RenderTheme::systemColor(cssValueId);
COLORREF color = GetSysColor(sysColorIndex);
return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
#if ENABLE(VIDEO)
bool RenderThemeWin::shouldRenderMediaControlPart(ControlPart part, Element* element)
{
if (part == MediaToggleClosedCaptionsButtonPart) {
#if SAFARI_THEME_VERSION >= 4
if (!element->hasTagName(videoTag))
return false;
#else
return false;
#endif
}
return RenderTheme::shouldRenderMediaControlPart(part, element);
}
bool RenderThemeWin::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaSeekBackButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaSeekForwardButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaSlider, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaToggleClosedCaptionsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsButton, o, paintInfo, r);
}
#endif
}