/* MS-Windows Engine (aka GTK-Wimp) * * Copyright (C) 2003, 2004 Raymond Penners * * 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. If not, see . */ #define _WIN32_WINNT 0x0501 #include "xp_theme.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifdef BUILDING_STANDALONE #include "gdk/gdkwin32.h" #else #include "gdk/win32/gdkwin32.h" #endif #include #include #include "xp_theme_defs.h" #ifndef TMT_CAPTIONFONT /* These aren't in mingw's "w32api" headers, nor in the Platform SDK * headers. */ #define TMT_CAPTIONFONT 801 #define TMT_MENUFONT 803 #define TMT_STATUSFONT 804 #define TMT_MSGBOXFONT 805 #endif #define GP_LINEHORZ 2 #define GP_LINEVERT 3 #define TP_SEPARATOR 5 #define TP_SEPARATORVERT 6 /* GLOBALS LINEHORZ states */ #define LHS_FLAT 1 #define LHS_RAISED 2 #define LHS_SUNKEN 3 /* GLOBAL LINEVERT states */ #define LVS_FLAT 1 #define LVS_RAISED 2 #define LVS_SUNKEN 3 /* TRACKBAR parts */ #define TKP_TRACK 1 #define TKP_TRACKVERT 2 #define TKP_THUMB 3 #define TKP_THUMBBOTTOM 4 #define TKP_THUMBTOP 5 #define TKP_THUMBVERT 6 #define TKP_THUMBLEFT 7 #define TKP_THUMBRIGHT 8 #define TKP_TICS 9 #define TKP_TICSVERT 10 #define TRS_NORMAL 1 #define MBI_NORMAL 1 #define MBI_HOT 2 #define MBI_PUSHED 3 #define MBI_DISABLED 4 #define MBI_DISABLEDHOT 5 #define MBI_DISABLEDPUSHED 6 #define MENU_POPUPGUTTER 13 #define MENU_POPUPITEM 14 #define MENU_POPUPSEPARATOR 15 static const LPCWSTR class_descriptors[] = { L"Scrollbar", /* XP_THEME_CLASS_SCROLLBAR */ L"Button", /* XP_THEME_CLASS_BUTTON */ L"Header", /* XP_THEME_CLASS_HEADER */ L"ComboBox", /* XP_THEME_CLASS_COMBOBOX */ L"Tab", /* XP_THEME_CLASS_TAB */ L"Edit", /* XP_THEME_CLASS_EDIT */ L"TreeView", /* XP_THEME_CLASS_TREEVIEW */ L"Spin", /* XP_THEME_CLASS_SPIN */ L"Progress", /* XP_THEME_CLASS_PROGRESS */ L"Tooltip", /* XP_THEME_CLASS_TOOLTIP */ L"Rebar", /* XP_THEME_CLASS_REBAR */ L"Toolbar", /* XP_THEME_CLASS_TOOLBAR */ L"Globals", /* XP_THEME_CLASS_GLOBALS */ L"Menu", /* XP_THEME_CLASS_MENU */ L"Window", /* XP_THEME_CLASS_WINDOW */ L"Status", /* XP_THEME_CLASS_STATUS */ L"Trackbar" /* XP_THEME_CLASS_TRACKBAR */ }; static const short element_part_map[XP_THEME_ELEMENT__SIZEOF] = { BP_CHECKBOX, BP_CHECKBOX, BP_CHECKBOX, BP_PUSHBUTTON, HP_HEADERITEM, CP_DROPDOWNBUTTON, TABP_BODY, TABP_TABITEM, TABP_TABITEMLEFTEDGE, TABP_TABITEMRIGHTEDGE, TABP_PANE, SBP_THUMBBTNHORZ, SBP_THUMBBTNVERT, SBP_ARROWBTN, SBP_ARROWBTN, SBP_ARROWBTN, SBP_ARROWBTN, SBP_GRIPPERHORZ, SBP_GRIPPERVERT, SBP_LOWERTRACKHORZ, SBP_LOWERTRACKVERT, EP_EDITTEXT, BP_PUSHBUTTON, SPNP_UP, SPNP_DOWN, BP_RADIOBUTTON, BP_RADIOBUTTON, TVP_GLYPH, TVP_GLYPH, PP_CHUNK, PP_CHUNKVERT, PP_BAR, PP_BARVERT, TTP_STANDARD, 0 /* RP_BAND */ , RP_GRIPPER, RP_GRIPPERVERT, RP_CHEVRON, TP_BUTTON, MENU_POPUPITEM, /*MP_MENUITEM,*/ MENU_POPUPSEPARATOR, /*MP_SEPARATOR,*/ SP_GRIPPER, SP_PANE, GP_LINEHORZ, GP_LINEVERT, TP_SEPARATOR, TP_SEPARATORVERT, TKP_TRACK, TKP_TRACKVERT, TKP_THUMB, TKP_THUMBVERT, TKP_TICS, TKP_TICSVERT }; #define UXTHEME_DLL "uxtheme.dll" static HINSTANCE uxtheme_dll = NULL; static HTHEME open_themes[XP_THEME_CLASS__SIZEOF]; static gboolean use_xp_theme = FALSE; typedef HRESULT (FAR PASCAL *GetThemeSysFontFunc) (HTHEME hTheme, int iFontID, OUT LOGFONTW *plf); typedef int (FAR PASCAL *GetThemeSysSizeFunc) (HTHEME hTheme, int iSizeId); typedef COLORREF (FAR PASCAL *GetThemeSysColorFunc) (HTHEME hTheme, int iColorID); typedef HTHEME (FAR PASCAL *OpenThemeDataFunc) (HWND hwnd, LPCWSTR pszClassList); typedef HRESULT (FAR PASCAL *CloseThemeDataFunc) (HTHEME theme); typedef HRESULT (FAR PASCAL *DrawThemeBackgroundFunc) (HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect); typedef HRESULT (FAR PASCAL *EnableThemeDialogTextureFunc) (HWND hwnd, DWORD dwFlags); typedef BOOL (FAR PASCAL *IsThemeActiveFunc) (VOID); typedef BOOL (FAR PASCAL *IsAppThemedFunc) (VOID); typedef BOOL (FAR PASCAL *IsThemeBackgroundPartiallyTransparentFunc) (HTHEME hTheme, int iPartId, int iStateId); typedef HRESULT (FAR PASCAL *DrawThemeParentBackgroundFunc) (HWND hwnd, HDC hdc, RECT *prc); typedef HRESULT (FAR PASCAL *GetThemePartSizeFunc) (HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, int eSize, SIZE *psz); static GetThemeSysFontFunc get_theme_sys_font_func = NULL; static GetThemeSysColorFunc get_theme_sys_color_func = NULL; static GetThemeSysSizeFunc get_theme_sys_metric_func = NULL; static OpenThemeDataFunc open_theme_data_func = NULL; static CloseThemeDataFunc close_theme_data_func = NULL; static DrawThemeBackgroundFunc draw_theme_background_func = NULL; static EnableThemeDialogTextureFunc enable_theme_dialog_texture_func = NULL; static IsThemeActiveFunc is_theme_active_func = NULL; static IsAppThemedFunc is_app_themed_func = NULL; static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent_func = NULL; static DrawThemeParentBackgroundFunc draw_theme_parent_background_func = NULL; static GetThemePartSizeFunc get_theme_part_size_func = NULL; static void xp_theme_close_open_handles (void) { int i; for (i = 0; i < XP_THEME_CLASS__SIZEOF; i++) { if (open_themes[i]) { close_theme_data_func (open_themes[i]); open_themes[i] = NULL; } } } void xp_theme_init (void) { char *buf; char dummy; int n, k; if (uxtheme_dll) return; memset (open_themes, 0, sizeof (open_themes)); n = GetSystemDirectory (&dummy, 0); if (n <= 0) return; buf = g_malloc (n + 1 + strlen (UXTHEME_DLL)); k = GetSystemDirectory (buf, n); if (k == 0 || k > n) { g_free (buf); return; } if (!G_IS_DIR_SEPARATOR (buf[strlen (buf) -1])) strcat (buf, G_DIR_SEPARATOR_S); strcat (buf, UXTHEME_DLL); uxtheme_dll = LoadLibrary (buf); g_free (buf); if (!uxtheme_dll) return; is_app_themed_func = (IsAppThemedFunc) GetProcAddress (uxtheme_dll, "IsAppThemed"); if (is_app_themed_func) { is_theme_active_func = (IsThemeActiveFunc) GetProcAddress (uxtheme_dll, "IsThemeActive"); open_theme_data_func = (OpenThemeDataFunc) GetProcAddress (uxtheme_dll, "OpenThemeData"); close_theme_data_func = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData"); draw_theme_background_func = (DrawThemeBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeBackground"); enable_theme_dialog_texture_func = (EnableThemeDialogTextureFunc) GetProcAddress (uxtheme_dll, "EnableThemeDialogTexture"); get_theme_sys_font_func = (GetThemeSysFontFunc) GetProcAddress (uxtheme_dll, "GetThemeSysFont"); get_theme_sys_color_func = (GetThemeSysColorFunc) GetProcAddress (uxtheme_dll, "GetThemeSysColor"); get_theme_sys_metric_func = (GetThemeSysSizeFunc) GetProcAddress (uxtheme_dll, "GetThemeSysSize"); is_theme_partially_transparent_func = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent"); draw_theme_parent_background_func = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground"); get_theme_part_size_func = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize"); } if (is_app_themed_func && is_theme_active_func) { use_xp_theme = (is_app_themed_func () && is_theme_active_func ()); } else { use_xp_theme = FALSE; } } void xp_theme_reset (void) { xp_theme_close_open_handles (); if (is_app_themed_func && is_theme_active_func) { use_xp_theme = (is_app_themed_func () && is_theme_active_func ()); } else { use_xp_theme = FALSE; } } void xp_theme_exit (void) { if (!uxtheme_dll) return; xp_theme_close_open_handles (); FreeLibrary (uxtheme_dll); uxtheme_dll = NULL; use_xp_theme = FALSE; is_app_themed_func = NULL; is_theme_active_func = NULL; open_theme_data_func = NULL; close_theme_data_func = NULL; draw_theme_background_func = NULL; enable_theme_dialog_texture_func = NULL; get_theme_sys_font_func = NULL; get_theme_sys_color_func = NULL; get_theme_sys_metric_func = NULL; is_theme_partially_transparent_func = NULL; draw_theme_parent_background_func = NULL; get_theme_part_size_func = NULL; } static HTHEME xp_theme_get_handle_by_class (XpThemeClass klazz) { if (!open_themes[klazz] && open_theme_data_func) { open_themes[klazz] = open_theme_data_func (NULL, class_descriptors[klazz]); } return open_themes[klazz]; } static HTHEME xp_theme_get_handle_by_element (XpThemeElement element) { HTHEME ret = NULL; XpThemeClass klazz = XP_THEME_CLASS__SIZEOF; switch (element) { case XP_THEME_ELEMENT_TOOLTIP: klazz = XP_THEME_CLASS_TOOLTIP; break; case XP_THEME_ELEMENT_REBAR: case XP_THEME_ELEMENT_REBAR_GRIPPER_H: case XP_THEME_ELEMENT_REBAR_GRIPPER_V: case XP_THEME_ELEMENT_REBAR_CHEVRON: klazz = XP_THEME_CLASS_REBAR; break; case XP_THEME_ELEMENT_SCALE_TROUGH_H: case XP_THEME_ELEMENT_SCALE_TROUGH_V: case XP_THEME_ELEMENT_SCALE_SLIDER_H: case XP_THEME_ELEMENT_SCALE_SLIDER_V: case XP_THEME_ELEMENT_SCALE_TICS_H: case XP_THEME_ELEMENT_SCALE_TICS_V: klazz = XP_THEME_CLASS_TRACKBAR; break; case XP_THEME_ELEMENT_STATUS_GRIPPER: case XP_THEME_ELEMENT_STATUS_PANE: klazz = XP_THEME_CLASS_STATUS; break; case XP_THEME_ELEMENT_TOOLBAR_BUTTON: case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H: case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V: klazz = XP_THEME_CLASS_TOOLBAR; break; case XP_THEME_ELEMENT_MENU_ITEM: case XP_THEME_ELEMENT_MENU_SEPARATOR: klazz = XP_THEME_CLASS_MENU; break; case XP_THEME_ELEMENT_PRESSED_CHECKBOX: case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX: case XP_THEME_ELEMENT_CHECKBOX: case XP_THEME_ELEMENT_BUTTON: case XP_THEME_ELEMENT_DEFAULT_BUTTON: case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON: case XP_THEME_ELEMENT_RADIO_BUTTON: klazz = XP_THEME_CLASS_BUTTON; break; case XP_THEME_ELEMENT_LIST_HEADER: klazz = XP_THEME_CLASS_HEADER; break; case XP_THEME_ELEMENT_COMBOBUTTON: klazz = XP_THEME_CLASS_COMBOBOX; break; case XP_THEME_ELEMENT_BODY: case XP_THEME_ELEMENT_TAB_ITEM: case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE: case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE: case XP_THEME_ELEMENT_TAB_PANE: klazz = XP_THEME_CLASS_TAB; break; case XP_THEME_ELEMENT_SCROLLBAR_V: case XP_THEME_ELEMENT_SCROLLBAR_H: case XP_THEME_ELEMENT_ARROW_UP: case XP_THEME_ELEMENT_ARROW_DOWN: case XP_THEME_ELEMENT_ARROW_LEFT: case XP_THEME_ELEMENT_ARROW_RIGHT: case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V: case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H: case XP_THEME_ELEMENT_TROUGH_V: case XP_THEME_ELEMENT_TROUGH_H: klazz = XP_THEME_CLASS_SCROLLBAR; break; case XP_THEME_ELEMENT_EDIT_TEXT: klazz = XP_THEME_CLASS_EDIT; break; case XP_THEME_ELEMENT_SPIN_BUTTON_UP: case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN: klazz = XP_THEME_CLASS_SPIN; break; case XP_THEME_ELEMENT_PROGRESS_BAR_H: case XP_THEME_ELEMENT_PROGRESS_BAR_V: case XP_THEME_ELEMENT_PROGRESS_TROUGH_H: case XP_THEME_ELEMENT_PROGRESS_TROUGH_V: klazz = XP_THEME_CLASS_PROGRESS; break; case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED: case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED: klazz = XP_THEME_CLASS_TREEVIEW; break; case XP_THEME_ELEMENT_LINE_H: case XP_THEME_ELEMENT_LINE_V: klazz = XP_THEME_CLASS_GLOBALS; break; default: break; } if (klazz != XP_THEME_CLASS__SIZEOF) { ret = xp_theme_get_handle_by_class (klazz); } return ret; } static int xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state) { int ret = 0; switch (element) { case XP_THEME_ELEMENT_TOOLTIP: ret = TTSS_NORMAL; break; case XP_THEME_ELEMENT_REBAR: ret = 0; break; case XP_THEME_ELEMENT_REBAR_GRIPPER_H: case XP_THEME_ELEMENT_REBAR_GRIPPER_V: ret = 0; break; case XP_THEME_ELEMENT_STATUS_GRIPPER: case XP_THEME_ELEMENT_STATUS_PANE: ret = 1; break; case XP_THEME_ELEMENT_REBAR_CHEVRON: switch (state) { case GTK_STATE_PRELIGHT: ret = CHEVS_HOT; break; case GTK_STATE_SELECTED: case GTK_STATE_ACTIVE: ret = CHEVS_PRESSED; break; default: ret = CHEVS_NORMAL; } break; case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H: case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V: ret = TS_NORMAL; break; case XP_THEME_ELEMENT_TOOLBAR_BUTTON: switch (state) { case GTK_STATE_ACTIVE: ret = TS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = TS_HOT; break; case GTK_STATE_INSENSITIVE: ret = TS_DISABLED; break; default: ret = TS_NORMAL; } break; case XP_THEME_ELEMENT_TAB_PANE: ret = 1; break; case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE: case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE: case XP_THEME_ELEMENT_TAB_ITEM: switch (state) { case GTK_STATE_PRELIGHT: ret = TIS_HOT; break; case GTK_STATE_INSENSITIVE: ret = TIS_DISABLED; break; case GTK_STATE_SELECTED: case GTK_STATE_ACTIVE: ret = TIS_NORMAL; break; default: ret = TIS_SELECTED; } break; case XP_THEME_ELEMENT_EDIT_TEXT: switch (state) { case GTK_STATE_PRELIGHT: ret = ETS_FOCUSED; break; case GTK_STATE_INSENSITIVE: ret = ETS_READONLY; break; case GTK_STATE_SELECTED: case GTK_STATE_ACTIVE: default: ret = ETS_NORMAL; } break; case XP_THEME_ELEMENT_TROUGH_H: case XP_THEME_ELEMENT_TROUGH_V: ret = SCRBS_NORMAL; break; case XP_THEME_ELEMENT_SCROLLBAR_H: case XP_THEME_ELEMENT_SCROLLBAR_V: switch (state) { case GTK_STATE_SELECTED: case GTK_STATE_ACTIVE: ret = SCRBS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = SCRBS_HOT; break; case GTK_STATE_INSENSITIVE: ret = SCRBS_DISABLED; break; default: ret = SCRBS_NORMAL; } break; case XP_THEME_ELEMENT_ARROW_DOWN: switch (state) { case GTK_STATE_ACTIVE: ret = ABS_DOWNPRESSED; break; case GTK_STATE_PRELIGHT: ret = ABS_DOWNHOT; break; case GTK_STATE_INSENSITIVE: ret = ABS_DOWNDISABLED; break; default: ret = ABS_DOWNNORMAL; } break; case XP_THEME_ELEMENT_ARROW_UP: switch (state) { case GTK_STATE_ACTIVE: ret = ABS_UPPRESSED; break; case GTK_STATE_PRELIGHT: ret = ABS_UPHOT; break; case GTK_STATE_INSENSITIVE: ret = ABS_UPDISABLED; break; default: ret = ABS_UPNORMAL; } break; case XP_THEME_ELEMENT_ARROW_LEFT: switch (state) { case GTK_STATE_ACTIVE: ret = ABS_LEFTPRESSED; break; case GTK_STATE_PRELIGHT: ret = ABS_LEFTHOT; break; case GTK_STATE_INSENSITIVE: ret = ABS_LEFTDISABLED; break; default: ret = ABS_LEFTNORMAL; } break; case XP_THEME_ELEMENT_ARROW_RIGHT: switch (state) { case GTK_STATE_ACTIVE: ret = ABS_RIGHTPRESSED; break; case GTK_STATE_PRELIGHT: ret = ABS_RIGHTHOT; break; case GTK_STATE_INSENSITIVE: ret = ABS_RIGHTDISABLED; break; default: ret = ABS_RIGHTNORMAL; } break; case XP_THEME_ELEMENT_CHECKBOX: case XP_THEME_ELEMENT_RADIO_BUTTON: switch (state) { case GTK_STATE_SELECTED: ret = CBS_UNCHECKEDPRESSED; break; case GTK_STATE_PRELIGHT: ret = CBS_UNCHECKEDHOT; break; case GTK_STATE_INSENSITIVE: ret = CBS_UNCHECKEDDISABLED; break; default: ret = CBS_UNCHECKEDNORMAL; } break; case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX: switch (state) { case GTK_STATE_SELECTED: ret = CBS_MIXEDPRESSED; break; case GTK_STATE_PRELIGHT: ret = CBS_MIXEDHOT; break; case GTK_STATE_INSENSITIVE: ret = CBS_MIXEDDISABLED; break; default: ret = CBS_MIXEDNORMAL; } break; case XP_THEME_ELEMENT_PRESSED_CHECKBOX: case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON: switch (state) { case GTK_STATE_SELECTED: ret = CBS_CHECKEDPRESSED; break; case GTK_STATE_PRELIGHT: ret = CBS_CHECKEDHOT; break; case GTK_STATE_INSENSITIVE: ret = CBS_CHECKEDDISABLED; break; default: ret = CBS_CHECKEDNORMAL; } break; case XP_THEME_ELEMENT_DEFAULT_BUTTON: switch (state) { case GTK_STATE_ACTIVE: ret = PBS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = PBS_HOT; break; case GTK_STATE_INSENSITIVE: ret = PBS_DISABLED; break; default: ret = PBS_DEFAULTED; } break; case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN: switch (state) { case GTK_STATE_ACTIVE: ret = DNS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = DNS_HOT; break; case GTK_STATE_INSENSITIVE: ret = DNS_DISABLED; break; default: ret = DNS_NORMAL; } break; case XP_THEME_ELEMENT_SPIN_BUTTON_UP: switch (state) { case GTK_STATE_ACTIVE: ret = UPS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = UPS_HOT; break; case GTK_STATE_INSENSITIVE: ret = UPS_DISABLED; break; default: ret = UPS_NORMAL; } break; case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED: ret = GLPS_OPENED; break; case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED: ret = GLPS_CLOSED; break; case XP_THEME_ELEMENT_PROGRESS_BAR_H: case XP_THEME_ELEMENT_PROGRESS_BAR_V: case XP_THEME_ELEMENT_PROGRESS_TROUGH_H: case XP_THEME_ELEMENT_PROGRESS_TROUGH_V: ret = 1; break; case XP_THEME_ELEMENT_MENU_SEPARATOR: ret = TS_NORMAL; break; case XP_THEME_ELEMENT_MENU_ITEM: switch (state) { case GTK_STATE_SELECTED: ret = MS_SELECTED; break; case GTK_STATE_PRELIGHT: ret = MBI_HOT; break; case GTK_STATE_INSENSITIVE: ret = MBI_DISABLED; break; default: ret = MBI_NORMAL; } break; case XP_THEME_ELEMENT_LINE_H: switch (state) { /* LHS_FLAT, LHS_RAISED, LHS_SUNKEN */ ret = LHS_RAISED; break; } break; case XP_THEME_ELEMENT_LINE_V: switch (state) { /* LVS_FLAT, LVS_RAISED, LVS_SUNKEN */ ret = LVS_RAISED; break; } break; case XP_THEME_ELEMENT_SCALE_TROUGH_H: case XP_THEME_ELEMENT_SCALE_TROUGH_V: ret = TRS_NORMAL; break; default: switch (state) { case GTK_STATE_ACTIVE: ret = PBS_PRESSED; break; case GTK_STATE_PRELIGHT: ret = PBS_HOT; break; case GTK_STATE_INSENSITIVE: ret = PBS_DISABLED; break; default: ret = PBS_NORMAL; } } return ret; } HDC get_window_dc (GtkStyle *style, cairo_t *cr, GtkStateType state_type, XpDCInfo *dc_info_out, gint x, gint y, gint width, gint height, RECT *rect_out) { HDC hDC, hTempDC; HBITMAP hBitmap, hOldBitmap; cairo_surface_t *sourceCS, *tempCS; cairo_t *tempCR; double x_off = 0, y_off = 0; dc_info_out->hdc = NULL; hDC = GetDC(NULL); hTempDC = CreateCompatibleDC(hDC); hBitmap = CreateCompatibleBitmap(hDC, x + width, y + height); hOldBitmap = (HBITMAP)SelectObject(hTempDC, hBitmap); ReleaseDC(NULL, hDC); tempCS = cairo_win32_surface_create (hTempDC); if (!tempCS) return NULL; sourceCS = cairo_get_target (cr); tempCR = cairo_create (tempCS); /* FIXME: I am missing something here - why is it needed to have device * for cairo_set_source_surface() ? */ cairo_surface_get_device_offset (sourceCS, &x_off, &y_off); cairo_set_source_surface (tempCR, sourceCS, x_off, y_off); cairo_set_operator (tempCR, CAIRO_OPERATOR_OVER); /* FIXME: Something is not quit right here - seems the CR or SURFACE do * not always have the correct data. Hovering on a GtkToolbar from * left to right draws the previous button over the next for ex. */ cairo_rectangle (tempCR, x, y, width, height); cairo_fill (tempCR); cairo_destroy (tempCR); cairo_surface_flush (tempCS); cairo_surface_destroy (tempCS); rect_out->left = x; rect_out->top = y; rect_out->right = rect_out->left + width; rect_out->bottom = rect_out->top + height; dc_info_out->hdc = hTempDC; dc_info_out->hBitmap = hBitmap; dc_info_out->hOldBitmap = hOldBitmap; dc_info_out->cr = cr; dc_info_out->x = x; dc_info_out->y = y; dc_info_out->width = width; dc_info_out->height = height; return hTempDC; } void release_window_dc (XpDCInfo *dc_info) { cairo_surface_t *tempCS, *target; if (!dc_info->hdc) return; tempCS = cairo_win32_surface_create (dc_info->hdc); target = cairo_get_target (dc_info->cr); cairo_save (dc_info->cr); cairo_set_source_surface (dc_info->cr, tempCS, 0, 0); cairo_set_operator (dc_info->cr, CAIRO_OPERATOR_OVER); cairo_rectangle (dc_info->cr, dc_info->x, dc_info->y, dc_info->width, dc_info->height); cairo_fill (dc_info->cr); cairo_restore (dc_info->cr); cairo_surface_destroy (tempCS); SelectObject(dc_info->hdc, dc_info->hOldBitmap); DeleteDC(dc_info->hdc); DeleteObject(dc_info->hBitmap); dc_info->hdc = NULL; } gboolean xp_theme_draw (cairo_t *cr, XpThemeElement element, GtkStyle *style, int x, int y, int width, int height, GtkStateType state_type) { HTHEME theme; RECT rect; HDC dc; XpDCInfo dc_info; int part_state; if (!xp_theme_is_drawable (element)) return FALSE; theme = xp_theme_get_handle_by_element (element); if (!theme) return FALSE; /* FIXME: Recheck its function */ // if (GDK_IS_WINDOW (win) && gdk_win32_window_is_win32 (win)) // enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB); dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect); if (!dc) return FALSE; part_state = xp_theme_map_gtk_state (element, state_type); /* Support transparency */ // if (is_theme_partially_transparent_func (theme, element_part_map[element], part_state)) // draw_theme_parent_background_func (GDK_WINDOW_HWND (win), dc, pClip); /* FIXME: Should we get and handle clipping (check it on the CR?) ? */ draw_theme_background_func (theme, dc, element_part_map[element], part_state, &rect, NULL); release_window_dc (&dc_info); return TRUE; } gboolean xp_theme_is_active (void) { return use_xp_theme; } gboolean xp_theme_is_drawable (XpThemeElement element) { if (xp_theme_is_active ()) return (xp_theme_get_handle_by_element (element) != NULL); return FALSE; } gboolean xp_theme_get_element_dimensions (XpThemeElement element, GtkStateType state_type, gint *cx, gint *cy) { HTHEME theme; SIZE part_size; int part_state; if (!xp_theme_is_active ()) return FALSE; theme = xp_theme_get_handle_by_element (element); if (!theme) return FALSE; part_state = xp_theme_map_gtk_state (element, state_type); get_theme_part_size_func (theme, NULL, element_part_map[element], part_state, NULL, TS_MIN, &part_size); *cx = part_size.cx; *cy = part_size.cy; if (element == XP_THEME_ELEMENT_MENU_ITEM || element == XP_THEME_ELEMENT_MENU_SEPARATOR) { SIZE gutter_size; get_theme_part_size_func (theme, NULL, MENU_POPUPGUTTER, 0, NULL, TS_MIN, &gutter_size); *cx += gutter_size.cx * 2; *cy += gutter_size.cy * 2; } return TRUE; } gboolean xp_theme_get_system_font (XpThemeClass klazz, XpThemeFont fontId, OUT LOGFONTW *lf) { if (xp_theme_is_active () && get_theme_sys_font_func != NULL) { HTHEME theme = xp_theme_get_handle_by_class (klazz); int themeFont; if (!theme) return FALSE; switch (fontId) { case XP_THEME_FONT_CAPTION: themeFont = TMT_CAPTIONFONT; break; case XP_THEME_FONT_MENU: themeFont = TMT_MENUFONT; break; case XP_THEME_FONT_STATUS: themeFont = TMT_STATUSFONT; break; case XP_THEME_FONT_MESSAGE: default: themeFont = TMT_MSGBOXFONT; break; } /* if theme is NULL, it will just return the GetSystemFont() value */ return ((*get_theme_sys_font_func) (theme, themeFont, lf) == S_OK); } return FALSE; } gboolean xp_theme_get_system_color (XpThemeClass klazz, int colorId, OUT DWORD *pColor) { if (xp_theme_is_active () && get_theme_sys_color_func != NULL) { HTHEME theme = xp_theme_get_handle_by_class (klazz); /* if theme is NULL, it will just return the GetSystemColor() value */ *pColor = (*get_theme_sys_color_func) (theme, colorId); return TRUE; } return FALSE; } gboolean xp_theme_get_system_metric (XpThemeClass klazz, int metricId, OUT int *pVal) { if (xp_theme_is_active () && get_theme_sys_metric_func != NULL) { HTHEME theme = xp_theme_get_handle_by_class (klazz); /* if theme is NULL, it will just return the GetSystemMetrics() value */ *pVal = (*get_theme_sys_metric_func) (theme, metricId); return TRUE; } return FALSE; }