diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-08-02 23:49:17 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-08-02 23:49:17 (GMT) |
commit | c3bfd743a8422e7c844ccf3247b142af548209b8 (patch) | |
tree | 7073f153d0f5a0589e0c44166b65649ec047040d /src/glibext | |
parent | 9226736f0702db296433466462cfbad5a11bf46b (diff) |
Allowed to emit signals to GTK main thread for GUI updates in a generic way.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@563 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/signal.c | 98 | ||||
-rw-r--r-- | src/glibext/signal.h | 2 |
2 files changed, 62 insertions, 38 deletions
diff --git a/src/glibext/signal.c b/src/glibext/signal.c index c7c8fe3..dd4f00b 100644 --- a/src/glibext/signal.c +++ b/src/glibext/signal.c @@ -24,8 +24,11 @@ #include "signal.h" +#include <assert.h> #include <malloc.h> #include <stdarg.h> +#include <stdbool.h> +#include <gobject/gvaluecollector.h> @@ -36,24 +39,26 @@ typedef void (* GSignalCallback) (gpointer, ...); /* Informations concernant une diffusion de signal */ typedef struct _gsignal_wrapper_info { - GConnectFlags flags; /* Ordre des arguments */ - - GSignalCallback callback; /* Fonction finale de récept° */ gpointer instance; /* Instance GLib initiatrice */ - gpointer data; /* Donnée utilisateur associée */ + GClosure *closure; /* Glue pour les appels */ + + GType return_type; /* Type de la valeur retournée */ guint n_params; /* Nombre de paramètres */ - unsigned long params[0]; /* Paramètres récupérés */ + const GType *param_types; /* Type des paramètres associés*/ + + GValue return_value; /* Valeur de retour */ + GValue instance_and_params[0]; /* Instance & paramètres */ } gsignal_wrapper_info; -/* Réceptionne un signal et redirige son exécution. */ -static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...); - /* Transmet un signal dans le contexte principal. */ static gboolean to_main_wrapper(gsignal_wrapper_info *); +/* Réceptionne un signal et redirige son exécution. */ +static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...); + /****************************************************************************** @@ -70,27 +75,9 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *); static gboolean to_main_wrapper(gsignal_wrapper_info *info) { - gpointer data1; /* Premier argument à envoyer */ - gpointer data2; /* Dernier argument à envoyer */ - - if (info->flags & G_CONNECT_SWAPPED) - { - data1 = info->data; - data2 = info->instance; - } - else - { - data1 = info->instance; - data2 = info->data; - } - - switch (info->n_params - 1) - { - case 0: - info->callback(data1, data2); - break; - - } + g_closure_invoke(info->closure, NULL/*&info->return_value*/, + info->n_params + 1, info->instance_and_params, + NULL); return G_SOURCE_REMOVE; @@ -112,17 +99,51 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info) static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...) { + GValue *param_values; /* Paramètres d'appel */ va_list ap; /* Liste d'arguments sur pile */ guint i; /* Boucle de parcours */ + bool static_scope; /* Portée des arguments */ + gchar *error; /* Eventuelle erreur inattendue*/ + + //g_value_init(&info->return_value, info->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); + + if (G_IS_VALUE(info->instance_and_params)) + g_value_unset(info->instance_and_params); + + g_value_init(info->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance)); + g_value_set_instance(info->instance_and_params, info->instance); + + param_values = info->instance_and_params + 1; va_start(ap, info); + error = NULL; + for (i = 0; i < info->n_params; i++) - info->params[i] = va_arg(ap, unsigned long); + { + if (G_IS_VALUE(param_values + i)) + g_value_unset(param_values + i); + + static_scope = info->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; + + G_VALUE_COLLECT_INIT(param_values + i, + info->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, + ap, static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, + &error); + + if (error != NULL) + { + fprintf(stderr, "%s: %s", G_STRLOC, error); + g_free(error); + break; + } + + } va_end(ap); - g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, free); + if (error == NULL) + g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, NULL); } @@ -142,7 +163,7 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...) * * ******************************************************************************/ -gulong g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data) +gulong g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal) { guint signal_id; /* Identifiant du signal visé */ GSignalQuery query; /* Information sur le signal */ @@ -156,15 +177,18 @@ gulong g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallbac /* Allocation adaptée */ - info = (gsignal_wrapper_info *)malloc(sizeof(gsignal_wrapper_info) + sizeof(unsigned long) * ++query.n_params); - - info->flags = 0; + info = (gsignal_wrapper_info *)calloc(1, sizeof(gsignal_wrapper_info) + sizeof(GValue) * (query.n_params + 1)); - info->callback = (GSignalCallback)handler; info->instance = instance; - info->data = data; + info->closure = g_cclosure_new(handler, data, NULL); + g_closure_set_marshal(info->closure, marshal); + + info->return_type = query.return_type; info->n_params = query.n_params; + info->param_types = query.param_types; + + assert(query.return_type == G_TYPE_NONE); return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info); diff --git a/src/glibext/signal.h b/src/glibext/signal.h index c2a442d..e29210c 100644 --- a/src/glibext/signal.h +++ b/src/glibext/signal.h @@ -31,7 +31,7 @@ /* Reproduit le comportement de la fonction g_signal_connect(). */ -gulong g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer); +gulong g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal); |