From 3b19db425e63fb6f16b1daf4c8da288c631e1cc0 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 14 Feb 2016 00:54:37 +0100 Subject: [PATCH] css: Add a number value handling win32 sizes --- gtk/Makefile.am | 2 + gtk/gtkcssnumbervalue.c | 6 +- gtk/gtkcssstylefuncs.c | 42 ++++--- gtk/gtkcsswin32sizevalue.c | 196 ++++++++++++++++++++++++++++++ gtk/gtkcsswin32sizevalueprivate.h | 32 +++++ gtk/gtkwin32theme.c | 99 ++++----------- gtk/gtkwin32themeprivate.h | 10 +- 7 files changed, 293 insertions(+), 94 deletions(-) create mode 100644 gtk/gtkcsswin32sizevalue.c create mode 100644 gtk/gtkcsswin32sizevalueprivate.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 7bf26a62ef..7069071931 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -445,6 +445,7 @@ gtk_private_h_sources = \ gtkcsstypedvalueprivate.h \ gtkcssunsetvalueprivate.h \ gtkcssvalueprivate.h \ + gtkcsswin32sizevalueprviate.h \ gtkcsswidgetnodeprivate.h \ gtkcustompaperunixdialog.h \ gtkdialogprivate.h \ @@ -715,6 +716,7 @@ gtk_base_c_sources = \ gtkcsstypes.c \ gtkcssvalue.c \ gtkcsswidgetnode.c \ + gtkcsswin32sizevalue.c \ gtkdialog.c \ gtkdragsource.c \ gtkdrawingarea.c \ diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c index 80239d6f4d..cca1e8513d 100644 --- a/gtk/gtkcssnumbervalue.c +++ b/gtk/gtkcssnumbervalue.c @@ -21,6 +21,7 @@ #include "gtkcsscalcvalueprivate.h" #include "gtkcssdimensionvalueprivate.h" +#include "gtkcsswin32sizevalueprivate.h" struct _GtkCssValue { GTK_CSS_VALUE_BASE @@ -129,7 +130,8 @@ gboolean 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, "calc") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-size"); } GtkCssValue * @@ -138,6 +140,8 @@ _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")) + return gtk_css_win32_size_value_parse (parser, flags); return gtk_css_dimension_value_parse (parser, flags); } diff --git a/gtk/gtkcssstylefuncs.c b/gtk/gtkcssstylefuncs.c index 2a50d45486..466863114a 100644 --- a/gtk/gtkcssstylefuncs.c +++ b/gtk/gtkcssstylefuncs.c @@ -36,7 +36,7 @@ #include "gtkprivatetypebuiltins.h" #include "gtkstylecontextprivate.h" #include "gtktypebuiltins.h" -#include "gtkwin32themeprivate.h" +#include "gtkcsswin32sizevalueprivate.h" #include "deprecated/gtkthemingengine.h" #include "deprecated/gtkgradientprivate.h" @@ -431,15 +431,18 @@ int_value_parse (GtkCssParser *parser, { gint i; - if (_gtk_css_parser_begins_with (parser, '-')) + if (_gtk_css_parser_has_prefix (parser, "-gtk")) { - int res = _gtk_win32_theme_int_parse (parser, &i); - if (res >= 0) - { - g_value_set_int (value, i); - return res > 0; - } - /* < 0 => continue */ + GtkCssValue *cssvalue = gtk_css_win32_size_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS); + + if (cssvalue) + { + g_value_set_int (value, _gtk_css_number_value_get (cssvalue, 100)); + _gtk_css_value_unref (cssvalue); + return TRUE; + } + + return FALSE; } if (!_gtk_css_parser_try_int (parser, &i)) @@ -615,18 +618,19 @@ border_value_parse (GtkCssParser *parser, for (i = 0; i < G_N_ELEMENTS (numbers); i++) { - if (_gtk_css_parser_begins_with (parser, '-')) - { - /* These are strictly speaking signed, but we want to be able to use them - for unsigned types too, as the actual ranges of values make this safe */ - int res = _gtk_win32_theme_int_parse (parser, &numbers[i]); + if (_gtk_css_parser_has_prefix (parser, "-gtk")) + { + GtkCssValue *cssvalue = gtk_css_win32_size_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS); - if (res == 0) /* Parse error, report */ - return FALSE; + if (cssvalue) + { + numbers[i] = _gtk_css_number_value_get (cssvalue, 100); + _gtk_css_value_unref (cssvalue); + return TRUE; + } - if (res < 0) /* Nothing known to expand */ - break; - } + return FALSE; + } else { if (!_gtk_css_parser_try_length (parser, &numbers[i])) diff --git a/gtk/gtkcsswin32sizevalue.c b/gtk/gtkcsswin32sizevalue.c new file mode 100644 index 0000000000..c2b8b0879b --- /dev/null +++ b/gtk/gtkcsswin32sizevalue.c @@ -0,0 +1,196 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtkcsswin32sizevalueprivate.h" + +#include "gtkwin32themeprivate.h" + +struct _GtkCssValue { + GTK_CSS_VALUE_BASE + double scale; /* needed for calc() math */ + GtkWin32Theme *theme; + gint id; +}; + +static GtkCssValue * gtk_css_win32_size_value_new (double scale, + GtkWin32Theme *theme, + int id); + +static void +gtk_css_value_win32_size_free (GtkCssValue *value) +{ + gtk_win32_theme_unref (value->theme); + g_slice_free (GtkCssValue, value); +} + +static GtkCssValue * +gtk_css_value_win32_size_compute (GtkCssValue *value, + guint property_id, + GtkStyleProviderPrivate *provider, + 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); +} + +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; +} + +static void +gtk_css_value_win32_size_print (const GtkCssValue *value, + GString *string) +{ + if (value->scale != 1.0) + { + g_string_append_printf (string, "%g * ", value->scale); + } + g_string_append (string, "-gtk-win32-size("); + gtk_win32_theme_print (value->theme, string); + g_string_append_printf (string, ", %d)", value->id); +} + +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); +} + +static GtkCssDimension +gtk_css_value_win32_size_get_dimension (const GtkCssValue *value) +{ + return GTK_CSS_DIMENSION_LENGTH; +} + +static gboolean +gtk_css_value_win32_size_has_percent (const GtkCssValue *value) +{ + return FALSE; +} + +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); +} + +static GtkCssValue * +gtk_css_value_win32_size_try_add (const GtkCssValue *value1, + const GtkCssValue *value2) +{ + 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); +} + +static gint +gtk_css_value_win32_size_get_calc_term_order (const GtkCssValue *value) +{ + return 2000; +} + +static const GtkCssNumberValueClass GTK_CSS_VALUE_WIN32_SIZE = { + { + gtk_css_value_win32_size_free, + gtk_css_value_win32_size_compute, + gtk_css_value_win32_size_equal, + gtk_css_number_value_transition, + gtk_css_value_win32_size_print + }, + gtk_css_value_win32_size_get, + gtk_css_value_win32_size_get_dimension, + gtk_css_value_win32_size_has_percent, + gtk_css_value_win32_size_multiply, + gtk_css_value_win32_size_try_add, + gtk_css_value_win32_size_get_calc_term_order +}; + +static GtkCssValue * +gtk_css_win32_size_value_new (double scale, + GtkWin32Theme *theme, + int id) +{ + 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; + + return result; +} + +GtkCssValue * +gtk_css_win32_size_value_parse (GtkCssParser *parser, + GtkCssNumberParseFlags flags) +{ + GtkWin32Theme *theme; + char *theme_class; + GtkCssValue *result; + int id; + + if (!_gtk_css_parser_try (parser, "-gtk-win32-size(", TRUE)) + { + _gtk_css_parser_error (parser, "Expected '-gtk-win32-size('"); + return NULL; + } + + theme_class = _gtk_css_parser_try_name (parser, TRUE); + if (theme_class == NULL) + { + _gtk_css_parser_error (parser, "Expected name as first argument to '-gtk-win32-size'"); + return NULL; + } + + if (! _gtk_css_parser_try (parser, ",", TRUE)) + { + g_free (theme_class); + _gtk_css_parser_error (parser, "Expected ','"); + return NULL; + } + + if (!_gtk_css_parser_try_int (parser, &id)) + { + g_free (theme_class); + _gtk_css_parser_error (parser, "Expected an integer ID"); + return 0; + } + + if (!_gtk_css_parser_try (parser, ")", TRUE)) + { + g_free (theme_class); + _gtk_css_parser_error (parser, "Expected ')'"); + return NULL; + } + + theme = gtk_win32_theme_lookup (theme_class); + g_free (theme_class); + + result = gtk_css_win32_size_value_new (1.0, theme, id); + gtk_win32_theme_unref (theme); + + return result; +} diff --git a/gtk/gtkcsswin32sizevalueprivate.h b/gtk/gtkcsswin32sizevalueprivate.h new file mode 100644 index 0000000000..fd9bf19a40 --- /dev/null +++ b/gtk/gtkcsswin32sizevalueprivate.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2012 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Alexander Larsson + */ + +#ifndef __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__ +#define __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__ + +#include "gtkcssnumbervalueprivate.h" + +G_BEGIN_DECLS + +GtkCssValue * gtk_css_win32_size_value_parse (GtkCssParser *parser, + GtkCssNumberParseFlags flags); + +G_END_DECLS + +#endif /* __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__ */ diff --git a/gtk/gtkwin32theme.c b/gtk/gtkwin32theme.c index 167abf375a..c55a66a314 100644 --- a/gtk/gtkwin32theme.c +++ b/gtk/gtkwin32theme.c @@ -126,6 +126,14 @@ gtk_win32_theme_unref (GtkWin32Theme *theme) g_slice_free (GtkWin32Theme, theme); } +gboolean +gtk_win32_theme_equal (GtkWin32Theme *theme1, + GtkWin32Theme *theme2) +{ + /* Themes are cached so they're guaranteed unique. */ + return theme1 == theme2; +} + #ifdef G_OS_WIN32 static GdkFilterReturn @@ -213,8 +221,6 @@ gtk_win32_theme_init (void) use_xp_theme = FALSE; } - themes_by_class = g_hash_table_new (g_str_hash, g_str_equal); - gdk_window_add_filter (NULL, invalidate_win32_themes, NULL); } @@ -246,6 +252,9 @@ gtk_win32_theme_lookup (const char *classname) { GtkWin32Theme *theme; + if (G_UNLIKELY (themes_by_class == NULL)) + themes_by_class = g_hash_table_new (g_str_hash, g_str_equal); + theme = g_hash_table_lookup (themes_by_class, classname); if (theme != NULL) @@ -353,82 +362,22 @@ gtk_win32_theme_create_surface (GtkWin32Theme *theme, } int -_gtk_win32_theme_int_parse (GtkCssParser *parser, - int *value) +gtk_win32_theme_get_size (GtkWin32Theme *theme, + int id) { - char *theme_class; - int arg; #ifdef G_OS_WIN32 - GtkWin32Theme *theme; - HTHEME htheme; -#endif - - if (_gtk_css_parser_try (parser, - "-gtk-win32-size", - TRUE)) + if (use_xp_theme && get_theme_sys_metric != NULL) { - if (!_gtk_css_parser_try (parser, "(", TRUE)) - { - _gtk_css_parser_error (parser, - "Expected '(' after '-gtk-win32-size'"); - return 0; - } + HTHEME htheme = gtk_win32_theme_get_htheme (theme); - theme_class = _gtk_css_parser_try_name (parser, TRUE); - if (theme_class == NULL) - { - _gtk_css_parser_error (parser, - "Expected name as first argument to '-gtk-win32-size'"); - return 0; - } - - if (! _gtk_css_parser_try (parser, ",", TRUE)) - { - g_free (theme_class); - _gtk_css_parser_error (parser, - "Expected ','"); - return 0; - } - - if (!_gtk_css_parser_try_int (parser, &arg)) - { - g_free (theme_class); - _gtk_css_parser_error (parser, "Expected a valid integer value"); - return 0; - } - - if (!_gtk_css_parser_try (parser, ")", TRUE)) - { - g_free (theme_class); - _gtk_css_parser_error (parser, - "Expected ')'"); - return 0; - } - -#ifdef G_OS_WIN32 - theme = gtk_win32_theme_lookup (theme_class); - if (use_xp_theme && get_theme_sys_metric != NULL) - { - htheme = gtk_win32_theme_get_htheme (theme); - - /* If htheme is NULL it will just return the GetSystemMetrics value */ - *value = get_theme_sys_metric (htheme, arg); - } - else - *value = GetSystemMetrics (arg); - - gtk_win32_theme_unref (theme); - -#else - *value = 1; -#endif - - g_free (theme_class); - - return 1; + /* If htheme is NULL it will just return the GetSystemMetrics value */ + return get_theme_sys_metric (htheme, id); } - + else + return GetSystemMetrics (id); +#else return -1; +#endif } gboolean @@ -465,3 +414,9 @@ _gtk_win32_theme_color_resolve (const char *theme_class, return TRUE; } +void +gtk_win32_theme_print (GtkWin32Theme *theme, + GString *string) +{ + g_string_append (string, theme->class_name); +} diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h index 412c88c416..964eb8a10e 100644 --- a/gtk/gtkwin32themeprivate.h +++ b/gtk/gtkwin32themeprivate.h @@ -33,6 +33,12 @@ GtkWin32Theme * gtk_win32_theme_lookup (const char *classna GtkWin32Theme * gtk_win32_theme_ref (GtkWin32Theme *theme); void gtk_win32_theme_unref (GtkWin32Theme *theme); +gboolean gtk_win32_theme_equal (GtkWin32Theme *theme1, + GtkWin32Theme *theme2); + +void gtk_win32_theme_print (GtkWin32Theme *theme, + GString *string); + cairo_surface_t * gtk_win32_theme_create_surface (GtkWin32Theme *theme, int xp_part, int state, @@ -41,9 +47,9 @@ cairo_surface_t * gtk_win32_theme_create_surface (GtkWin32Theme *theme, int height, int *x_offs_out, int *y_offs_out); +int gtk_win32_theme_get_size (GtkWin32Theme *theme, + int id); -int _gtk_win32_theme_int_parse (GtkCssParser *parser, - int *value); gboolean _gtk_win32_theme_color_resolve (const char *theme_class, gint id, GdkRGBA *color);