summaryrefslogtreecommitdiff
path: root/gtk/gtksignal.c
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>1998-12-07 02:31:19 +0000
committerTim Janik <timj@src.gnome.org>1998-12-07 02:31:19 +0000
commit33447a38564dbc0c0db28f9eb4efb86a16be1505 (patch)
tree07d1e49c3f003bc1170ff454b01f6469de16960f /gtk/gtksignal.c
parent031aa464c6c3ba3758412dae1c7c0da3f8dea14b (diff)
downloadgtk+-33447a38564dbc0c0db28f9eb4efb86a16be1505.tar.gz
reverted marius change to expose the type systems internal type info data
Mon Dec 7 03:08:39 1998 Tim Janik <timj@gtk.org> * gtk/gtktypeutils.h: * gtk/gtktypeutils.c: reverted marius change to expose the type systems internal type info data to the user. if such functionality is required we should provide wrapped accessors, ala gtk_signal_query(). * gtk/gtksignal.c (gtk_signal_connect_by_type): reverted marius change, since it destroys the possibility to implement automatic marshaller lookups some day, and it also disables third party code's ability to connect to any signal. also the GtkTypeInfo structures are dynamically allocated memory portions, so only the type system is really allowed to access that stuff. Mon Dec 7 01:32:18 1998 Tim Janik <timj@gtk.org> * gtk/gtkfilesel.c (gtk_file_selection_key_press): always intercept the Tab key on the entry. the focus shouldn't get lost even if completion is attempted from an empty entry, since an empty entry string does indeed have a valid completion meaning (complete all). (gtk_file_selection_init): cast the gchar array parameter in calls to gtk_clist_new_with_titles() to quit compiler warnings. (check_dir): the no_stat_dirs struct must not be const, since we do indeed modify its contents. * gtk/testgtk.c (event_watcher): adapted prototype to fit new emission hook semantics. * gtk/gtksignal.h: * gtk/gtksignal.c: changed emission allocation, so we don't use a doubly linked list but link ourselfs (singly linked). changed emission hooks, they get the emision parameters passed as well now and are emitted during the actuall signal emission (after the RUN_FIRST class method, but prior to RUN_FIRST handlers). the existing restrictions do still apply to signal emission hooks, i.e. an emission may not be stopped or restarted from an emission hook. due to possibly huge perfomance impacts, frequent use of emision hooks is also not recommended. (gtk_signal_next_and_invalidate): added an assertments which explicits what the code assumes anyways: a maximum amount of 65535 signals. * gtk/gtkcontainer.h: deprecated gtk_container_foreach_interp(), gtk_container_foreach_full() should be used instead. * gtk/gtkmain.h: deprecated gtk_timeout_add_interp and gtk_idle_add_interp, since we provide _full variants. * gtk/gtksignal.h: deprecated gtk_signal_connect_interp(), we provide gtk_signal_connect_full() for long enough now.
Diffstat (limited to 'gtk/gtksignal.c')
-rw-r--r--gtk/gtksignal.c214
1 files changed, 110 insertions, 104 deletions
diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c
index 18f938ae0c..5e52fee3c4 100644
--- a/gtk/gtksignal.c
+++ b/gtk/gtksignal.c
@@ -43,7 +43,7 @@ typedef struct _GtkSignal GtkSignal;
typedef struct _GtkSignalHash GtkSignalHash;
typedef struct _GtkHandler GtkHandler;
typedef struct _GtkEmission GtkEmission;
-typedef union _GtkEmissionAllocator GtkEmissionAllocator;
+typedef struct _GtkEmissionHookData GtkEmissionHookData;
typedef struct _GtkDisconnectInfo GtkDisconnectInfo;
typedef void (*GtkSignalMarshaller0) (GtkObject *object,
@@ -88,14 +88,18 @@ struct _GtkHandler
struct _GtkEmission
{
- GtkObject *object;
- guint signal_id;
+ GtkObject *object;
+ guint16 signal_id;
+ guint in_hook : 1;
+ GtkEmission *next;
};
-union _GtkEmissionAllocator
+struct _GtkEmissionHookData
{
- GtkEmissionAllocator *next;
- GtkEmission emission;
+ GtkObject *object;
+ guint signal_id;
+ guint n_params;
+ GtkArg *params;
};
struct _GtkDisconnectInfo
@@ -132,13 +136,13 @@ static guint gtk_signal_connect_by_type (GtkObject *object,
gint no_marshal);
static guint gtk_alive_disconnecter (GtkDisconnectInfo *info);
static GtkEmission* gtk_emission_new (void);
-static void gtk_emission_add (GList **emissions,
+static void gtk_emission_add (GtkEmission **emissions,
GtkObject *object,
guint signal_type);
-static void gtk_emission_remove (GList **emissions,
+static void gtk_emission_remove (GtkEmission **emissions,
GtkObject *object,
guint signal_type);
-static gint gtk_emission_check (GList *emissions,
+static gint gtk_emission_check (GtkEmission *emissions,
GtkObject *object,
guint signal_type);
static gint gtk_handlers_run (GtkHandler *handlers,
@@ -172,13 +176,13 @@ static guint gtk_n_signals = 0;
static GMemChunk *gtk_signal_hash_mem_chunk = NULL;
static GMemChunk *gtk_disconnect_info_mem_chunk = NULL;
static GtkHandler *gtk_handler_free_list = NULL;
-static GtkEmissionAllocator *gtk_emission_free_list = NULL;
+static GtkEmission *gtk_free_emissions = NULL;
-static GList *current_emissions = NULL;
-static GList *stop_emissions = NULL;
-static GList *restart_emissions = NULL;
+static GtkEmission *current_emissions = NULL;
+static GtkEmission *stop_emissions = NULL;
+static GtkEmission *restart_emissions = NULL;
static GtkSignal*
gtk_signal_next_and_invalidate (void)
@@ -213,6 +217,8 @@ gtk_signal_next_and_invalidate (void)
new_signal_id = gtk_n_signals++;
gtk_n_free_signals--;
+
+ g_assert (gtk_n_signals < 65535);
signal = LOOKUP_SIGNAL_ID (new_signal_id);
if (signal)
@@ -244,7 +250,7 @@ gtk_signal_init (void)
sizeof (GtkDisconnectInfo) * DISCONNECT_INFO_BLOCK_SIZE,
G_ALLOC_AND_FREE);
gtk_handler_free_list = NULL;
- gtk_emission_free_list = NULL;
+ gtk_free_emissions = NULL;
gtk_signal_hash_table = g_hash_table_new (gtk_signal_hash,
gtk_signal_compare);
@@ -268,6 +274,7 @@ gtk_signal_newv (const gchar *r_name,
gchar *name;
g_return_val_if_fail (r_name != NULL, 0);
+ g_return_val_if_fail (marshaller != NULL, 0);
g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0);
if (nparams)
g_return_val_if_fail (params != NULL, 0);
@@ -587,10 +594,17 @@ void
gtk_signal_emit_stop (GtkObject *object,
guint signal_id)
{
+ gint state;
+
g_return_if_fail (object != NULL);
g_return_if_fail (signal_id >= 1);
- if (gtk_emission_check (current_emissions, object, signal_id))
+ state = gtk_emission_check (current_emissions, object, signal_id);
+ if (state > 1)
+ g_warning ("gtk_signal_emit_stop(): emission (%u) for object `%s' cannot be stopped from emission hook",
+ signal_id,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ else if (state)
{
if (!gtk_emission_check (stop_emissions, object, signal_id))
gtk_emission_add (&stop_emissions, object, signal_id);
@@ -623,21 +637,16 @@ guint
gtk_signal_n_emissions (GtkObject *object,
guint signal_id)
{
- GList *list;
+ GtkEmission *emission;
guint n;
g_return_val_if_fail (object != NULL, 0);
g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
n = 0;
- for (list = current_emissions; list; list = list->next)
+ for (emission = current_emissions; emission; emission = emission->next)
{
- GtkEmission *emission;
-
- emission = list->data;
-
- if ((emission->object == object) &&
- (emission->signal_id == signal_id))
+ if (emission->object == object && emission->signal_id == signal_id)
n++;
}
@@ -759,6 +768,8 @@ gtk_signal_connect_interp (GtkObject *object,
GtkDestroyNotify destroy_func,
gint after)
{
+ g_message ("gtk_signal_connect_interp() is deprecated");
+
return gtk_signal_connect_full (object, name, NULL, func,
func_data, destroy_func, FALSE, after);
}
@@ -1346,16 +1357,10 @@ gtk_signal_real_emit (GtkObject *object,
guint signal_id,
GtkArg *params)
{
- static guint emission_hooks_called = 0;
GtkSignal signal;
GtkHandler *handlers;
GtkSignalFunc signal_func;
-
- if (emission_hooks_called)
- {
- g_warning ("gtk_signal_real_emit() may not recurse from emission hooks");
- return;
- }
+ GtkEmission *emission;
/* gtk_handlers_run() expects a reentrant GtkSignal*, so we allocate
* it locally on the stack. we save some lookups ourselves with this as well.
@@ -1376,18 +1381,28 @@ gtk_signal_real_emit (GtkObject *object,
signal_func);
#endif /* G_ENABLE_DEBUG */
- if (signal.signal_flags & GTK_RUN_NO_RECURSE &&
- gtk_emission_check (current_emissions, object, signal_id))
+ if (signal.signal_flags & GTK_RUN_NO_RECURSE)
{
- if (!gtk_emission_check (restart_emissions, object, signal_id))
- gtk_emission_add (&restart_emissions, object, signal_id);
-
- return;
+ gint state;
+
+ state = gtk_emission_check (current_emissions, object, signal_id);
+ if (state)
+ {
+ if (state > 1)
+ g_warning ("gtk_signal_real_emit(): emission (%u) for object `%s' cannot be restarted from emission hook",
+ signal_id,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ else if (!gtk_emission_check (restart_emissions, object, signal_id))
+ gtk_emission_add (&restart_emissions, object, signal_id);
+
+ return;
+ }
}
gtk_object_ref (object);
gtk_emission_add (&current_emissions, object, signal_id);
+ emission = current_emissions;
emission_restart:
@@ -1410,6 +1425,19 @@ gtk_signal_real_emit (GtkObject *object,
}
}
+ if (signal.hook_list && !GTK_OBJECT_DESTROYED (object))
+ {
+ GtkEmissionHookData data;
+
+ data.object = object;
+ data.n_params = signal.nparams;
+ data.params = params;
+ data.signal_id = signal_id;
+ emission->in_hook = 1;
+ g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data);
+ emission->in_hook = 0;
+ }
+
if (GTK_OBJECT_CONNECTED (object))
{
handlers = gtk_signal_get_handlers (object, signal_id);
@@ -1475,19 +1503,6 @@ gtk_signal_real_emit (GtkObject *object,
gtk_emission_remove (&current_emissions, object, signal_id);
- /* the hook invokation portion may not be moved!
- */
- if (signal.hook_list && !GTK_OBJECT_DESTROYED (object))
- {
- gpointer data[2];
-
- data[0] = &signal;
- data[1] = object;
- emission_hooks_called++;
- g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data);
- emission_hooks_called--;
- }
-
gtk_object_unref (object);
}
@@ -1646,15 +1661,15 @@ static gboolean
gtk_emission_hook_marshaller (GHook *hook,
gpointer data_p)
{
- gpointer *data = data_p;
- GtkSignal *signal;
+ GtkEmissionHookData *data = data_p;
GtkEmissionHook func;
- signal = data[0];
func = hook->func;
- if (!GTK_OBJECT_DESTROYED (data[1]))
- return func (data[1], signal->signal_id, hook->data);
+ if (!GTK_OBJECT_DESTROYED (data->object))
+ return func (data->object, data->signal_id,
+ data->n_params, data->params,
+ hook->data);
else
return TRUE;
}
@@ -1677,11 +1692,7 @@ gtk_signal_connect_by_type (GtkObject *object,
g_return_val_if_fail (object != NULL, 0);
g_return_val_if_fail (object->klass != NULL, 0);
- /* A signal without a default marshaller can only take no_marshal
- handlers. */
-
signal = LOOKUP_SIGNAL_ID (signal_id);
- g_return_val_if_fail (signal->marshaller || no_marshal, 0);
/* Search through the signals for this object and make
* sure the one we are adding is valid. We need to perform
@@ -1744,36 +1755,38 @@ gtk_emission_new (void)
{
GtkEmission *emission;
- if (!gtk_emission_free_list)
+ if (!gtk_free_emissions)
{
- GtkEmissionAllocator *emission_block;
+ GtkEmission *emission_block;
guint i;
- emission_block = g_new0 (GtkEmissionAllocator, EMISSION_BLOCK_SIZE);
+ emission_block = g_new0 (GtkEmission, EMISSION_BLOCK_SIZE);
for (i = 1; i < EMISSION_BLOCK_SIZE; i++)
{
- (emission_block + i)->next = gtk_emission_free_list;
- gtk_emission_free_list = (emission_block + i);
+ (emission_block + i)->next = gtk_free_emissions;
+ gtk_free_emissions = (emission_block + i);
}
- emission = &emission_block->emission;
+ emission = emission_block;
}
else
{
- emission = &gtk_emission_free_list->emission;
- gtk_emission_free_list = gtk_emission_free_list->next;
+ emission = gtk_free_emissions;
+ gtk_free_emissions = emission->next;
}
emission->object = NULL;
emission->signal_id = 0;
+ emission->in_hook = 0;
+ emission->next = NULL;
return emission;
}
static void
-gtk_emission_add (GList **emissions,
- GtkObject *object,
- guint signal_id)
+gtk_emission_add (GtkEmission **emissions,
+ GtkObject *object,
+ guint signal_id)
{
GtkEmission *emission;
@@ -1783,58 +1796,51 @@ gtk_emission_add (GList **emissions,
emission = gtk_emission_new ();
emission->object = object;
emission->signal_id = signal_id;
-
- *emissions = g_list_prepend (*emissions, emission);
+
+ emission->next = *emissions;
+ *emissions = emission;
}
static void
-gtk_emission_remove (GList **emissions,
- GtkObject *object,
- guint signal_id)
+gtk_emission_remove (GtkEmission **emissions,
+ GtkObject *object,
+ guint signal_id)
{
- GList *tmp;
+ GtkEmission *emission, *last;
g_return_if_fail (emissions != NULL);
-
- tmp = *emissions;
- while (tmp)
+
+ last = NULL;
+ emission = *emissions;
+ while (emission)
{
- GtkEmissionAllocator *ea;
-
- ea = tmp->data;
-
- if ((ea->emission.object == object) &&
- (ea->emission.signal_id == signal_id))
+ if (emission->object == object && emission->signal_id == signal_id)
{
- *emissions = g_list_remove_link (*emissions, tmp);
- g_list_free (tmp);
+ if (last)
+ last->next = emission->next;
+ else
+ *emissions = emission->next;
- ea->next = gtk_emission_free_list;
- gtk_emission_free_list = ea;
+ emission->next = gtk_free_emissions;
+ gtk_free_emissions = emission;
break;
}
-
- tmp = tmp->next;
+
+ last = emission;
+ emission = last->next;
}
}
static gint
-gtk_emission_check (GList *emissions,
- GtkObject *object,
- guint signal_id)
+gtk_emission_check (GtkEmission *emission,
+ GtkObject *object,
+ guint signal_id)
{
- GtkEmission *emission;
- GList *tmp;
-
- tmp = emissions;
- while (tmp)
+ while (emission)
{
- emission = tmp->data;
- tmp = tmp->next;
-
- if ((emission->object == object) &&
- (emission->signal_id == signal_id))
- return TRUE;
+ if (emission->object == object && emission->signal_id == signal_id)
+ return 1 + emission->in_hook;
+ emission = emission->next;
}
return FALSE;
}