1 /* MS-Windows Engine (aka GTK-Wimp)
3 * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #define _WIN32_WINNT 0x0501
30 #include "gdk/win32/gdkwin32.h"
33 #ifdef DONT_HAVE_UXTHEME_H
34 #include "xp_theme_defs.h"
40 #ifndef TMT_CAPTIONFONT
41 /* These aren't in mingw's "w32api" headers, nor in the Platform SDK
44 #define TMT_CAPTIONFONT 801
45 #define TMT_MENUFONT 803
46 #define TMT_STATUSFONT 804
47 #define TMT_MSGBOXFONT 805
50 static const LPCWSTR class_descriptors[] =
52 L"Scrollbar", /* XP_THEME_CLASS_SCROLLBAR */
53 L"Button", /* XP_THEME_CLASS_BUTTON */
54 L"Header", /* XP_THEME_CLASS_HEADER */
55 L"ComboBox", /* XP_THEME_CLASS_COMBOBOX */
56 L"Tab", /* XP_THEME_CLASS_TAB */
57 L"Edit", /* XP_THEME_CLASS_EDIT */
58 L"TreeView", /* XP_THEME_CLASS_TREEVIEW */
59 L"Spin", /* XP_THEME_CLASS_SPIN */
60 L"Progress", /* XP_THEME_CLASS_PROGRESS */
61 L"Tooltip", /* XP_THEME_CLASS_TOOLTIP */
62 L"Rebar", /* XP_THEME_CLASS_REBAR */
63 L"Toolbar", /* XP_THEME_CLASS_TOOLBAR */
64 L"Globals", /* XP_THEME_CLASS_GLOBALS */
65 L"Menu", /* XP_THEME_CLASS_MENU */
66 L"Window", /* XP_THEME_CLASS_WINDOW */
67 L"Status" /* XP_THEME_CLASS_STATUS */
70 static const short element_part_map[]=
115 static HINSTANCE uxtheme_dll = NULL;
116 static HTHEME open_themes[XP_THEME_CLASS__SIZEOF];
118 typedef HRESULT (FAR PASCAL *GetThemeSysFontFunc)
119 (HTHEME hTheme, int iFontID, OUT LOGFONT *plf);
120 typedef int (FAR PASCAL *GetThemeSysSizeFunc)
121 (HTHEME hTheme, int iSizeId);
122 typedef COLORREF (FAR PASCAL *GetThemeSysColorFunc)(HTHEME hTheme, int iColorID);
123 typedef HTHEME (FAR PASCAL *OpenThemeDataFunc)
124 (HWND hwnd, LPCWSTR pszClassList);
125 typedef HRESULT (FAR PASCAL *CloseThemeDataFunc)(HTHEME theme);
126 typedef HRESULT (FAR PASCAL *DrawThemeBackgroundFunc)
127 (HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
128 const RECT *pRect, const RECT *pClipRect);
129 typedef HRESULT (FAR PASCAL *EnableThemeDialogTextureFunc)(HWND hwnd, DWORD dwFlags);
130 typedef BOOL (FAR PASCAL *IsThemeActiveFunc)(VOID);
131 typedef BOOL (FAR PASCAL *IsAppThemedFunc)(VOID);
133 static GetThemeSysFontFunc get_theme_sys_font_func = NULL;
134 static GetThemeSysColorFunc get_theme_sys_color_func = NULL;
135 static GetThemeSysSizeFunc get_theme_sys_metric_func = NULL;
136 static OpenThemeDataFunc open_theme_data_func = NULL;
137 static CloseThemeDataFunc close_theme_data_func = NULL;
138 static DrawThemeBackgroundFunc draw_theme_background_func = NULL;
139 static EnableThemeDialogTextureFunc enable_theme_dialog_texture_func = NULL;
140 static IsThemeActiveFunc is_theme_active_func = NULL;
141 static IsAppThemedFunc is_app_themed_func = NULL;
144 xp_theme_close_open_handles (void)
148 for (i=0; i < XP_THEME_CLASS__SIZEOF; i++)
152 close_theme_data_func (open_themes[i]);
153 open_themes[i] = NULL;
164 memset(open_themes, 0, sizeof(open_themes));
166 uxtheme_dll = LoadLibrary("uxtheme.dll");
171 is_app_themed_func = (IsAppThemedFunc) GetProcAddress(uxtheme_dll, "IsAppThemed");
173 if(is_app_themed_func) {
174 is_theme_active_func = (IsThemeActiveFunc) GetProcAddress(uxtheme_dll, "IsThemeActive");
175 open_theme_data_func = (OpenThemeDataFunc) GetProcAddress(uxtheme_dll, "OpenThemeData");
176 close_theme_data_func = (CloseThemeDataFunc) GetProcAddress(uxtheme_dll, "CloseThemeData");
177 draw_theme_background_func = (DrawThemeBackgroundFunc) GetProcAddress(uxtheme_dll, "DrawThemeBackground");
178 enable_theme_dialog_texture_func = (EnableThemeDialogTextureFunc) GetProcAddress(uxtheme_dll, "EnableThemeDialogTexture");
179 get_theme_sys_font_func = (GetThemeSysFontFunc) GetProcAddress(uxtheme_dll, "GetThemeSysFont");
180 get_theme_sys_color_func = (GetThemeSysColorFunc) GetProcAddress(uxtheme_dll, "GetThemeSysColor");
181 get_theme_sys_metric_func = (GetThemeSysSizeFunc) GetProcAddress(uxtheme_dll, "GetThemeSysSize");
186 xp_theme_reset (void)
188 xp_theme_close_open_handles ();
197 xp_theme_close_open_handles ();
199 FreeLibrary (uxtheme_dll);
202 is_app_themed_func = NULL;
203 is_theme_active_func = NULL;
204 open_theme_data_func = NULL;
205 close_theme_data_func = NULL;
206 draw_theme_background_func = NULL;
207 enable_theme_dialog_texture_func = NULL;
208 get_theme_sys_font_func = NULL;
209 get_theme_sys_color_func = NULL;
210 get_theme_sys_metric_func = NULL;
214 xp_theme_get_handle_by_class (XpThemeClass klazz)
216 if (!open_themes[klazz] && open_theme_data_func)
218 open_themes[klazz] = open_theme_data_func(NULL, class_descriptors[klazz]);
220 return open_themes[klazz];
224 xp_theme_get_handle_by_element (XpThemeElement element)
227 XpThemeClass klazz = XP_THEME_CLASS__SIZEOF;
231 case XP_THEME_ELEMENT_TOOLTIP:
232 klazz = XP_THEME_CLASS_TOOLTIP;
235 case XP_THEME_ELEMENT_REBAR:
236 case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
237 case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
238 case XP_THEME_ELEMENT_REBAR_CHEVRON:
239 klazz = XP_THEME_CLASS_REBAR;
242 case XP_THEME_ELEMENT_STATUS_GRIPPER:
243 case XP_THEME_ELEMENT_STATUS_PANE:
244 klazz = XP_THEME_CLASS_STATUS;
247 case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
248 klazz = XP_THEME_CLASS_TOOLBAR;
251 case XP_THEME_ELEMENT_MENU_ITEM:
252 case XP_THEME_ELEMENT_MENU_SEPARATOR:
253 klazz = XP_THEME_CLASS_MENU;
256 case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
257 case XP_THEME_ELEMENT_CHECKBOX:
258 case XP_THEME_ELEMENT_BUTTON:
259 case XP_THEME_ELEMENT_DEFAULT_BUTTON:
260 case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
261 case XP_THEME_ELEMENT_RADIO_BUTTON:
262 klazz = XP_THEME_CLASS_BUTTON;
265 case XP_THEME_ELEMENT_LIST_HEADER:
266 klazz = XP_THEME_CLASS_HEADER;
269 case XP_THEME_ELEMENT_COMBOBUTTON:
270 klazz = XP_THEME_CLASS_COMBOBOX;
273 case XP_THEME_ELEMENT_BODY:
274 case XP_THEME_ELEMENT_TAB_ITEM:
275 case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
276 case XP_THEME_ELEMENT_TAB_PANE:
277 klazz = XP_THEME_CLASS_TAB;
280 case XP_THEME_ELEMENT_SCROLLBAR_V:
281 case XP_THEME_ELEMENT_SCROLLBAR_H:
282 case XP_THEME_ELEMENT_ARROW_UP:
283 case XP_THEME_ELEMENT_ARROW_DOWN:
284 case XP_THEME_ELEMENT_ARROW_LEFT:
285 case XP_THEME_ELEMENT_ARROW_RIGHT:
286 case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V:
287 case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H:
288 case XP_THEME_ELEMENT_TROUGH_V:
289 case XP_THEME_ELEMENT_TROUGH_H:
290 klazz = XP_THEME_CLASS_SCROLLBAR;
293 case XP_THEME_ELEMENT_EDIT_TEXT:
294 klazz = XP_THEME_CLASS_EDIT;
297 case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
298 case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
299 klazz = XP_THEME_CLASS_SPIN;
302 case XP_THEME_ELEMENT_PROGRESS_BAR_H:
303 case XP_THEME_ELEMENT_PROGRESS_BAR_V:
304 case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
305 case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
306 klazz = XP_THEME_CLASS_PROGRESS;
309 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
310 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
311 klazz = XP_THEME_CLASS_TREEVIEW;
315 if (klazz != XP_THEME_CLASS__SIZEOF)
317 ret = xp_theme_get_handle_by_class (klazz);
323 xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state)
329 case XP_THEME_ELEMENT_TOOLTIP:
333 case XP_THEME_ELEMENT_REBAR:
334 case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
335 case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
339 case XP_THEME_ELEMENT_STATUS_GRIPPER:
340 case XP_THEME_ELEMENT_STATUS_PANE:
344 case XP_THEME_ELEMENT_REBAR_CHEVRON:
347 case GTK_STATE_PRELIGHT:
350 case GTK_STATE_SELECTED:
351 case GTK_STATE_ACTIVE:
359 case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
362 case GTK_STATE_ACTIVE:
365 case GTK_STATE_PRELIGHT:
368 case GTK_STATE_INSENSITIVE:
376 case XP_THEME_ELEMENT_TAB_PANE:
380 case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
381 case XP_THEME_ELEMENT_TAB_ITEM:
384 case GTK_STATE_PRELIGHT:
387 case GTK_STATE_INSENSITIVE:
390 case GTK_STATE_SELECTED:
391 case GTK_STATE_ACTIVE:
399 case XP_THEME_ELEMENT_EDIT_TEXT:
402 case GTK_STATE_PRELIGHT:
405 case GTK_STATE_INSENSITIVE:
408 case GTK_STATE_SELECTED:
409 case GTK_STATE_ACTIVE:
415 case XP_THEME_ELEMENT_SCROLLBAR_H:
416 case XP_THEME_ELEMENT_SCROLLBAR_V:
417 case XP_THEME_ELEMENT_TROUGH_H:
418 case XP_THEME_ELEMENT_TROUGH_V:
421 case GTK_STATE_SELECTED:
422 case GTK_STATE_ACTIVE:
425 case GTK_STATE_PRELIGHT:
428 case GTK_STATE_INSENSITIVE:
429 ret = SCRBS_DISABLED;
436 case XP_THEME_ELEMENT_ARROW_DOWN:
439 case GTK_STATE_ACTIVE:
440 ret = ABS_DOWNPRESSED;
442 case GTK_STATE_PRELIGHT:
445 case GTK_STATE_INSENSITIVE:
446 ret = ABS_DOWNDISABLED;
449 ret = ABS_DOWNNORMAL;
453 case XP_THEME_ELEMENT_ARROW_UP:
456 case GTK_STATE_ACTIVE:
459 case GTK_STATE_PRELIGHT:
462 case GTK_STATE_INSENSITIVE:
463 ret = ABS_UPDISABLED;
470 case XP_THEME_ELEMENT_ARROW_LEFT:
473 case GTK_STATE_ACTIVE:
474 ret = ABS_LEFTPRESSED;
476 case GTK_STATE_PRELIGHT:
479 case GTK_STATE_INSENSITIVE:
480 ret = ABS_LEFTDISABLED;
483 ret = ABS_LEFTNORMAL;
487 case XP_THEME_ELEMENT_ARROW_RIGHT:
490 case GTK_STATE_ACTIVE:
491 ret = ABS_RIGHTPRESSED;
493 case GTK_STATE_PRELIGHT:
496 case GTK_STATE_INSENSITIVE:
497 ret = ABS_RIGHTDISABLED;
500 ret = ABS_RIGHTNORMAL;
504 case XP_THEME_ELEMENT_CHECKBOX:
505 case XP_THEME_ELEMENT_RADIO_BUTTON:
508 case GTK_STATE_SELECTED:
509 ret = CBS_UNCHECKEDPRESSED;
511 case GTK_STATE_PRELIGHT:
512 ret = CBS_UNCHECKEDHOT;
514 case GTK_STATE_INSENSITIVE:
515 ret = CBS_UNCHECKEDDISABLED;
518 ret = CBS_UNCHECKEDNORMAL;
522 case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
523 case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
526 case GTK_STATE_SELECTED:
527 ret = CBS_CHECKEDPRESSED;
529 case GTK_STATE_PRELIGHT:
530 ret = CBS_CHECKEDHOT;
532 case GTK_STATE_INSENSITIVE:
533 ret = CBS_CHECKEDDISABLED;
536 ret = CBS_CHECKEDNORMAL;
540 XP_THEME_ELEMENT_DEFAULT_BUTTON:
543 case GTK_STATE_ACTIVE:
546 case GTK_STATE_PRELIGHT:
549 case GTK_STATE_INSENSITIVE:
557 case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
560 case GTK_STATE_ACTIVE:
563 case GTK_STATE_PRELIGHT:
566 case GTK_STATE_INSENSITIVE:
574 case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
577 case GTK_STATE_ACTIVE:
580 case GTK_STATE_PRELIGHT:
583 case GTK_STATE_INSENSITIVE:
591 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
595 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
599 case XP_THEME_ELEMENT_PROGRESS_BAR_H:
600 case XP_THEME_ELEMENT_PROGRESS_BAR_V:
601 case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
602 case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
606 case XP_THEME_ELEMENT_MENU_ITEM:
607 case XP_THEME_ELEMENT_MENU_SEPARATOR:
609 case GTK_STATE_SELECTED:
612 case GTK_STATE_INSENSITIVE:
623 case GTK_STATE_ACTIVE:
626 case GTK_STATE_PRELIGHT:
629 case GTK_STATE_INSENSITIVE:
640 xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style,
641 int x, int y, int width, int height,
642 GtkStateType state_type, GdkRectangle *area)
645 RECT rect, clip, *pClip;
646 int xoff, yoff, state;
648 GdkDrawable *drawable;
651 if (! xp_theme_is_drawable (element))
654 theme = xp_theme_get_handle_by_element(element);
658 /* FIXME: Recheck its function */
659 enable_theme_dialog_texture_func(GDK_WINDOW_HWND(win), ETDT_ENABLETAB);
661 if (!GDK_IS_WINDOW(win))
669 gdk_window_get_internal_paint_info(win, &drawable, &xoff, &yoff);
671 rect.left = x - xoff;
673 rect.right = rect.left + width;
674 rect.bottom = rect.top + height;
678 clip.left = area->x - xoff;
679 clip.top = area->y - yoff;
680 clip.right = clip.left + area->width;
681 clip.bottom = clip.top + area->height;
690 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
691 dc = gdk_win32_hdc_get(drawable, style->dark_gc[state_type], 0);
695 part_state = xp_theme_map_gtk_state(element, state_type);
698 if (element == XP_THEME_ELEMENT_REBAR_GRIPPER_V
699 || element == XP_THEME_ELEMENT_REBAR_GRIPPER_H)
701 /* Hack alert: when XP draws a gripper, it does not seem to fill
702 up the whole rectangle. It only fills the gripper line
703 itself. Therefore we manually fill up the background here
704 ourselves. I still have to look into this a bit further, as
705 tests with GNAT Programming System show some awkward
706 interference between this FillRect and the subsequent
707 DrawThemeBackground(). */
708 FillRect (dc, &rect, (HBRUSH) (COLOR_3DFACE+1));
712 draw_theme_background_func(theme, dc, element_part_map[element], part_state, &rect, pClip);
713 gdk_win32_hdc_release(drawable, style->dark_gc[state_type], 0);
719 xp_theme_is_active (void)
721 gboolean active = FALSE;
723 if (is_app_themed_func)
725 active = (*is_app_themed_func) ();
727 if (active && is_theme_active_func)
729 active = (*is_theme_active_func) ();
737 xp_theme_is_drawable (XpThemeElement element)
739 if (xp_theme_is_active ())
740 return (xp_theme_get_handle_by_element (element) != NULL);
746 xp_theme_get_system_font (XpThemeClass klazz, XpThemeFont fontId, LOGFONT *lf)
750 if (get_theme_sys_font_func != NULL)
752 HTHEME theme = xp_theme_get_handle_by_class(klazz);
758 case XP_THEME_FONT_CAPTION:
759 themeFont = TMT_CAPTIONFONT; break;
760 case XP_THEME_FONT_MENU:
761 themeFont = TMT_MENUFONT; break;
762 case XP_THEME_FONT_STATUS:
763 themeFont = TMT_STATUSFONT; break;
764 case XP_THEME_FONT_MESSAGE:
766 themeFont = TMT_MSGBOXFONT; break;
768 /* if theme is NULL, it will just return the GetSystemFont() value */
769 return ((*get_theme_sys_font_func)(theme, themeFont, lf) == S_OK);
775 xp_theme_get_system_color (XpThemeClass klazz, int colorId, DWORD * pColor)
777 if (get_theme_sys_color_func != NULL)
779 HTHEME theme = xp_theme_get_handle_by_class(klazz);
781 /* if theme is NULL, it will just return the GetSystemColor() value */
782 *pColor = (*get_theme_sys_color_func)(theme, colorId);
789 xp_theme_get_system_metric (XpThemeClass klazz, int metricId, int * pVal)
791 if (get_theme_sys_metric_func != NULL)
793 HTHEME theme = xp_theme_get_handle_by_class(klazz);
795 /* if theme is NULL, it will just return the GetSystemMetrics() value */
796 *pVal = (*get_theme_sys_metric_func)(theme, metricId);