/tags/Robespierre_2.0_pre-merge/WebCore/rendering/RenderThemeWin.cpp
C++ | 342 lines | 255 code | 43 blank | 44 comment | 50 complexity | 27a38783f5ebf27d039af4b0fbc5e619 MD5 | raw file
- /*
- * 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 <cairo-win32.h>
- #include "Document.h"
- #include "GraphicsContext.h"
- /*
- * The following constants are used to determine how a widget is drawn using
- * Windows' Theme API. For more information on theme parts and states see
- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
- */
- #define THEME_COLOR 204
- #define THEME_FONT 210
- // Generic state constants
- #define TS_NORMAL 1
- #define TS_HOVER 2
- #define TS_ACTIVE 3
- #define TS_DISABLED 4
- #define TS_FOCUSED 5
- // Button constants
- #define BP_BUTTON 1
- #define BP_RADIO 2
- #define BP_CHECKBOX 3
- // Textfield constants
- #define TFP_TEXTFIELD 1
- #define TFS_READONLY 6
- // Combobox constants
- #define CP_DROPDOWNBUTTON 1
- typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
- typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme);
- typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId,
- int iStateId, const RECT *pRect,
- const RECT* pClipRect);
- typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId,
- int iStateId, const RECT *pRect,
- unsigned uEdge, unsigned uFlags,
- const RECT* pClipRect);
- typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
- int iStateId, const RECT* pRect,
- RECT* pContentRect);
- typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
- int iStateId, RECT* prc, int ts,
- SIZE* psz);
- typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
- typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
- int iStateId, int iPropId, OUT COLORREF* pFont);
- static openThemeDataPtr openTheme = 0;
- static closeThemeDataPtr closeTheme = 0;
- static drawThemeBackgroundPtr drawThemeBG = 0;
- static drawThemeEdgePtr drawThemeEdge = 0;
- static getThemeContentRectPtr getThemeContentRect = 0;
- static getThemePartSizePtr getThemePartSize = 0;
- static getThemeSysFontPtr getThemeSysFont = 0;
- static getThemeColorPtr getThemeColor = 0;
- namespace WebCore {
- RenderTheme* theme()
- {
- static RenderThemeWin winTheme;
- return &winTheme;
- }
- RenderThemeWin::RenderThemeWin()
- :m_themeDLL(0), m_buttonTheme(0), m_textFieldTheme(0), m_menuListTheme(0)
- {
- m_themeDLL = ::LoadLibrary(L"uxtheme.dll");
- if (m_themeDLL) {
- openTheme = (openThemeDataPtr)GetProcAddress(m_themeDLL, "OpenThemeData");
- closeTheme = (closeThemeDataPtr)GetProcAddress(m_themeDLL, "CloseThemeData");
- drawThemeBG = (drawThemeBackgroundPtr)GetProcAddress(m_themeDLL, "DrawThemeBackground");
- drawThemeEdge = (drawThemeEdgePtr)GetProcAddress(m_themeDLL, "DrawThemeEdge");
- getThemeContentRect = (getThemeContentRectPtr)GetProcAddress(m_themeDLL, "GetThemeBackgroundContentRect");
- getThemePartSize = (getThemePartSizePtr)GetProcAddress(m_themeDLL, "GetThemePartSize");
- getThemeSysFont = (getThemeSysFontPtr)GetProcAddress(m_themeDLL, "GetThemeSysFont");
- getThemeColor = (getThemeColorPtr)GetProcAddress(m_themeDLL, "GetThemeColor");
- }
- }
- RenderThemeWin::~RenderThemeWin()
- {
- if (!m_themeDLL)
- return;
- close();
- ::FreeLibrary(m_themeDLL);
- }
- void RenderThemeWin::close()
- {
- // This method will need to be called when the OS theme changes to flush our cached themes.
- if (m_buttonTheme)
- closeTheme(m_buttonTheme);
- if (m_textFieldTheme)
- closeTheme(m_textFieldTheme);
- if (m_menuListTheme)
- closeTheme(m_menuListTheme);
- m_buttonTheme = m_textFieldTheme = m_menuListTheme = 0;
- }
- Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
- {
- COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
- }
- Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
- {
- COLORREF color = GetSysColor(COLOR_GRAYTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
- }
- Color RenderThemeWin::platformActiveSelectionForegroundColor() const
- {
- COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
- }
- Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
- {
- return Color::white;
- }
- bool RenderThemeWin::supportsFocus(EAppearance appearance)
- {
- switch (appearance) {
- case PushButtonAppearance:
- case ButtonAppearance:
- case TextFieldAppearance:
- case TextAreaAppearance:
- return true;
- default:
- return false;
- }
- return false;
- }
- unsigned RenderThemeWin::determineState(RenderObject* o)
- {
- unsigned result = TS_NORMAL;
- if (!isEnabled(o))
- result = TS_DISABLED;
- else if (isReadOnlyControl(o))
- result = TFS_READONLY; // Readonly is supported on textfields.
- else if (supportsFocus(o->style()->appearance()) && isFocused(o))
- result = TS_FOCUSED;
- else if (isPressed(o)) // Active overrides hover.
- result = TS_ACTIVE;
- else if (isHovered(o))
- result = TS_HOVER;
- 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_BUTTON;
- 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_RADIO;
- result.m_classicState = DFCS_BUTTONRADIO;
- break;
- case ListboxAppearance:
- case MenulistAppearance:
- case TextFieldAppearance:
- case TextAreaAppearance:
- result.m_part = TFP_TEXTFIELD;
- break;
- }
- result.m_state = determineState(o);
- result.m_classicState |= determineClassicState(o);
- return result;
- }
- // May need to add stuff to these later, so keep the graphics context retrieval/release in some helpers.
- static HDC prepareForDrawing(GraphicsContext* g)
- {
- return g->getWindowsContext();
- }
-
- static void doneDrawing(GraphicsContext* g, HDC hdc)
- {
- g->releaseWindowsContext(hdc);
- }
- bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
- {
- // Get the correct theme data for a button
- ThemeData themeData = getThemeData(o);
- // Now paint the button.
- HDC hdc = prepareForDrawing(i.context);
- RECT widgetRect = r;
- if (m_themeDLL && !m_buttonTheme)
- m_buttonTheme = openTheme(0, L"Button");
- if (m_buttonTheme && drawThemeBG) {
- drawThemeBG(m_buttonTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
- } else {
- if ((themeData.m_part == BP_BUTTON) && isFocused(o)) {
- // Draw black focus rect around button outer edge
- HBRUSH brush = GetSysColorBrush(COLOR_3DDKSHADOW);
- if (brush) {
- FrameRect(hdc, &widgetRect, brush);
- InflateRect(&widgetRect, -1, -1);
- }
- }
- DrawFrameControl(hdc, &widgetRect, DFC_BUTTON, themeData.m_classicState);
- if ((themeData.m_part != BP_BUTTON) && isFocused(o)) {
- DrawFocusRect(hdc, &widgetRect);
- }
- }
- doneDrawing(i.context, hdc);
- return false;
- }
- 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.
- 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)
- {
- // Get the correct theme data for a textfield
- ThemeData themeData = getThemeData(o);
- // Now paint the text field.
- HDC hdc = prepareForDrawing(i.context);
- RECT widgetRect = r;
- if (m_themeDLL && !m_textFieldTheme)
- m_textFieldTheme = openTheme(0, L"Edit");
- if (m_textFieldTheme && drawThemeBG) {
- drawThemeBG(m_textFieldTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
- } else {
- DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
- FillRect(hdc, &widgetRect, reinterpret_cast<HBRUSH>(((themeData.m_classicState & DFCS_INACTIVE) ? COLOR_BTNFACE : COLOR_WINDOW) + 1));
- }
- doneDrawing(i.context, hdc);
- return false;
- }
- bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
- {
- // FIXME: All these inflate() calls are bogus, causing painting problems,
- // as well as sizing wackiness in Classic mode
- IntRect editRect(r);
- editRect.inflateY(2);
- paintTextField(o, i, editRect);
- const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
- IntRect buttonRect(r.right() - buttonWidth - 1, r.y(), buttonWidth, r.height());
- buttonRect.inflateY(1);
- paintMenuListButton(o, i, buttonRect);
- return false;
- }
- bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
- {
- HDC hdc = prepareForDrawing(i.context);
- RECT widgetRect = r;
- if (m_themeDLL && !m_menuListTheme)
- m_menuListTheme = openTheme(0, L"Combobox");
- if (m_menuListTheme && drawThemeBG)
- drawThemeBG(m_menuListTheme, hdc, CP_DROPDOWNBUTTON, determineState(o), &widgetRect, NULL);
- else
- DrawFrameControl(hdc, &widgetRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(o));
- doneDrawing(i.context, hdc);
- return false;
- }
- }