added an event watcher for enter/leave based on signal emission hooks.

Mon Nov 30 06:20:36 1998  Tim Janik  <timj@gtk.org>

        * gtk/testgtk.c: added an event watcher for enter/leave based on
        signal emission hooks.

        * gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
        GTK_RUN_NO_HOOKS signal.

        * gtk/gtksignal.h:
        * gtk/gtksignal.c: implemented emission hooks, new hooks can be added
        to a signal with gtk_signal_add_emission_hook or
        gtk_signal_add_emission_hook_full, and can be removed again with
        gtk_signal_remove_emission_hook.

        * gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
        an appropriate mask for signal runtypes for a long time now.
        added GTK_RUN_NO_HOOKS value, which is used to flag signals
        that do not allow the running of signal hooks.
This commit is contained in:
Tim Janik 1998-11-30 07:09:36 +00:00 committed by Tim Janik
parent 140c26afbc
commit 2c0fc39e62
13 changed files with 459 additions and 20 deletions

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -1,3 +1,22 @@
Mon Nov 30 06:20:36 1998 Tim Janik <timj@gtk.org>
* gtk/testgtk.c: added an event watcher for enter/leave based on
signal emission hooks.
* gtk/gtkobject.c (gtk_object_class_init): made GtkObject::destroy a
GTK_RUN_NO_HOOKS signal.
* gtk/gtksignal.h:
* gtk/gtksignal.c: implemented emission hooks, new hooks can be added
to a signal with gtk_signal_add_emission_hook or
gtk_signal_add_emission_hook_full, and can be removed again with
gtk_signal_remove_emission_hook.
* gtk/gtkenums.h: remove GTK_RUN_MASK, since it doesn't represent
an appropriate mask for signal runtypes for a long time now.
added GTK_RUN_NO_HOOKS value, which is used to flag signals
that do not allow the running of signal hooks.
1998-11-26 Michael Krause <m.krause@tu-harburg.de>
* gtk/gtknotebook.c (gtk_notebook_switch_page): made 'page_num'

View File

@ -194,12 +194,12 @@ typedef enum
/* signal run types */
typedef enum /*< flags >*/
{
GTK_RUN_FIRST = 0x1,
GTK_RUN_LAST = 0x2,
GTK_RUN_BOTH = 0x3,
GTK_RUN_MASK = 0xF,
GTK_RUN_FIRST = 0x01,
GTK_RUN_LAST = 0x02,
GTK_RUN_BOTH = (GTK_RUN_FIRST | GTK_RUN_LAST),
GTK_RUN_NO_RECURSE = 0x10,
GTK_RUN_ACTION = 0x20
GTK_RUN_ACTION = 0x20,
GTK_RUN_NO_HOOKS = 0x30
} GtkSignalRunType;
/* scrolling types */

View File

@ -166,7 +166,7 @@ gtk_object_class_init (GtkObjectClass *class)
object_signals[DESTROY] =
gtk_signal_new ("destroy",
GTK_RUN_LAST,
GTK_RUN_LAST | GTK_RUN_NO_HOOKS,
class->type,
GTK_SIGNAL_OFFSET (GtkObjectClass, destroy),
gtk_marshal_NONE__NONE,

View File

@ -36,7 +36,7 @@ enum
EMISSION_DONE
};
#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_MASK)
#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_BOTH)
typedef struct _GtkSignal GtkSignal;
@ -55,11 +55,12 @@ struct _GtkSignal
GtkType object_type;
gchar *name;
guint function_offset;
GtkSignalRunType signal_flags;
GtkSignalMarshaller marshaller;
GtkType return_val;
GtkSignalRunType signal_flags : 16;
guint nparams : 16;
GtkType *params;
guint nparams;
GHookList *hook_list;
};
struct _GtkSignalHash
@ -145,7 +146,9 @@ static gint gtk_handlers_run (GtkHandler *handlers,
GtkObject *object,
GtkArg *params,
gint after);
static gboolean gtk_signal_collect_params (GtkArg *params,
static gboolean gtk_emission_hook_marshaller (GHook *hook,
gpointer data);
static gboolean gtk_signal_collect_params (GtkArg *params,
guint nparams,
GtkType *param_types,
GtkType return_type,
@ -303,10 +306,11 @@ gtk_signal_newv (const gchar *r_name,
signal->object_type = object_type;
signal->name = name;
signal->function_offset = function_offset;
signal->signal_flags = signal_flags;
signal->marshaller = marshaller;
signal->return_val = return_val;
signal->signal_flags = signal_flags;
signal->nparams = nparams;
signal->hook_list = NULL;
if (nparams > 0)
{
@ -1419,7 +1423,17 @@ gtk_signal_real_emit (GtkObject *object,
}
}
}
/* do *not* reorder this call! */
if (signal.hook_list)
{
gpointer data[2];
data[0] = &signal;
data[1] = object;
g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data);
}
emission_done:
gtk_emission_remove (&current_emissions, object, signal_id);
@ -1517,6 +1531,90 @@ gtk_signal_handler_pending_by_func (GtkObject *object,
return handler_id;
}
guint
gtk_signal_add_emission_hook (guint signal_id,
GtkEmissionHook hook_func,
gpointer data)
{
return gtk_signal_add_emission_hook_full (signal_id, hook_func, data, NULL);
}
guint
gtk_signal_add_emission_hook_full (guint signal_id,
GtkEmissionHook hook_func,
gpointer data,
GDestroyNotify destroy)
{
static guint seq_hook_id = 1;
GtkSignal *signal;
GHook *hook;
g_return_val_if_fail (signal_id > 0, 0);
g_return_val_if_fail (hook_func != NULL, 0);
signal = LOOKUP_SIGNAL_ID (signal_id);
g_return_val_if_fail (signal != NULL, 0);
if (signal->signal_flags & GTK_RUN_NO_HOOKS)
{
g_warning ("gtk_signal_add_emission_hook_full(): signal \"%s\" does not support emission hooks",
signal->name);
return 0;
}
if (!signal->hook_list)
{
signal->hook_list = g_new (GHookList, 1);
g_hook_list_init (signal->hook_list, sizeof (GHook));
}
hook = g_hook_alloc (signal->hook_list);
hook->data = data;
hook->func = hook_func;
hook->destroy = destroy;
signal->hook_list->seq_id = seq_hook_id;
g_hook_prepend (signal->hook_list, hook);
seq_hook_id = signal->hook_list->seq_id;
return hook->hook_id;
}
void
gtk_signal_remove_emission_hook (guint signal_id,
guint hook_id)
{
GtkSignal *signal;
g_return_if_fail (signal_id > 0);
g_return_if_fail (hook_id > 0);
signal = LOOKUP_SIGNAL_ID (signal_id);
g_return_if_fail (signal != NULL);
if (!signal->hook_list || !g_hook_destroy (signal->hook_list, hook_id))
g_warning ("gtk_signal_remove_emission_hook(): could not find hook (%u)", hook_id);
if (signal->hook_list && !signal->hook_list->hooks)
{
g_hook_list_clear (signal->hook_list);
g_free (signal->hook_list);
signal->hook_list = NULL;
}
}
static gboolean
gtk_emission_hook_marshaller (GHook *hook,
gpointer data_p)
{
gpointer *data = data_p;
GtkSignal *signal;
GtkEmissionHook func;
signal = data[0];
func = hook->func;
return func (data[1], signal->signal_id, hook->data);
}
static guint
gtk_signal_connect_by_type (GtkObject *object,
guint signal_id,

View File

@ -33,13 +33,17 @@ extern "C" {
#define GTK_SIGNAL_OFFSET(struct, field) (GTK_STRUCT_OFFSET (struct, field))
typedef void (*GtkSignalMarshal) (GtkObject *object,
typedef void (*GtkSignalMarshal) (GtkObject *object,
gpointer data,
guint nparams,
GtkArg *args,
GtkType *arg_types,
GtkType return_type);
typedef void (*GtkSignalDestroy) (gpointer data);
typedef void (*GtkSignalDestroy) (gpointer data);
typedef gboolean (*GtkEmissionHook) (GtkObject *object,
guint signal_id,
gpointer data);
typedef struct _GtkSignalQuery GtkSignalQuery;
@ -166,6 +170,16 @@ guint gtk_signal_handler_pending_by_func (GtkObject *object,
GtkSignalFunc func,
gpointer data);
void gtk_signal_handlers_destroy (GtkObject *object);
guint gtk_signal_add_emission_hook (guint signal_id,
GtkEmissionHook hook_func,
gpointer data);
guint gtk_signal_add_emission_hook_full (guint signal_id,
GtkEmissionHook hook_func,
gpointer data,
GDestroyNotify destroy);
void gtk_signal_remove_emission_hook (guint signal_id,
guint hook_id);
void gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
GtkSignalDestroy destroy_func);

View File

@ -5261,7 +5261,7 @@ create_font_selection (void)
static GtkWidget *dialog_window = NULL;
void
static void
label_toggle (GtkWidget *widget,
GtkWidget **label)
{
@ -5281,7 +5281,7 @@ label_toggle (GtkWidget *widget,
gtk_widget_destroy (*label);
}
void
static void
create_dialog (void)
{
static GtkWidget *label;
@ -5324,11 +5324,107 @@ create_dialog (void)
gtk_widget_destroy (dialog_window);
}
/* Event Watcher
*/
static gboolean event_watcher_enter_id = 0;
static gboolean event_watcher_leave_id = 0;
static gboolean
event_watcher (GtkObject *object,
guint signal_id,
gpointer data)
{
g_print ("Watch: \"%s\" emitted for %s\n",
gtk_signal_name (signal_id),
gtk_type_name (GTK_OBJECT_TYPE (object)));
return TRUE;
}
static void
event_watcher_down (void)
{
if (event_watcher_enter_id)
{
guint signal_id;
signal_id = gtk_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
gtk_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
event_watcher_enter_id = 0;
signal_id = gtk_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
gtk_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
event_watcher_leave_id = 0;
}
}
static void
event_watcher_toggle (void)
{
if (event_watcher_enter_id)
event_watcher_down ();
else
{
guint signal_id;
signal_id = gtk_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
event_watcher_enter_id = gtk_signal_add_emission_hook (signal_id, event_watcher, NULL);
signal_id = gtk_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
event_watcher_leave_id = gtk_signal_add_emission_hook (signal_id, event_watcher, NULL);
}
}
static void
create_event_watcher (void)
{
GtkWidget *button;
if (!dialog_window)
{
dialog_window = gtk_dialog_new ();
gtk_signal_connect (GTK_OBJECT (dialog_window), "destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
&dialog_window);
gtk_signal_connect (GTK_OBJECT (dialog_window),
"destroy",
GTK_SIGNAL_FUNC (event_watcher_down),
NULL);
gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
gtk_widget_set_usize (dialog_window, 200, 110);
button = gtk_toggle_button_new_with_label ("Activate Watch");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (event_watcher_toggle),
NULL);
gtk_container_set_border_width (GTK_CONTAINER (button), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox),
button, TRUE, TRUE, 0);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Close");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
dialog_window);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
}
if (!GTK_WIDGET_VISIBLE (dialog_window))
gtk_widget_show (dialog_window);
else
gtk_widget_destroy (dialog_window);
}
/*
* GtkRange
*/
void
static void
create_range_controls (void)
{
static GtkWidget *window = NULL;
@ -8067,6 +8163,7 @@ create_main_window (void)
{ "dialog", create_dialog },
/* { "dnd", create_dnd }, */
{ "entry", create_entry },
{ "event watcher", create_event_watcher },
{ "file selection", create_file_selection },
{ "font selection", create_font_selection },
{ "gamma curve", create_gamma_curve },

View File

@ -5261,7 +5261,7 @@ create_font_selection (void)
static GtkWidget *dialog_window = NULL;
void
static void
label_toggle (GtkWidget *widget,
GtkWidget **label)
{
@ -5281,7 +5281,7 @@ label_toggle (GtkWidget *widget,
gtk_widget_destroy (*label);
}
void
static void
create_dialog (void)
{
static GtkWidget *label;
@ -5324,11 +5324,107 @@ create_dialog (void)
gtk_widget_destroy (dialog_window);
}
/* Event Watcher
*/
static gboolean event_watcher_enter_id = 0;
static gboolean event_watcher_leave_id = 0;
static gboolean
event_watcher (GtkObject *object,
guint signal_id,
gpointer data)
{
g_print ("Watch: \"%s\" emitted for %s\n",
gtk_signal_name (signal_id),
gtk_type_name (GTK_OBJECT_TYPE (object)));
return TRUE;
}
static void
event_watcher_down (void)
{
if (event_watcher_enter_id)
{
guint signal_id;
signal_id = gtk_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
gtk_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
event_watcher_enter_id = 0;
signal_id = gtk_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
gtk_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
event_watcher_leave_id = 0;
}
}
static void
event_watcher_toggle (void)
{
if (event_watcher_enter_id)
event_watcher_down ();
else
{
guint signal_id;
signal_id = gtk_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
event_watcher_enter_id = gtk_signal_add_emission_hook (signal_id, event_watcher, NULL);
signal_id = gtk_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
event_watcher_leave_id = gtk_signal_add_emission_hook (signal_id, event_watcher, NULL);
}
}
static void
create_event_watcher (void)
{
GtkWidget *button;
if (!dialog_window)
{
dialog_window = gtk_dialog_new ();
gtk_signal_connect (GTK_OBJECT (dialog_window), "destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
&dialog_window);
gtk_signal_connect (GTK_OBJECT (dialog_window),
"destroy",
GTK_SIGNAL_FUNC (event_watcher_down),
NULL);
gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
gtk_widget_set_usize (dialog_window, 200, 110);
button = gtk_toggle_button_new_with_label ("Activate Watch");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (event_watcher_toggle),
NULL);
gtk_container_set_border_width (GTK_CONTAINER (button), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox),
button, TRUE, TRUE, 0);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Close");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
dialog_window);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
}
if (!GTK_WIDGET_VISIBLE (dialog_window))
gtk_widget_show (dialog_window);
else
gtk_widget_destroy (dialog_window);
}
/*
* GtkRange
*/
void
static void
create_range_controls (void)
{
static GtkWidget *window = NULL;
@ -8067,6 +8163,7 @@ create_main_window (void)
{ "dialog", create_dialog },
/* { "dnd", create_dnd }, */
{ "entry", create_entry },
{ "event watcher", create_event_watcher },
{ "file selection", create_file_selection },
{ "font selection", create_font_selection },
{ "gamma curve", create_gamma_curve },