[gtk+] win32: Add support for -gtk-win32-part-width/height to CSS



commit f425b5549c49146ba3b751672e79f70d5e5572d7
Author: Benjamin Otte <otte gnome org>
Date:   Mon Feb 15 00:49:29 2016 +0100

    win32: Add support for -gtk-win32-part-width/height to CSS
    
    It's unused by now, but I want it for min-width of checks/radios.

 gtk/gtkcssnumbervalue.c    |    8 ++-
 gtk/gtkcsswin32sizevalue.c |  214 +++++++++++++++++++++++++++++++++++++-------
 gtk/gtkwin32theme.c        |   53 ++++++++++-
 gtk/gtkwin32themeprivate.h |    6 ++
 4 files changed, 245 insertions(+), 36 deletions(-)
---
diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c
index cca1e85..e8256c0 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 9856a20..7c35d37 100644
--- a/gtk/gtkcsswin32sizevalue.c
+++ b/gtk/gtkcsswin32sizevalue.c
@@ -21,16 +21,37 @@
 
 #include "gtkwin32themeprivate.h"
 
+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("
+};
+
 struct _GtkCssValue {
   GTK_CSS_VALUE_BASE
-  double         scale;         /* needed for calc() math */
-  GtkWin32Theme *theme;
-  gint           id;
+  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,
-                                                      int            id);
+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, &GTK_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 e1de2c9..d2fb6f0 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 c05311d..b03bea8 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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]