diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c index cca1e8513d..e8256c0cf7 100644 --- a/gtk/gtkcssnumbervalue.c +++ b/gtk/gtkcssnumbervalue.c @@ -131,7 +131,9 @@ gtk_css_number_value_can_parse (GtkCssParser *parser) { return _gtk_css_parser_has_number (parser) || _gtk_css_parser_has_prefix (parser, "calc") - || _gtk_css_parser_has_prefix (parser, "-gtk-win32-size"); + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-size") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height"); } GtkCssValue * @@ -140,7 +142,9 @@ _gtk_css_number_value_parse (GtkCssParser *parser, { if (_gtk_css_parser_has_prefix (parser, "calc")) return gtk_css_calc_value_parse (parser, flags); - if (_gtk_css_parser_has_prefix (parser, "-gtk-win32-size")) + if (_gtk_css_parser_has_prefix (parser, "-gtk-win32-size") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height")) return gtk_css_win32_size_value_parse (parser, flags); return gtk_css_dimension_value_parse (parser, flags); diff --git a/gtk/gtkcsswin32sizevalue.c b/gtk/gtkcsswin32sizevalue.c index 9856a20aaf..7c35d37902 100644 --- a/gtk/gtkcsswin32sizevalue.c +++ b/gtk/gtkcsswin32sizevalue.c @@ -21,16 +21,37 @@ #include "gtkwin32themeprivate.h" -struct _GtkCssValue { - GTK_CSS_VALUE_BASE - double scale; /* needed for calc() math */ - GtkWin32Theme *theme; - gint id; +typedef enum { + GTK_WIN32_SIZE, + GTK_WIN32_PART_WIDTH, + GTK_WIN32_PART_HEIGHT +} GtkWin32SizeType; + +static const char *css_value_names[] = { + "-gtk-win32-size(", + "-gtk-win32-part-width(", + "-gtk-win32-part-height(" }; -static GtkCssValue * gtk_css_win32_size_value_new (double scale, - GtkWin32Theme *theme, - int id); +struct _GtkCssValue { + GTK_CSS_VALUE_BASE + double scale; /* needed for calc() math */ + GtkWin32Theme *theme; + GtkWin32SizeType type; + union { + struct { + gint id; + } size; + struct { + gint part; + gint state; + } part; + } val; +}; + +static GtkCssValue * gtk_css_win32_size_value_new (double scale, + GtkWin32Theme *theme, + GtkWin32SizeType type); static void gtk_css_value_win32_size_free (GtkCssValue *value) @@ -39,6 +60,32 @@ gtk_css_value_win32_size_free (GtkCssValue *value) g_slice_free (GtkCssValue, value); } +static int +gtk_css_value_win32_compute_size (const GtkCssValue *value) +{ + int size; + + switch (value->type) + { + case GTK_WIN32_SIZE: + size = gtk_win32_theme_get_size (value->theme, value->val.size.id); + + case GTK_WIN32_PART_WIDTH: + gtk_win32_theme_get_part_size (value->theme, value->val.part.part, value->val.part.state, &size, NULL); + break; + + case GTK_WIN32_PART_HEIGHT: + gtk_win32_theme_get_part_size (value->theme, value->val.part.part, value->val.part.state, NULL, &size); + break; + + default: + g_assert_not_reached (); + return 0; + } + + return size; +} + static GtkCssValue * gtk_css_value_win32_size_compute (GtkCssValue *value, guint property_id, @@ -46,15 +93,31 @@ gtk_css_value_win32_size_compute (GtkCssValue *value, GtkCssStyle *style, GtkCssStyle *parent_style) { - return _gtk_css_number_value_new (value->scale * gtk_win32_theme_get_size (value->theme, value->id), GTK_CSS_PX); + return _gtk_css_number_value_new (value->scale * gtk_css_value_win32_compute_size (value), GTK_CSS_PX); } static gboolean gtk_css_value_win32_size_equal (const GtkCssValue *value1, const GtkCssValue *value2) { - return gtk_win32_theme_equal (value1->theme, value2->theme) && - value1->id == value2->id; + if (value1->type != value2->type || + !gtk_win32_theme_equal (value1->theme, value2->theme) ) + return FALSE; + + switch (value1->type) + { + case GTK_WIN32_SIZE: + return value1->val.size.id == value2->val.size.id; + + case GTK_WIN32_PART_WIDTH: + case GTK_WIN32_PART_HEIGHT: + return value1->val.part.part == value2->val.part.part + && value1->val.part.state == value2->val.part.state; + + default: + g_assert_not_reached (); + return FALSE; + } } static void @@ -65,16 +128,33 @@ gtk_css_value_win32_size_print (const GtkCssValue *value, { g_string_append_printf (string, "%g * ", value->scale); } - g_string_append (string, "-gtk-win32-size("); + g_string_append (string, css_value_names[value->type]); gtk_win32_theme_print (value->theme, string); - g_string_append_printf (string, ", %d)", value->id); + + switch (value->type) + { + case GTK_WIN32_SIZE: + g_string_append_printf (string, ", %d", value->val.size.id); + break; + + case GTK_WIN32_PART_WIDTH: + case GTK_WIN32_PART_HEIGHT: + g_string_append_printf (string, ", %d, %d", value->val.part.part, value->val.part.state); + break; + + default: + g_assert_not_reached (); + break; + } + + g_string_append (string, ")"); } static double gtk_css_value_win32_size_get (const GtkCssValue *value, double one_hundred_percent) { - return value->scale * gtk_win32_theme_get_size (value->theme, value->id); + return value->scale * gtk_css_value_win32_compute_size (value); } static GtkCssDimension @@ -93,23 +173,33 @@ static GtkCssValue * gtk_css_value_win32_size_multiply (const GtkCssValue *value, double factor) { - return gtk_css_win32_size_value_new (value->scale * factor, value->theme, value->id); + GtkCssValue *result; + + result = gtk_css_win32_size_value_new (value->scale * factor, value->theme, value->type); + result->val = value->val; + + return result; } static GtkCssValue * gtk_css_value_win32_size_try_add (const GtkCssValue *value1, const GtkCssValue *value2) { + GtkCssValue *result; + if (!gtk_css_value_win32_size_equal (value1, value2)) return NULL; - return gtk_css_win32_size_value_new (value1->scale + value2->scale, value1->theme, value1->id); + result = gtk_css_win32_size_value_new (value1->scale + value2->scale, value1->theme, value1->type); + result->val = value1->val; + + return result; } static gint gtk_css_value_win32_size_get_calc_term_order (const GtkCssValue *value) { - return 2000; + return 2000 + 100 * value->type; } static const GtkCssNumberValueClass GTK_CSS_VALUE_WIN32_SIZE = { @@ -129,31 +219,79 @@ static const GtkCssNumberValueClass GTK_CSS_VALUE_WIN32_SIZE = { }; static GtkCssValue * -gtk_css_win32_size_value_new (double scale, - GtkWin32Theme *theme, - int id) +gtk_css_win32_size_value_new (double scale, + GtkWin32Theme *theme, + GtkWin32SizeType type) { GtkCssValue *result; result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_WIN32_SIZE.value_class); result->scale = scale; result->theme = gtk_win32_theme_ref (theme); - result->id = id; + result->type = type; return result; } +static GtkCssValue * +gtk_css_win32_size_value_parse_size (GtkCssValue *value, + GtkCssParser *parser) +{ + if (!_gtk_css_parser_try_int (parser, &value->val.size.id)) + { + _gtk_css_value_unref (value); + _gtk_css_parser_error (parser, "Expected an integer ID"); + return NULL; + } + + return value; +} + +static GtkCssValue * +gtk_css_win32_size_value_parse_part_size (GtkCssValue *value, + GtkCssParser *parser) +{ + if (!_gtk_css_parser_try_int (parser, &value->val.part.part)) + { + _gtk_css_value_unref (value); + _gtk_css_parser_error (parser, "Expected an integer part ID"); + return NULL; + } + + if (! _gtk_css_parser_try (parser, ",", TRUE)) + { + _gtk_css_value_unref (value); + _gtk_css_parser_error (parser, "Expected ','"); + return NULL; + } + + if (!_gtk_css_parser_try_int (parser, &value->val.part.state)) + { + _gtk_css_value_unref (value); + _gtk_css_parser_error (parser, "Expected an integer state ID"); + return NULL; + } + + return value; +} + GtkCssValue * gtk_css_win32_size_value_parse (GtkCssParser *parser, GtkCssNumberParseFlags flags) { GtkWin32Theme *theme; GtkCssValue *result; - int id; + guint type; - if (!_gtk_css_parser_try (parser, "-gtk-win32-size(", TRUE)) + for (type = 0; type < G_N_ELEMENTS(css_value_names); type++) { - _gtk_css_parser_error (parser, "Expected '-gtk-win32-size('"); + if (_gtk_css_parser_try (parser, css_value_names[type], TRUE)) + break; + } + + if (type >= G_N_ELEMENTS(css_value_names)) + { + _gtk_css_parser_error (parser, "Not a win32 size value"); return NULL; } @@ -161,29 +299,43 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser, if (theme == NULL) return NULL; + result = gtk_css_win32_size_value_new (1.0, theme, type); + gtk_win32_theme_unref (theme); + if (! _gtk_css_parser_try (parser, ",", TRUE)) { - gtk_win32_theme_unref (theme); + _gtk_css_value_unref (result); _gtk_css_parser_error (parser, "Expected ','"); return NULL; } - if (!_gtk_css_parser_try_int (parser, &id)) + switch (result->type) { - gtk_win32_theme_unref (theme); - _gtk_css_parser_error (parser, "Expected an integer ID"); - return 0; + case GTK_WIN32_SIZE: + result = gtk_css_win32_size_value_parse_size (result, parser); + break; + + case GTK_WIN32_PART_WIDTH: + case GTK_WIN32_PART_HEIGHT: + result = gtk_css_win32_size_value_parse_part_size (result, parser); + break; + + default: + g_assert_not_reached (); + _gtk_css_value_unref (result); + result = NULL; + break; } + if (result == NULL) + return NULL; + if (!_gtk_css_parser_try (parser, ")", TRUE)) { - gtk_win32_theme_unref (theme); + _gtk_css_value_unref (result); _gtk_css_parser_error (parser, "Expected ')'"); return NULL; } - result = gtk_css_win32_size_value_new (1.0, theme, id); - gtk_win32_theme_unref (theme); - return result; } diff --git a/gtk/gtkwin32theme.c b/gtk/gtkwin32theme.c index e1de2c9de9..d2fb6f0551 100644 --- a/gtk/gtkwin32theme.c +++ b/gtk/gtkwin32theme.c @@ -74,7 +74,7 @@ static IsThemeActiveFunc is_theme_active = NULL; static IsAppThemedFunc is_app_themed = NULL; static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent = NULL; static DrawThemeParentBackgroundFunc draw_theme_parent_background = NULL; -static GetThemePartSizeFunc get_theme_part_size = NULL; +static GetThemePartSizeFunc GetThemePartSize = NULL; #endif @@ -209,7 +209,7 @@ gtk_win32_theme_init (void) get_theme_sys_metric = (GetThemeSysSizeFunc) GetProcAddress (uxtheme_dll, "GetThemeSysSize"); is_theme_partially_transparent = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent"); draw_theme_parent_background = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground"); - get_theme_part_size = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize"); + GetThemePartSize = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize"); } if (is_app_themed && is_theme_active) @@ -337,7 +337,7 @@ gtk_win32_theme_create_surface (GtkWin32Theme *theme, rect.bottom = height; hdc = GetDC (NULL); - res = get_theme_part_size (htheme, hdc, xp_part, state, &rect, 2, &size); + res = GetThemePartSize (htheme, hdc, xp_part, state, &rect, 2 /*TS_DRAW*/, &size); ReleaseDC (NULL, hdc); if (res == S_OK) @@ -389,6 +389,53 @@ gtk_win32_theme_create_surface (GtkWin32Theme *theme, return surface; } +void +gtk_win32_theme_get_part_size (GtkWin32Theme *theme, + int part, + int state, + int *width, + int *height) +{ +#if 0 + /* Known fallback sizes copied from Wine */ + struct { + int part; + int width; + int height; + } fallback_sizes[] = { + { BP_RADIOBUTTON, 13, 13 }, + { BP_CHECKBOX, 13, 13 }, + }; +#endif +#ifdef G_OS_WIN32 + HTHEME htheme = gtk_win32_theme_get_htheme (theme); + SIZE size; + HDC hdc; + HRESULT res; + + if (use_xp_theme && GetThemePartSize != NULL && htheme != NULL) + { + hdc = GetDC (NULL); + res = GetThemePartSize (htheme, hdc, part, state, NULL, 2 /*TS_DRAW*/, &size); + ReleaseDC (NULL, hdc); + + if (SUCCEEDED (res)) + { + if (width) + *width = size.cx; + if (height) + *height = size.cy; + return; + } + } +#endif + + if (width) + *width = 1; + if (height) + *height = 1; +} + int gtk_win32_theme_get_size (GtkWin32Theme *theme, int id) diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h index c05311d80b..b03bea835e 100644 --- a/gtk/gtkwin32themeprivate.h +++ b/gtk/gtkwin32themeprivate.h @@ -48,6 +48,12 @@ cairo_surface_t * gtk_win32_theme_create_surface (GtkWin32Theme *theme, int height, int *x_offs_out, int *y_offs_out); + +void gtk_win32_theme_get_part_size (GtkWin32Theme *theme, + int part, + int state, + int *width, + int *height); int gtk_win32_theme_get_size (GtkWin32Theme *theme, int id); void gtk_win32_theme_get_color (GtkWin32Theme *theme,