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
34 /* #include "gdk/gdkwin32.h" */
35 #include "gdk/win32/gdkwin32.h"
37 #include "xp_theme_defs.h"
39 #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
52 #define TP_SEPARATOR 5
53 #define TP_SEPARATORVERT 6
55 /* GLOBALS LINEHORZ states */
60 /* GLOBAL LINEVERT states */
67 #define TKP_TRACKVERT 2
69 #define TKP_THUMBBOTTOM 4
70 #define TKP_THUMBTOP 5
71 #define TKP_THUMBVERT 6
72 #define TKP_THUMBLEFT 7
73 #define TKP_THUMBRIGHT 8
75 #define TKP_TICSVERT 10
79 static const LPCWSTR class_descriptors[] = {
80 L"Scrollbar", /* XP_THEME_CLASS_SCROLLBAR */
81 L"Button", /* XP_THEME_CLASS_BUTTON */
82 L"Header", /* XP_THEME_CLASS_HEADER */
83 L"ComboBox", /* XP_THEME_CLASS_COMBOBOX */
84 L"Tab", /* XP_THEME_CLASS_TAB */
85 L"Edit", /* XP_THEME_CLASS_EDIT */
86 L"TreeView", /* XP_THEME_CLASS_TREEVIEW */
87 L"Spin", /* XP_THEME_CLASS_SPIN */
88 L"Progress", /* XP_THEME_CLASS_PROGRESS */
89 L"Tooltip", /* XP_THEME_CLASS_TOOLTIP */
90 L"Rebar", /* XP_THEME_CLASS_REBAR */
91 L"Toolbar", /* XP_THEME_CLASS_TOOLBAR */
92 L"Globals", /* XP_THEME_CLASS_GLOBALS */
93 L"Menu", /* XP_THEME_CLASS_MENU */
94 L"Window", /* XP_THEME_CLASS_WINDOW */
95 L"Status", /* XP_THEME_CLASS_STATUS */
96 L"Trackbar" /* XP_THEME_CLASS_TRACKBAR */
99 static const short element_part_map[XP_THEME_ELEMENT__SIZEOF] = {
108 TABP_TABITEMLEFTEDGE,
109 TABP_TABITEMRIGHTEDGE,
155 static HINSTANCE uxtheme_dll = NULL;
156 static HTHEME open_themes[XP_THEME_CLASS__SIZEOF];
157 static gboolean use_xp_theme = FALSE;
159 typedef HRESULT (FAR PASCAL *GetThemeSysFontFunc) (HTHEME hTheme, int iFontID, OUT LOGFONT *plf);
160 typedef int (FAR PASCAL *GetThemeSysSizeFunc) (HTHEME hTheme, int iSizeId);
161 typedef COLORREF (FAR PASCAL *GetThemeSysColorFunc) (HTHEME hTheme,
163 typedef HTHEME (FAR PASCAL *OpenThemeDataFunc) (HWND hwnd,
164 LPCWSTR pszClassList);
165 typedef HRESULT (FAR PASCAL *CloseThemeDataFunc) (HTHEME theme);
166 typedef HRESULT (FAR PASCAL *DrawThemeBackgroundFunc) (HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
167 const RECT *pRect, const RECT *pClipRect);
168 typedef HRESULT (FAR PASCAL *EnableThemeDialogTextureFunc) (HWND hwnd,
170 typedef BOOL (FAR PASCAL *IsThemeActiveFunc) (VOID);
171 typedef BOOL (FAR PASCAL *IsAppThemedFunc) (VOID);
172 typedef BOOL (FAR PASCAL *IsThemeBackgroundPartiallyTransparentFunc) (HTHEME hTheme,
175 typedef HRESULT (FAR PASCAL *DrawThemeParentBackgroundFunc) (HWND hwnd,
179 static GetThemeSysFontFunc get_theme_sys_font_func = NULL;
180 static GetThemeSysColorFunc get_theme_sys_color_func = NULL;
181 static GetThemeSysSizeFunc get_theme_sys_metric_func = NULL;
182 static OpenThemeDataFunc open_theme_data_func = NULL;
183 static CloseThemeDataFunc close_theme_data_func = NULL;
184 static DrawThemeBackgroundFunc draw_theme_background_func = NULL;
185 static EnableThemeDialogTextureFunc enable_theme_dialog_texture_func = NULL;
186 static IsThemeActiveFunc is_theme_active_func = NULL;
187 static IsAppThemedFunc is_app_themed_func = NULL;
188 static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent_func = NULL;
189 static DrawThemeParentBackgroundFunc draw_theme_parent_background_func = NULL;
192 xp_theme_close_open_handles (void)
196 for (i = 0; i < XP_THEME_CLASS__SIZEOF; i++)
200 close_theme_data_func (open_themes[i]);
201 open_themes[i] = NULL;
212 memset (open_themes, 0, sizeof (open_themes));
214 uxtheme_dll = LoadLibrary ("uxtheme.dll");
218 is_app_themed_func = (IsAppThemedFunc) GetProcAddress (uxtheme_dll, "IsAppThemed");
220 if (is_app_themed_func)
222 is_theme_active_func = (IsThemeActiveFunc) GetProcAddress (uxtheme_dll, "IsThemeActive");
223 open_theme_data_func = (OpenThemeDataFunc) GetProcAddress (uxtheme_dll, "OpenThemeData");
224 close_theme_data_func = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData");
225 draw_theme_background_func = (DrawThemeBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeBackground");
226 enable_theme_dialog_texture_func = (EnableThemeDialogTextureFunc) GetProcAddress (uxtheme_dll, "EnableThemeDialogTexture");
227 get_theme_sys_font_func = (GetThemeSysFontFunc) GetProcAddress (uxtheme_dll, "GetThemeSysFont");
228 get_theme_sys_color_func = (GetThemeSysColorFunc) GetProcAddress (uxtheme_dll, "GetThemeSysColor");
229 get_theme_sys_metric_func = (GetThemeSysSizeFunc) GetProcAddress (uxtheme_dll, "GetThemeSysSize");
230 is_theme_partially_transparent_func = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent");
231 draw_theme_parent_background_func = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground");
234 if (is_app_themed_func && is_theme_active_func)
236 use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
240 use_xp_theme = FALSE;
245 xp_theme_reset (void)
247 xp_theme_close_open_handles ();
249 if (is_app_themed_func && is_theme_active_func)
251 use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
255 use_xp_theme = FALSE;
265 xp_theme_close_open_handles ();
267 FreeLibrary (uxtheme_dll);
269 use_xp_theme = FALSE;
271 is_app_themed_func = NULL;
272 is_theme_active_func = NULL;
273 open_theme_data_func = NULL;
274 close_theme_data_func = NULL;
275 draw_theme_background_func = NULL;
276 enable_theme_dialog_texture_func = NULL;
277 get_theme_sys_font_func = NULL;
278 get_theme_sys_color_func = NULL;
279 get_theme_sys_metric_func = NULL;
280 is_theme_partially_transparent_func = NULL;
281 draw_theme_parent_background_func = NULL;
285 xp_theme_get_handle_by_class (XpThemeClass klazz)
287 if (!open_themes[klazz] && open_theme_data_func)
289 open_themes[klazz] = open_theme_data_func (NULL, class_descriptors[klazz]);
292 return open_themes[klazz];
296 xp_theme_get_handle_by_element (XpThemeElement element)
299 XpThemeClass klazz = XP_THEME_CLASS__SIZEOF;
303 case XP_THEME_ELEMENT_TOOLTIP:
304 klazz = XP_THEME_CLASS_TOOLTIP;
307 case XP_THEME_ELEMENT_REBAR:
308 case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
309 case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
310 case XP_THEME_ELEMENT_REBAR_CHEVRON:
311 klazz = XP_THEME_CLASS_REBAR;
314 case XP_THEME_ELEMENT_SCALE_TROUGH_H:
315 case XP_THEME_ELEMENT_SCALE_TROUGH_V:
316 case XP_THEME_ELEMENT_SCALE_SLIDER_H:
317 case XP_THEME_ELEMENT_SCALE_SLIDER_V:
318 case XP_THEME_ELEMENT_SCALE_TICS_H:
319 case XP_THEME_ELEMENT_SCALE_TICS_V:
320 klazz = XP_THEME_CLASS_TRACKBAR;
323 case XP_THEME_ELEMENT_STATUS_GRIPPER:
324 case XP_THEME_ELEMENT_STATUS_PANE:
325 klazz = XP_THEME_CLASS_STATUS;
328 case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
329 case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
330 case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
331 klazz = XP_THEME_CLASS_TOOLBAR;
334 case XP_THEME_ELEMENT_MENU_ITEM:
335 case XP_THEME_ELEMENT_MENU_SEPARATOR:
336 klazz = XP_THEME_CLASS_MENU;
339 case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
340 case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
341 case XP_THEME_ELEMENT_CHECKBOX:
342 case XP_THEME_ELEMENT_BUTTON:
343 case XP_THEME_ELEMENT_DEFAULT_BUTTON:
344 case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
345 case XP_THEME_ELEMENT_RADIO_BUTTON:
346 klazz = XP_THEME_CLASS_BUTTON;
349 case XP_THEME_ELEMENT_LIST_HEADER:
350 klazz = XP_THEME_CLASS_HEADER;
353 case XP_THEME_ELEMENT_COMBOBUTTON:
354 klazz = XP_THEME_CLASS_COMBOBOX;
357 case XP_THEME_ELEMENT_BODY:
358 case XP_THEME_ELEMENT_TAB_ITEM:
359 case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
360 case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
361 case XP_THEME_ELEMENT_TAB_PANE:
362 klazz = XP_THEME_CLASS_TAB;
365 case XP_THEME_ELEMENT_SCROLLBAR_V:
366 case XP_THEME_ELEMENT_SCROLLBAR_H:
367 case XP_THEME_ELEMENT_ARROW_UP:
368 case XP_THEME_ELEMENT_ARROW_DOWN:
369 case XP_THEME_ELEMENT_ARROW_LEFT:
370 case XP_THEME_ELEMENT_ARROW_RIGHT:
371 case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V:
372 case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H:
373 case XP_THEME_ELEMENT_TROUGH_V:
374 case XP_THEME_ELEMENT_TROUGH_H:
375 klazz = XP_THEME_CLASS_SCROLLBAR;
378 case XP_THEME_ELEMENT_EDIT_TEXT:
379 klazz = XP_THEME_CLASS_EDIT;
382 case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
383 case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
384 klazz = XP_THEME_CLASS_SPIN;
387 case XP_THEME_ELEMENT_PROGRESS_BAR_H:
388 case XP_THEME_ELEMENT_PROGRESS_BAR_V:
389 case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
390 case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
391 klazz = XP_THEME_CLASS_PROGRESS;
394 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
395 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
396 klazz = XP_THEME_CLASS_TREEVIEW;
399 case XP_THEME_ELEMENT_LINE_H:
400 case XP_THEME_ELEMENT_LINE_V:
401 klazz = XP_THEME_CLASS_GLOBALS;
408 if (klazz != XP_THEME_CLASS__SIZEOF)
410 ret = xp_theme_get_handle_by_class (klazz);
417 xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state)
423 case XP_THEME_ELEMENT_TOOLTIP:
427 case XP_THEME_ELEMENT_REBAR:
431 case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
432 case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
436 case XP_THEME_ELEMENT_STATUS_GRIPPER:
437 case XP_THEME_ELEMENT_STATUS_PANE:
441 case XP_THEME_ELEMENT_REBAR_CHEVRON:
444 case GTK_STATE_PRELIGHT:
448 case GTK_STATE_SELECTED:
449 case GTK_STATE_ACTIVE:
458 case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
459 case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
463 case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
466 case GTK_STATE_ACTIVE:
470 case GTK_STATE_PRELIGHT:
474 case GTK_STATE_INSENSITIVE:
483 case XP_THEME_ELEMENT_TAB_PANE:
487 case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
488 case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
489 case XP_THEME_ELEMENT_TAB_ITEM:
492 case GTK_STATE_PRELIGHT:
496 case GTK_STATE_INSENSITIVE:
500 case GTK_STATE_SELECTED:
501 case GTK_STATE_ACTIVE:
510 case XP_THEME_ELEMENT_EDIT_TEXT:
513 case GTK_STATE_PRELIGHT:
517 case GTK_STATE_INSENSITIVE:
521 case GTK_STATE_SELECTED:
522 case GTK_STATE_ACTIVE:
528 case XP_THEME_ELEMENT_TROUGH_H:
529 case XP_THEME_ELEMENT_TROUGH_V:
533 case XP_THEME_ELEMENT_SCROLLBAR_H:
534 case XP_THEME_ELEMENT_SCROLLBAR_V:
537 case GTK_STATE_SELECTED:
538 case GTK_STATE_ACTIVE:
542 case GTK_STATE_PRELIGHT:
546 case GTK_STATE_INSENSITIVE:
547 ret = SCRBS_DISABLED;
555 case XP_THEME_ELEMENT_ARROW_DOWN:
558 case GTK_STATE_ACTIVE:
559 ret = ABS_DOWNPRESSED;
562 case GTK_STATE_PRELIGHT:
566 case GTK_STATE_INSENSITIVE:
567 ret = ABS_DOWNDISABLED;
571 ret = ABS_DOWNNORMAL;
575 case XP_THEME_ELEMENT_ARROW_UP:
578 case GTK_STATE_ACTIVE:
582 case GTK_STATE_PRELIGHT:
586 case GTK_STATE_INSENSITIVE:
587 ret = ABS_UPDISABLED;
595 case XP_THEME_ELEMENT_ARROW_LEFT:
598 case GTK_STATE_ACTIVE:
599 ret = ABS_LEFTPRESSED;
602 case GTK_STATE_PRELIGHT:
606 case GTK_STATE_INSENSITIVE:
607 ret = ABS_LEFTDISABLED;
611 ret = ABS_LEFTNORMAL;
615 case XP_THEME_ELEMENT_ARROW_RIGHT:
618 case GTK_STATE_ACTIVE:
619 ret = ABS_RIGHTPRESSED;
622 case GTK_STATE_PRELIGHT:
626 case GTK_STATE_INSENSITIVE:
627 ret = ABS_RIGHTDISABLED;
631 ret = ABS_RIGHTNORMAL;
635 case XP_THEME_ELEMENT_CHECKBOX:
636 case XP_THEME_ELEMENT_RADIO_BUTTON:
639 case GTK_STATE_SELECTED:
640 ret = CBS_UNCHECKEDPRESSED;
643 case GTK_STATE_PRELIGHT:
644 ret = CBS_UNCHECKEDHOT;
647 case GTK_STATE_INSENSITIVE:
648 ret = CBS_UNCHECKEDDISABLED;
652 ret = CBS_UNCHECKEDNORMAL;
656 case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
659 case GTK_STATE_SELECTED:
660 ret = CBS_MIXEDPRESSED;
663 case GTK_STATE_PRELIGHT:
667 case GTK_STATE_INSENSITIVE:
668 ret = CBS_MIXEDDISABLED;
672 ret = CBS_MIXEDNORMAL;
676 case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
677 case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
680 case GTK_STATE_SELECTED:
681 ret = CBS_CHECKEDPRESSED;
684 case GTK_STATE_PRELIGHT:
685 ret = CBS_CHECKEDHOT;
688 case GTK_STATE_INSENSITIVE:
689 ret = CBS_CHECKEDDISABLED;
693 ret = CBS_CHECKEDNORMAL;
697 case XP_THEME_ELEMENT_DEFAULT_BUTTON:
700 case GTK_STATE_ACTIVE:
704 case GTK_STATE_PRELIGHT:
708 case GTK_STATE_INSENSITIVE:
717 case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
720 case GTK_STATE_ACTIVE:
724 case GTK_STATE_PRELIGHT:
728 case GTK_STATE_INSENSITIVE:
737 case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
740 case GTK_STATE_ACTIVE:
744 case GTK_STATE_PRELIGHT:
748 case GTK_STATE_INSENSITIVE:
757 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
761 case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
765 case XP_THEME_ELEMENT_PROGRESS_BAR_H:
766 case XP_THEME_ELEMENT_PROGRESS_BAR_V:
767 case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
768 case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
772 case XP_THEME_ELEMENT_MENU_ITEM:
773 case XP_THEME_ELEMENT_MENU_SEPARATOR:
776 case GTK_STATE_SELECTED:
780 case GTK_STATE_INSENSITIVE:
789 case XP_THEME_ELEMENT_LINE_H:
792 /* LHS_FLAT, LHS_RAISED, LHS_SUNKEN */
798 case XP_THEME_ELEMENT_LINE_V:
801 /* LVS_FLAT, LVS_RAISED, LVS_SUNKEN */
807 case XP_THEME_ELEMENT_SCALE_TROUGH_H:
808 case XP_THEME_ELEMENT_SCALE_TROUGH_V:
815 case GTK_STATE_ACTIVE:
819 case GTK_STATE_PRELIGHT:
823 case GTK_STATE_INSENSITIVE:
836 xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style,
837 int x, int y, int width, int height,
838 GtkStateType state_type, GdkRectangle *area)
841 RECT rect, clip, *pClip;
844 GdkDrawable *drawable;
847 if (!xp_theme_is_drawable (element))
850 theme = xp_theme_get_handle_by_element (element);
854 /* FIXME: Recheck its function */
855 enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB);
857 if (!GDK_IS_WINDOW (win))
865 gdk_window_get_internal_paint_info (win, &drawable, &xoff, &yoff);
868 rect.left = x - xoff;
870 rect.right = rect.left + width;
871 rect.bottom = rect.top + height;
875 clip.left = area->x - xoff;
876 clip.top = area->y - yoff;
877 clip.right = clip.left + area->width;
878 clip.bottom = clip.top + area->height;
887 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
888 dc = gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
892 part_state = xp_theme_map_gtk_state (element, state_type);
894 draw_theme_background_func (theme, dc, element_part_map[element],
895 part_state, &rect, pClip);
897 gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
903 xp_theme_is_active (void)
909 xp_theme_is_drawable (XpThemeElement element)
911 if (xp_theme_is_active ())
912 return (xp_theme_get_handle_by_element (element) != NULL);
918 xp_theme_get_system_font (XpThemeClass klazz, XpThemeFont fontId,
921 if (xp_theme_is_active () && get_theme_sys_font_func != NULL)
923 HTHEME theme = xp_theme_get_handle_by_class (klazz);
931 case XP_THEME_FONT_CAPTION:
932 themeFont = TMT_CAPTIONFONT;
935 case XP_THEME_FONT_MENU:
936 themeFont = TMT_MENUFONT;
939 case XP_THEME_FONT_STATUS:
940 themeFont = TMT_STATUSFONT;
943 case XP_THEME_FONT_MESSAGE:
945 themeFont = TMT_MSGBOXFONT;
949 /* if theme is NULL, it will just return the GetSystemFont()
951 return ((*get_theme_sys_font_func) (theme, themeFont, lf) == S_OK);
958 xp_theme_get_system_color (XpThemeClass klazz, int colorId,
961 if (xp_theme_is_active () && get_theme_sys_color_func != NULL)
963 HTHEME theme = xp_theme_get_handle_by_class (klazz);
965 /* if theme is NULL, it will just return the GetSystemColor()
967 *pColor = (*get_theme_sys_color_func) (theme, colorId);
975 xp_theme_get_system_metric (XpThemeClass klazz, int metricId, OUT int *pVal)
977 if (xp_theme_is_active () && get_theme_sys_metric_func != NULL)
979 HTHEME theme = xp_theme_get_handle_by_class (klazz);
981 /* if theme is NULL, it will just return the GetSystemMetrics()
983 *pVal = (*get_theme_sys_metric_func) (theme, metricId);