* 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#define _WIN32_WINNT 0x0501
#include <string.h>
#include <stdio.h>
-/* #include "gdk/gdkwin32.h" */
+#ifdef BUILDING_STANDALONE
+#include "gdk/gdkwin32.h"
+#else
#include "gdk/win32/gdkwin32.h"
+#endif
+
+#include <cairo-win32.h>
+#include <gdk/gdk.h>
#include "xp_theme_defs.h"
#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 */
RP_GRIPPERVERT,
RP_CHEVRON,
TP_BUTTON,
- MP_MENUITEM,
- MP_SEPARATOR,
+ MENU_POPUPITEM, /*MP_MENUITEM,*/
+ MENU_POPUPSEPARATOR, /*MP_SEPARATOR,*/
SP_GRIPPER,
SP_PANE,
GP_LINEHORZ,
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 LOGFONT *plf);
+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 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 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)
void
xp_theme_init (void)
{
+ char *buf;
+ char dummy;
+ int n, k;
+
if (uxtheme_dll)
return;
memset (open_themes, 0, sizeof (open_themes));
- uxtheme_dll = LoadLibrary ("uxtheme.dll");
+ 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;
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)
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
ret = 1;
break;
- case XP_THEME_ELEMENT_MENU_ITEM:
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 = MS_DEMOTED;
+ ret = MBI_DISABLED;
break;
default:
- ret = MS_NORMAL;
+ ret = MBI_NORMAL;
}
break;
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 (GdkWindow *win, XpThemeElement element, GtkStyle *style,
+xp_theme_draw (cairo_t *cr, XpThemeElement element, GtkStyle *style,
int x, int y, int width, int height,
- GtkStateType state_type, GdkRectangle *area)
+ GtkStateType state_type)
{
HTHEME theme;
- RECT rect, clip, *pClip;
- int xoff, yoff;
+ RECT rect;
HDC dc;
- GdkDrawable *drawable;
+ XpDCInfo dc_info;
int part_state;
if (!xp_theme_is_drawable (element))
return FALSE;
/* FIXME: Recheck its function */
- enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB);
+// if (GDK_IS_WINDOW (win) && gdk_win32_window_is_win32 (win))
+// enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB);
- if (!GDK_IS_WINDOW (win))
- {
- xoff = 0;
- yoff = 0;
- drawable = win;
- }
- else
- {
- gdk_window_get_internal_paint_info (win, &drawable, &xoff, &yoff);
- }
-
- rect.left = x - xoff;
- rect.top = y - yoff;
- rect.right = rect.left + width;
- rect.bottom = rect.top + height;
-
- if (area)
- {
- clip.left = area->x - xoff;
- clip.top = area->y - yoff;
- clip.right = clip.left + area->width;
- clip.bottom = clip.top + area->height;
-
- pClip = &clip;
- }
- else
- {
- pClip = NULL;
- }
-
- gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
- dc = gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
+ 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, pClip);
+ part_state, &rect, NULL);
- gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
+ release_window_dc (&dc_info);
return TRUE;
}
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 LOGFONT *lf)
+ OUT LOGFONTW *lf)
{
if (xp_theme_is_active () && get_theme_sys_font_func != NULL)
{