PageRenderTime 27ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/Robespierre_2.0_pre-merge/WebCore/rendering/RenderThemeWin.cpp

https://github.com/weissms/owb-mirror
C++ | 342 lines | 255 code | 43 blank | 44 comment | 50 complexity | 27a38783f5ebf27d039af4b0fbc5e619 MD5 | raw file
  1. /*
  2. * This file is part of the WebKit project.
  3. *
  4. * Copyright (C) 2006 Apple Computer, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public License
  17. * along with this library; see the file COPYING.LIB. If not, write to
  18. * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. */
  22. #include "config.h"
  23. #include "RenderThemeWin.h"
  24. #include <cairo-win32.h>
  25. #include "Document.h"
  26. #include "GraphicsContext.h"
  27. /*
  28. * The following constants are used to determine how a widget is drawn using
  29. * Windows' Theme API. For more information on theme parts and states see
  30. * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
  31. */
  32. #define THEME_COLOR 204
  33. #define THEME_FONT 210
  34. // Generic state constants
  35. #define TS_NORMAL 1
  36. #define TS_HOVER 2
  37. #define TS_ACTIVE 3
  38. #define TS_DISABLED 4
  39. #define TS_FOCUSED 5
  40. // Button constants
  41. #define BP_BUTTON 1
  42. #define BP_RADIO 2
  43. #define BP_CHECKBOX 3
  44. // Textfield constants
  45. #define TFP_TEXTFIELD 1
  46. #define TFS_READONLY 6
  47. // Combobox constants
  48. #define CP_DROPDOWNBUTTON 1
  49. typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
  50. typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme);
  51. typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId,
  52. int iStateId, const RECT *pRect,
  53. const RECT* pClipRect);
  54. typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId,
  55. int iStateId, const RECT *pRect,
  56. unsigned uEdge, unsigned uFlags,
  57. const RECT* pClipRect);
  58. typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
  59. int iStateId, const RECT* pRect,
  60. RECT* pContentRect);
  61. typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
  62. int iStateId, RECT* prc, int ts,
  63. SIZE* psz);
  64. typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
  65. typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
  66. int iStateId, int iPropId, OUT COLORREF* pFont);
  67. static openThemeDataPtr openTheme = 0;
  68. static closeThemeDataPtr closeTheme = 0;
  69. static drawThemeBackgroundPtr drawThemeBG = 0;
  70. static drawThemeEdgePtr drawThemeEdge = 0;
  71. static getThemeContentRectPtr getThemeContentRect = 0;
  72. static getThemePartSizePtr getThemePartSize = 0;
  73. static getThemeSysFontPtr getThemeSysFont = 0;
  74. static getThemeColorPtr getThemeColor = 0;
  75. namespace WebCore {
  76. RenderTheme* theme()
  77. {
  78. static RenderThemeWin winTheme;
  79. return &winTheme;
  80. }
  81. RenderThemeWin::RenderThemeWin()
  82. :m_themeDLL(0), m_buttonTheme(0), m_textFieldTheme(0), m_menuListTheme(0)
  83. {
  84. m_themeDLL = ::LoadLibrary(L"uxtheme.dll");
  85. if (m_themeDLL) {
  86. openTheme = (openThemeDataPtr)GetProcAddress(m_themeDLL, "OpenThemeData");
  87. closeTheme = (closeThemeDataPtr)GetProcAddress(m_themeDLL, "CloseThemeData");
  88. drawThemeBG = (drawThemeBackgroundPtr)GetProcAddress(m_themeDLL, "DrawThemeBackground");
  89. drawThemeEdge = (drawThemeEdgePtr)GetProcAddress(m_themeDLL, "DrawThemeEdge");
  90. getThemeContentRect = (getThemeContentRectPtr)GetProcAddress(m_themeDLL, "GetThemeBackgroundContentRect");
  91. getThemePartSize = (getThemePartSizePtr)GetProcAddress(m_themeDLL, "GetThemePartSize");
  92. getThemeSysFont = (getThemeSysFontPtr)GetProcAddress(m_themeDLL, "GetThemeSysFont");
  93. getThemeColor = (getThemeColorPtr)GetProcAddress(m_themeDLL, "GetThemeColor");
  94. }
  95. }
  96. RenderThemeWin::~RenderThemeWin()
  97. {
  98. if (!m_themeDLL)
  99. return;
  100. close();
  101. ::FreeLibrary(m_themeDLL);
  102. }
  103. void RenderThemeWin::close()
  104. {
  105. // This method will need to be called when the OS theme changes to flush our cached themes.
  106. if (m_buttonTheme)
  107. closeTheme(m_buttonTheme);
  108. if (m_textFieldTheme)
  109. closeTheme(m_textFieldTheme);
  110. if (m_menuListTheme)
  111. closeTheme(m_menuListTheme);
  112. m_buttonTheme = m_textFieldTheme = m_menuListTheme = 0;
  113. }
  114. Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
  115. {
  116. COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
  117. return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
  118. }
  119. Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
  120. {
  121. COLORREF color = GetSysColor(COLOR_GRAYTEXT);
  122. return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
  123. }
  124. Color RenderThemeWin::platformActiveSelectionForegroundColor() const
  125. {
  126. COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
  127. return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
  128. }
  129. Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
  130. {
  131. return Color::white;
  132. }
  133. bool RenderThemeWin::supportsFocus(EAppearance appearance)
  134. {
  135. switch (appearance) {
  136. case PushButtonAppearance:
  137. case ButtonAppearance:
  138. case TextFieldAppearance:
  139. case TextAreaAppearance:
  140. return true;
  141. default:
  142. return false;
  143. }
  144. return false;
  145. }
  146. unsigned RenderThemeWin::determineState(RenderObject* o)
  147. {
  148. unsigned result = TS_NORMAL;
  149. if (!isEnabled(o))
  150. result = TS_DISABLED;
  151. else if (isReadOnlyControl(o))
  152. result = TFS_READONLY; // Readonly is supported on textfields.
  153. else if (supportsFocus(o->style()->appearance()) && isFocused(o))
  154. result = TS_FOCUSED;
  155. else if (isPressed(o)) // Active overrides hover.
  156. result = TS_ACTIVE;
  157. else if (isHovered(o))
  158. result = TS_HOVER;
  159. if (isChecked(o))
  160. result += 4; // 4 unchecked states, 4 checked states.
  161. return result;
  162. }
  163. unsigned RenderThemeWin::determineClassicState(RenderObject* o)
  164. {
  165. unsigned result = 0;
  166. if (!isEnabled(o) || isReadOnlyControl(o))
  167. result = DFCS_INACTIVE;
  168. else if (isPressed(o)) // Active supersedes hover
  169. result = DFCS_PUSHED;
  170. else if (isHovered(o))
  171. result = DFCS_HOT;
  172. if (isChecked(o))
  173. result |= DFCS_CHECKED;
  174. return result;
  175. }
  176. ThemeData RenderThemeWin::getThemeData(RenderObject* o)
  177. {
  178. ThemeData result;
  179. switch (o->style()->appearance()) {
  180. case PushButtonAppearance:
  181. case ButtonAppearance:
  182. result.m_part = BP_BUTTON;
  183. result.m_classicState = DFCS_BUTTONPUSH;
  184. break;
  185. case CheckboxAppearance:
  186. result.m_part = BP_CHECKBOX;
  187. result.m_classicState = DFCS_BUTTONCHECK;
  188. break;
  189. case RadioAppearance:
  190. result.m_part = BP_RADIO;
  191. result.m_classicState = DFCS_BUTTONRADIO;
  192. break;
  193. case ListboxAppearance:
  194. case MenulistAppearance:
  195. case TextFieldAppearance:
  196. case TextAreaAppearance:
  197. result.m_part = TFP_TEXTFIELD;
  198. break;
  199. }
  200. result.m_state = determineState(o);
  201. result.m_classicState |= determineClassicState(o);
  202. return result;
  203. }
  204. // May need to add stuff to these later, so keep the graphics context retrieval/release in some helpers.
  205. static HDC prepareForDrawing(GraphicsContext* g)
  206. {
  207. return g->getWindowsContext();
  208. }
  209. static void doneDrawing(GraphicsContext* g, HDC hdc)
  210. {
  211. g->releaseWindowsContext(hdc);
  212. }
  213. bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
  214. {
  215. // Get the correct theme data for a button
  216. ThemeData themeData = getThemeData(o);
  217. // Now paint the button.
  218. HDC hdc = prepareForDrawing(i.context);
  219. RECT widgetRect = r;
  220. if (m_themeDLL && !m_buttonTheme)
  221. m_buttonTheme = openTheme(0, L"Button");
  222. if (m_buttonTheme && drawThemeBG) {
  223. drawThemeBG(m_buttonTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
  224. } else {
  225. if ((themeData.m_part == BP_BUTTON) && isFocused(o)) {
  226. // Draw black focus rect around button outer edge
  227. HBRUSH brush = GetSysColorBrush(COLOR_3DDKSHADOW);
  228. if (brush) {
  229. FrameRect(hdc, &widgetRect, brush);
  230. InflateRect(&widgetRect, -1, -1);
  231. }
  232. }
  233. DrawFrameControl(hdc, &widgetRect, DFC_BUTTON, themeData.m_classicState);
  234. if ((themeData.m_part != BP_BUTTON) && isFocused(o)) {
  235. DrawFocusRect(hdc, &widgetRect);
  236. }
  237. }
  238. doneDrawing(i.context, hdc);
  239. return false;
  240. }
  241. void RenderThemeWin::setCheckboxSize(RenderStyle* style) const
  242. {
  243. // If the width and height are both specified, then we have nothing to do.
  244. if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
  245. return;
  246. // FIXME: A hard-coded size of 13 is used. This is wrong but necessary for now. It matches Firefox.
  247. // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
  248. // the higher DPI. Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
  249. // metrics.
  250. if (style->width().isIntrinsicOrAuto())
  251. style->setWidth(Length(13, Fixed));
  252. if (style->height().isAuto())
  253. style->setHeight(Length(13, Fixed));
  254. }
  255. bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
  256. {
  257. // Get the correct theme data for a textfield
  258. ThemeData themeData = getThemeData(o);
  259. // Now paint the text field.
  260. HDC hdc = prepareForDrawing(i.context);
  261. RECT widgetRect = r;
  262. if (m_themeDLL && !m_textFieldTheme)
  263. m_textFieldTheme = openTheme(0, L"Edit");
  264. if (m_textFieldTheme && drawThemeBG) {
  265. drawThemeBG(m_textFieldTheme, hdc, themeData.m_part, themeData.m_state, &widgetRect, NULL);
  266. } else {
  267. DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  268. FillRect(hdc, &widgetRect, reinterpret_cast<HBRUSH>(((themeData.m_classicState & DFCS_INACTIVE) ? COLOR_BTNFACE : COLOR_WINDOW) + 1));
  269. }
  270. doneDrawing(i.context, hdc);
  271. return false;
  272. }
  273. bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
  274. {
  275. // FIXME: All these inflate() calls are bogus, causing painting problems,
  276. // as well as sizing wackiness in Classic mode
  277. IntRect editRect(r);
  278. editRect.inflateY(2);
  279. paintTextField(o, i, editRect);
  280. const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
  281. IntRect buttonRect(r.right() - buttonWidth - 1, r.y(), buttonWidth, r.height());
  282. buttonRect.inflateY(1);
  283. paintMenuListButton(o, i, buttonRect);
  284. return false;
  285. }
  286. bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
  287. {
  288. HDC hdc = prepareForDrawing(i.context);
  289. RECT widgetRect = r;
  290. if (m_themeDLL && !m_menuListTheme)
  291. m_menuListTheme = openTheme(0, L"Combobox");
  292. if (m_menuListTheme && drawThemeBG)
  293. drawThemeBG(m_menuListTheme, hdc, CP_DROPDOWNBUTTON, determineState(o), &widgetRect, NULL);
  294. else
  295. DrawFrameControl(hdc, &widgetRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(o));
  296. doneDrawing(i.context, hdc);
  297. return false;
  298. }
  299. }