summaryrefslogtreecommitdiff
path: root/src/glibext/signal.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-08-02 23:49:17 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-08-02 23:49:17 (GMT)
commitc3bfd743a8422e7c844ccf3247b142af548209b8 (patch)
tree7073f153d0f5a0589e0c44166b65649ec047040d /src/glibext/signal.c
parent9226736f0702db296433466462cfbad5a11bf46b (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/signal.c')
-rw-r--r--src/glibext/signal.c98
1 files changed, 61 insertions, 37 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);