[gtk+] win32 theme: Add a GtkWin32Theme object
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] win32 theme: Add a GtkWin32Theme object
- Date: Thu, 11 Feb 2016 02:47:13 +0000 (UTC)
commit 4dfbaccd6760ed01066f7e0dbbe08b802dbd06e1
Author: Benjamin Otte <otte gnome org>
Date: Mon Feb 8 04:07:40 2016 +0100
win32 theme: Add a GtkWin32Theme object
This object wraps a HTHEME and takes care of recreating it on theme changes.
gtk/gtkcssimagewin32.c | 24 +++-
gtk/gtkcssimagewin32private.h | 2 +-
gtk/gtkwin32theme.c | 253 +++++++++++++++++++++++++++--------------
gtk/gtkwin32themeprivate.h | 34 +++----
4 files changed, 199 insertions(+), 114 deletions(-)
---
diff --git a/gtk/gtkcssimagewin32.c b/gtk/gtkcssimagewin32.c
index 9ebd2f3..342178e 100644
--- a/gtk/gtkcssimagewin32.c
+++ b/gtk/gtkcssimagewin32.c
@@ -35,8 +35,8 @@ gtk_css_image_win32_draw (GtkCssImage *image,
cairo_surface_t *surface;
int dx, dy;
- surface = _gtk_win32_theme_part_create_surface (wimage->theme, wimage->part, wimage->state,
wimage->margins,
- width, height, &dx, &dy);
+ surface = gtk_win32_theme_create_surface (wimage->theme, wimage->part, wimage->state, wimage->margins,
+ width, height, &dx, &dy);
if (wimage->state2 >= 0)
{
@@ -44,8 +44,8 @@ gtk_css_image_win32_draw (GtkCssImage *image,
cairo_t *cr2;
int dx2, dy2;
- surface2 = _gtk_win32_theme_part_create_surface (wimage->theme, wimage->part2, wimage->state2,
wimage->margins,
- width, height, &dx2, &dy2);
+ surface2 = gtk_win32_theme_create_surface (wimage->theme, wimage->part2, wimage->state2,
wimage->margins,
+ width, height, &dx2, &dy2);
cr2 = cairo_create (surface);
@@ -92,7 +92,7 @@ gtk_css_image_win32_parse (GtkCssImage *image,
"Expected name as first argument to '-gtk-win32-theme-part'");
return FALSE;
}
- wimage->theme = _gtk_win32_lookup_htheme_by_classname (class);
+ wimage->theme = gtk_win32_theme_lookup (class);
g_free (class);
if (! _gtk_css_parser_try (parser, ",", TRUE))
@@ -215,9 +215,23 @@ gtk_css_image_win32_print (GtkCssImage *image,
}
static void
+gtk_css_image_win32_finalize (GObject *object)
+{
+ GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (object);
+
+ if (wimage->theme)
+ gtk_win32_theme_unref (wimage->theme);
+
+ G_OBJECT_CLASS (_gtk_css_image_win32_parent_class)->finalize (object);
+}
+
+static void
_gtk_css_image_win32_class_init (GtkCssImageWin32Class *klass)
{
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_css_image_win32_finalize;
image_class->draw = gtk_css_image_win32_draw;
image_class->parse = gtk_css_image_win32_parse;
diff --git a/gtk/gtkcssimagewin32private.h b/gtk/gtkcssimagewin32private.h
index e62f88b..da58412 100644
--- a/gtk/gtkcssimagewin32private.h
+++ b/gtk/gtkcssimagewin32private.h
@@ -48,7 +48,7 @@ struct _GtkCssImageWin32
gint margins[4];
- HTHEME theme;
+ GtkWin32Theme *theme;
};
struct _GtkCssImageWin32Class
diff --git a/gtk/gtkwin32theme.c b/gtk/gtkwin32theme.c
index 3d0abe3..a430f99 100644
--- a/gtk/gtkwin32theme.c
+++ b/gtk/gtkwin32theme.c
@@ -25,9 +25,12 @@
#ifdef G_OS_WIN32
+#include <windows.h>
#include <gdk/win32/gdkwin32.h>
#include <cairo-win32.h>
+typedef HANDLE HTHEME;
+
#define UXTHEME_DLL "uxtheme.dll"
static HINSTANCE uxtheme_dll = NULL;
@@ -64,7 +67,7 @@ static GetThemeSysFontFunc get_theme_sys_font = NULL;
static GetThemeSysColorFunc get_theme_sys_color = NULL;
static GetThemeSysSizeFunc get_theme_sys_metric = NULL;
static OpenThemeDataFunc open_theme_data = NULL;
-static CloseThemeDataFunc close_theme_data = NULL;
+static CloseThemeDataFunc CloseThemeData = NULL;
static DrawThemeBackgroundFunc draw_theme_background = NULL;
static EnableThemeDialogTextureFunc enable_theme_dialog_texture = NULL;
static IsThemeActiveFunc is_theme_active = NULL;
@@ -73,13 +76,66 @@ static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent
static DrawThemeParentBackgroundFunc draw_theme_parent_background = NULL;
static GetThemePartSizeFunc get_theme_part_size = NULL;
-static GHashTable *hthemes_by_class = NULL;
+#endif
+
+static GHashTable *themes_by_class = NULL;
+
+struct _GtkWin32Theme {
+ char *class_name;
+ gint ref_count;
+#ifdef G_OS_WIN32
+ HTHEME htheme;
+#endif
+};
+
+GtkWin32Theme *
+gtk_win32_theme_ref (GtkWin32Theme *theme)
+{
+ theme->ref_count++;
+
+ return theme;
+}
+
+static gboolean
+gtk_win32_theme_close (GtkWin32Theme *theme)
+{
+#ifdef G_OS_WIN32
+ if (theme->htheme)
+ {
+ CloseThemeData (theme->htheme);
+ theme->htheme = NULL;
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+void
+gtk_win32_theme_unref (GtkWin32Theme *theme)
+{
+ theme->ref_count--;
+
+ if (theme->ref_count > 0)
+ return;
+
+ g_hash_table_remove (themes_by_class, theme->class_name);
+
+ gtk_win32_theme_close (theme);
+ g_free (theme->class_name);
+
+ g_slice_free (GtkWin32Theme, theme);
+}
+
+#ifdef G_OS_WIN32
static GdkFilterReturn
invalidate_win32_themes (GdkXEvent *xevent,
GdkEvent *event,
gpointer unused)
{
+ GHashTableIter iter;
+ gboolean theme_was_open = FALSE;
+ gpointer theme;
MSG *msg;
if (!GDK_IS_WIN32_WINDOW (event->any.window))
@@ -89,11 +145,14 @@ invalidate_win32_themes (GdkXEvent *xevent,
if (msg->message != WM_THEMECHANGED)
return GDK_FILTER_CONTINUE;
- if (g_hash_table_size (hthemes_by_class) > 0)
+ g_hash_table_iter_init (&iter, themes_by_class);
+ while (g_hash_table_iter_next (&iter, NULL, &theme))
+ {
+ theme_was_open |= gtk_win32_theme_close (theme);
+ }
+ if (theme_was_open)
gtk_style_context_reset_widgets (gdk_display_get_default_screen (gdk_window_get_display
(event->any.window)));
- g_hash_table_remove_all (hthemes_by_class);
-
return GDK_FILTER_CONTINUE;
}
@@ -134,7 +193,7 @@ _gtk_win32_theme_init (void)
{
is_theme_active = (IsThemeActiveFunc) GetProcAddress (uxtheme_dll, "IsThemeActive");
open_theme_data = (OpenThemeDataFunc) GetProcAddress (uxtheme_dll, "OpenThemeData");
- close_theme_data = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData");
+ CloseThemeData = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData");
draw_theme_background = (DrawThemeBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeBackground");
enable_theme_dialog_texture = (EnableThemeDialogTextureFunc) GetProcAddress (uxtheme_dll,
"EnableThemeDialogTexture");
get_theme_sys_font = (GetThemeSysFontFunc) GetProcAddress (uxtheme_dll, "GetThemeSysFont");
@@ -154,64 +213,62 @@ _gtk_win32_theme_init (void)
use_xp_theme = FALSE;
}
- hthemes_by_class = g_hash_table_new (g_str_hash, g_str_equal);
+ themes_by_class = g_hash_table_new (g_str_hash, g_str_equal);
gdk_window_add_filter (NULL, invalidate_win32_themes, NULL);
}
-HTHEME
-_gtk_win32_lookup_htheme_by_classname (const char *class)
+static HTHEME
+gtk_win32_theme_get_htheme (GtkWin32Theme *theme)
{
- HTHEME theme;
guint16 *wclass;
char *lower;
- _gtk_win32_theme_init ();
+ if (theme->htheme)
+ return theme->htheme;
- lower = g_ascii_strdown (class, -1);
-
- theme = (HTHEME) g_hash_table_lookup (hthemes_by_class, lower);
- if (theme)
- {
- g_free (lower);
- return theme;
- }
+ lower = g_ascii_strdown (theme->class_name, -1);
wclass = g_utf8_to_utf16 (lower, -1, NULL, NULL, NULL);
- theme = open_theme_data (NULL, wclass);
+ theme->htheme = open_theme_data (NULL, wclass);
g_free (wclass);
+ g_free (lower);
- if (theme == NULL)
- {
- g_free (lower);
- return NULL;
- }
-
- /* Takes ownership of lower: */
- g_hash_table_insert (hthemes_by_class, lower, theme);
-
- return theme;
+ return theme->htheme;
}
-#else
+#endif /* G_OS_WIN32 */
-HTHEME
-_gtk_win32_lookup_htheme_by_classname (const char *class)
+GtkWin32Theme *
+gtk_win32_theme_lookup (const char *classname)
{
- return NULL;
-}
+ GtkWin32Theme *theme;
-#endif /* G_OS_WIN32 */
+ _gtk_win32_theme_init ();
+
+ theme = g_hash_table_lookup (themes_by_class, classname);
+
+ if (theme != NULL)
+ return gtk_win32_theme_ref (theme);
+
+ theme = g_slice_new0 (GtkWin32Theme);
+ theme->ref_count = 1;
+ theme->class_name = g_strdup (classname);
+
+ g_hash_table_insert (themes_by_class, theme->class_name, theme);
+
+ return theme;
+}
cairo_surface_t *
-_gtk_win32_theme_part_create_surface (HTHEME theme,
- int xp_part,
- int state,
- int margins[4],
- int width,
- int height,
- int *x_offs_out,
- int *y_offs_out)
+gtk_win32_theme_create_surface (GtkWin32Theme *theme,
+ int xp_part,
+ int state,
+ int margins[4],
+ int width,
+ int height,
+ int *x_offs_out,
+ int *y_offs_out)
{
cairo_surface_t *surface;
GdkRGBA color;
@@ -224,6 +281,7 @@ _gtk_win32_theme_part_create_surface (HTHEME theme,
RECT rect;
SIZE size;
HRESULT res;
+ HTHEME htheme;
#endif
x_offs = margins[3];
@@ -233,46 +291,51 @@ _gtk_win32_theme_part_create_surface (HTHEME theme,
height -= margins[0] + margins[2];
#ifdef G_OS_WIN32
- rect.left = 0;
- rect.top = 0;
- rect.right = width;
- rect.bottom = height;
-
- hdc = GetDC (NULL);
- res = get_theme_part_size (theme, hdc, xp_part, state, &rect, 2, &size);
- ReleaseDC (NULL, hdc);
-
- if (res == S_OK)
+ htheme = gtk_win32_theme_get_htheme (theme);
+ if (htheme)
{
- x_offs += (width - size.cx) / 2;
- y_offs += (height - size.cy) / 2;
-
- width = size.cx;
- height = size.cy;
-
+ rect.left = 0;
+ rect.top = 0;
rect.right = width;
rect.bottom = height;
- }
-
- has_alpha = is_theme_partially_transparent (theme, xp_part, state);
- if (has_alpha)
- surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
- else
- surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
- hdc = cairo_win32_surface_get_dc (surface);
+ hdc = GetDC (NULL);
+ res = get_theme_part_size (htheme, hdc, xp_part, state, &rect, 2, &size);
+ ReleaseDC (NULL, hdc);
+
+ if (res == S_OK)
+ {
+ x_offs += (width - size.cx) / 2;
+ y_offs += (height - size.cy) / 2;
+
+ width = size.cx;
+ height = size.cy;
+
+ rect.right = width;
+ rect.bottom = height;
+ }
+
+ has_alpha = is_theme_partially_transparent (htheme, xp_part, state);
+ if (has_alpha)
+ surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+ else
+ surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
- res = draw_theme_background (theme, hdc, xp_part, state, &rect, &rect);
+ hdc = cairo_win32_surface_get_dc (surface);
- *x_offs_out = x_offs;
- *y_offs_out = y_offs;
+ res = draw_theme_background (htheme, hdc, xp_part, state, &rect, &rect);
- if (res == S_OK)
- return surface;
+ *x_offs_out = x_offs;
+ *y_offs_out = y_offs;
-#else /* !G_OS_WIN32 */
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ if (res == S_OK)
+ return surface;
+ }
+ else
#endif /* G_OS_WIN32 */
+ {
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ }
cr = cairo_create (surface);
@@ -293,8 +356,12 @@ int
_gtk_win32_theme_int_parse (GtkCssParser *parser,
int *value)
{
- char *class;
+ char *theme_class;
int arg;
+#ifdef G_OS_WIN32
+ GtkWin32Theme *theme;
+ HTHEME htheme;
+#endif
if (_gtk_css_parser_try (parser,
"-gtk-win32-size",
@@ -307,8 +374,8 @@ _gtk_win32_theme_int_parse (GtkCssParser *parser,
return 0;
}
- class = _gtk_css_parser_try_name (parser, TRUE);
- if (class == 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'");
@@ -317,7 +384,7 @@ _gtk_win32_theme_int_parse (GtkCssParser *parser,
if (! _gtk_css_parser_try (parser, ",", TRUE))
{
- g_free (class);
+ g_free (theme_class);
_gtk_css_parser_error (parser,
"Expected ','");
return 0;
@@ -325,33 +392,38 @@ _gtk_win32_theme_int_parse (GtkCssParser *parser,
if (!_gtk_css_parser_try_int (parser, &arg))
{
- g_free (class);
+ 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 theme = _gtk_win32_lookup_htheme_by_classname (class);
+ {
+ htheme = gtk_win32_theme_get_htheme (theme);
- /* If theme is NULL it will just return the GetSystemMetrics value */
- *value = get_theme_sys_metric (theme, arg);
+ /* 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 (class);
+ g_free (theme_class);
return 1;
}
@@ -365,19 +437,24 @@ _gtk_win32_theme_color_resolve (const char *theme_class,
GdkRGBA *color)
{
#ifdef G_OS_WIN32
+ GtkWin32Theme *theme;
+ HTHEME htheme;
DWORD dcolor;
+ theme = gtk_win32_theme_lookup (theme_class);
if (use_xp_theme && get_theme_sys_color != NULL)
{
- HTHEME theme = _gtk_win32_lookup_htheme_by_classname (theme_class);
+ htheme = gtk_win32_theme_get_htheme (theme);
- /* if theme is NULL, it will just return the GetSystemColor()
+ /* if htheme is NULL, it will just return the GetSystemColor()
value */
- dcolor = get_theme_sys_color (theme, id);
+ dcolor = get_theme_sys_color (htheme, id);
}
else
dcolor = GetSysColor (id);
+ gtk_win32_theme_unref (theme);
+
color->alpha = 1.0;
color->red = GetRValue (dcolor) / 255.0;
color->green = GetGValue (dcolor) / 255.0;
diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h
index 90fcac9..412c88c 100644
--- a/gtk/gtkwin32themeprivate.h
+++ b/gtk/gtkwin32themeprivate.h
@@ -22,31 +22,25 @@
#include "gtkcssparserprivate.h"
-#ifdef G_OS_WIN32
-
-#include <windows.h>
-
-typedef HANDLE HTHEME;
-
-#else /* !G_OS_WIN32 */
+G_BEGIN_DECLS
-typedef void * HTHEME;
+typedef struct _GtkWin32Theme GtkWin32Theme;
-#endif /* G_OS_WIN32 */
+#define GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME "-gtk-win32-color"
-G_BEGIN_DECLS
+GtkWin32Theme * gtk_win32_theme_lookup (const char *classname);
-#define GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME "-gtk-win32-color"
+GtkWin32Theme * gtk_win32_theme_ref (GtkWin32Theme *theme);
+void gtk_win32_theme_unref (GtkWin32Theme *theme);
-HTHEME _gtk_win32_lookup_htheme_by_classname (const char *classname);
-cairo_surface_t * _gtk_win32_theme_part_create_surface (HTHEME theme,
- int xp_part,
- int state,
- int margins[4],
- int width,
- int height,
- int *x_offs_out,
- int *y_offs_out);
+cairo_surface_t * gtk_win32_theme_create_surface (GtkWin32Theme *theme,
+ int xp_part,
+ int state,
+ int margins[4],
+ int width,
+ int height,
+ int *x_offs_out,
+ int *y_offs_out);
int _gtk_win32_theme_int_parse (GtkCssParser *parser,
int *value);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]