diff options
Diffstat (limited to 'gtk/gtkthemes.c')
-rw-r--r-- | gtk/gtkthemes.c | 198 |
1 files changed, 179 insertions, 19 deletions
diff --git a/gtk/gtkthemes.c b/gtk/gtkthemes.c index 571ec6574e..e79b737fa4 100644 --- a/gtk/gtkthemes.c +++ b/gtk/gtkthemes.c @@ -37,20 +37,34 @@ #include "config.h" #include "gtkintl.h" -typedef struct _GtkThemeEnginePrivate GtkThemeEnginePrivate; +typedef struct _GtkThemeEnginePlugin GtkThemeEnginePlugin; -struct _GtkThemeEnginePrivate { - GtkThemeEngine engine; - +struct _GtkThemeEngine +{ GModule *library; - void *name; void (*init) (GtkThemeEngine *); void (*exit) (void); + GtkRcStyle *(*create_rc_style) (); + gchar *name; + + GSList *plugins; /* TypePlugins for this engine */ + guint refcount; }; +struct _GtkThemeEnginePlugin +{ + GTypePlugin plugin; + + GtkThemeEngine *engine; + gchar *engine_name; + GTypeInfo info; + GType type; + GType parent_type; +}; + static GHashTable *engine_hash = NULL; #ifdef __EMX__ @@ -67,7 +81,7 @@ static void gen_8_3_dll_name(gchar *name, gchar *fullname) GtkThemeEngine* gtk_theme_engine_get (const gchar *name) { - GtkThemeEnginePrivate *result; + GtkThemeEngine *result; if (!engine_hash) engine_hash = g_hash_table_new (g_str_hash, g_str_equal); @@ -121,17 +135,20 @@ gtk_theme_engine_get (const gchar *name) } else { - result = g_new (GtkThemeEnginePrivate, 1); + result = g_new (GtkThemeEngine, 1); result->refcount = 1; result->name = g_strdup (name); result->library = library; + result->plugins = NULL; /* extract symbols from the lib */ if (!g_module_symbol (library, "theme_init", (gpointer *)&result->init) || !g_module_symbol (library, "theme_exit", - (gpointer *)&result->exit)) + (gpointer *)&result->exit) || + !g_module_symbol (library, "theme_create_rc_style", + (gpointer *)&result->create_rc_style)) { g_warning (g_module_error()); g_free (result); @@ -156,28 +173,171 @@ gtk_theme_engine_ref (GtkThemeEngine *engine) { g_return_if_fail (engine != NULL); - ((GtkThemeEnginePrivate *)engine)->refcount++; + engine->refcount++; } void gtk_theme_engine_unref (GtkThemeEngine *engine) { - GtkThemeEnginePrivate *private; - private = (GtkThemeEnginePrivate *)engine; + GSList *tmp_list; g_return_if_fail (engine != NULL); - g_return_if_fail (private->refcount > 0); + g_return_if_fail (engine->refcount > 0); - private->refcount--; + engine->refcount--; - if (private->refcount == 0) + if (engine->refcount == 0) { - private->exit(); + engine->exit(); + + g_hash_table_remove (engine_hash, engine->name); + + tmp_list = engine->plugins; + while (tmp_list) + { + GtkThemeEnginePlugin *plugin = tmp_list->data; + plugin->engine = NULL; + + tmp_list = tmp_list->next; + } + g_slist_free (engine->plugins); - g_hash_table_remove (engine_hash, private->name); + g_module_close (engine->library); + g_free (engine->name); + g_free (engine); + } +} + +GtkRcStyle * +gtk_theme_engine_create_rc_style (GtkThemeEngine *engine) +{ + g_return_val_if_fail (engine != NULL, NULL); + + return engine->create_rc_style (); +} + +static void +gtk_theme_engine_plugin_ref (GTypePlugin *plugin) +{ + GtkThemeEnginePlugin *theme_plugin = (GtkThemeEnginePlugin *)plugin; + + if (theme_plugin->engine == NULL) + { + gtk_theme_engine_get (theme_plugin->engine_name); + if (!theme_plugin->engine) + { + g_warning ("An attempt to create an instance of a type from\n" + "a previously loaded theme engine was made after the engine\n" + "was unloaded, but the engine could not be reloaded or no longer\n" + "implements the type. Bad things will happen.\n"); + } + } + else + gtk_theme_engine_ref (theme_plugin->engine); +} + +static void +gtk_theme_engine_plugin_unref (GTypePlugin *plugin) +{ + GtkThemeEnginePlugin *theme_plugin = (GtkThemeEnginePlugin *)plugin; + + g_return_if_fail (theme_plugin->engine != NULL); + + gtk_theme_engine_unref (theme_plugin->engine); +} + +static void +gtk_theme_engine_complete_type_info (GTypePlugin *plugin, + GType g_type, + GTypeInfo *info, + GTypeValueTable *value_table) +{ + GtkThemeEnginePlugin *theme_plugin = (GtkThemeEnginePlugin *)plugin; + + *info = theme_plugin->info; +} + +static GTypePluginVTable gtk_theme_engine_plugin_vtable = { + gtk_theme_engine_plugin_ref, + gtk_theme_engine_plugin_unref, + gtk_theme_engine_complete_type_info, + NULL +}; + +/** + * gtk_theme_engine_register_type: + * @engine: a #GtkThemeEngine + * @parent_type: the type for the parent class + * @type_name: name for the type + * @type_info: type information structure + * + * Looks up or registers a type that is implemented with a particular + * theme engine. If a type with name @type_name is already registered, + * the #GType identifier for the type is returned, otherwise the type + * is newly registered, and the resulting #GType identifier returned. + * + * As long as any instances of the type exist, the a reference will be + * held to the theme engine and the theme engine will not be unloaded. + * + * Return value: the type identifier for the class. + **/ +GType +gtk_theme_engine_register_type (GtkThemeEngine *engine, + GType parent_type, + const gchar *type_name, + const GTypeInfo *type_info) +{ + GtkThemeEnginePlugin *plugin; + GType type; + + g_return_val_if_fail (engine != NULL, 0); + g_return_val_if_fail (type_name != NULL, 0); + g_return_val_if_fail (type_info != NULL, 0); + + type = g_type_from_name (type_name); + if (type) + plugin = (GtkThemeEnginePlugin *)g_type_get_plugin (type); + else + { + plugin = g_new (GtkThemeEnginePlugin, 1); + + plugin->plugin.vtable = >k_theme_engine_plugin_vtable; + plugin->engine = NULL; + plugin->engine_name = NULL; + plugin->parent_type = parent_type; + plugin->type = g_type_register_dynamic (parent_type, type_name, (GTypePlugin *)plugin); + } + + if (plugin->engine) + { + if (plugin->engine != engine) + { + g_warning ("Two different theme engines tried to register '%s'.", type_name); + return 0; + } + + if (plugin->parent_type != parent_type) + { + g_warning ("Type '%s' recreated with different parent type.\n" + "(was '%s', now '%s')", type_name, + g_type_name (plugin->parent_type), + g_type_name (parent_type)); + return 0; + } + } + else + { + plugin->engine = engine; + if (plugin->engine_name) + g_free (plugin->engine_name); + + plugin->engine_name = g_strdup (engine->name); - g_module_close (private->library); - g_free (private->name); - g_free (private); + plugin->info = *type_info; + + engine->plugins = g_slist_prepend (engine->plugins, plugin); } + + return plugin->type; } + |