Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Gtk+/Gnome Application Development
Prev Home Next

Using Existing Signals

Figure 4 shows the wide array of functions available for manipulating signals. You should already be familiar with the most fundamental signal operation: connecting a signal handler to be invoked when the signal is emitted, like this:


  gtk_signal_connect(GTK_OBJECT(window),
                     "delete_event",
                     GTK_SIGNAL_FUNC(delete_event_cb),
                     NULL);

  gtk_signal_connect(GTK_OBJECT(button),
                     "clicked",
                     GTK_SIGNAL_FUNC(button_click_cb),
                     label);


You may not be aware that gtk_signal_connect() returns a "handler ID" which can be used to refer to the connection it creates. Using the handler ID, you can unregister the callback with gtk_signal_disconnect(). You can also temporarily "block" the callback by calling gtk_signal_handler_block(). This increments a "block count"; the callback will not be invoked until the block count returns to 0. gtk_signal_handler_unblock() decrements the block count. Both gtk_signal_disconnect() and gtk_signal_handler_unblock() have variants that search for the handler ID given a callback function or user data pointer; these are possibly more convenient, with some loss of efficiency.

It can be useful to block signal handlers if you'll be changing some aspect of an object yourself, and thus don't need to run the callbacks you use to respond to user actions. For example, you normally change some boolean variable if the user clicks a toggle button, in a callback to the "toggled" signal. If you update the toggle button programmatically because the flag was changed via some mechanism other than the button, "toggled" will still be emitted; but you want to block your callback, since the flag is already correct.

gtk_signal_connect() is not the only way to connect to a signal. You can also use gtk_signal_connect_object(); this simply swaps the signal-emitting object pointer and the user data pointer in the arguments passed to the callback. Normally, the object comes first, then any arguments unique to the signal, and finally the user data pointer; with gtk_signal_connect_object(), the object is last and user data is first. This function is useful when you want to use a pre-existing function as a callback without writing a wrapper to move its arguments. For example:


  gtk_signal_connect_object(GTK_OBJECT(button),
                            "clicked",
                            GTK_SIGNAL_FUNC(gtk_widget_destroy),
                            GTK_OBJECT(dialog));

Because the user data and the button are swapped, the first argument to gtk_widget_destroy() will be the dialog rather than the button, closing the dialog. When using gtk_signal_connect_object(), your callback data must be a GtkObject to avoid confusing marshallers that expect an object as their first argument.

gtk_signal_connect_after() asks GTK+ to run the callback after the object's default signal handler, rather than before it. This only works with certain signals, those with the GTK_RUN_LAST flag set; the section called Adding a New Signal explains this flag.

gtk_signal_connect_object_after() combines the effects of gtk_signal_connect_object() and gtk_signal_connect_after().

gtk_signal_connect_full() gives you complete control over the connection and is mostly useful in language bindings. The object_signal and after arguments can be TRUE or FALSE, toggling argument order and time of callback invocation. The functions we just mentioned also let you change this, so gtk_signal_connect_full() adds little. Its unique features are the ability to specify a callback marshaller, and the ability to specify a GtkDestroyNotify function. Notice that gtk_signal_connect_full() does not expect the same kind of marshaller described in the section called Adding a New Signal; it expects a more general marshaller appropriate for marshalling functions written in languages other than C. If you give a non-NULLGtkDestroyNotify function, it will be invoked on the user data pointer when this handler is disconnected or the GtkObject is destroyed. Here is the proper signature for the function:


  typedef void (*GtkDestroyNotify)   (gpointer   data);

Conveniently, you can use g_free() or gtk_object_destroy() as a GtkDestroyNotify. Of course, if these aren't appropriate you can write a custom function.

gtk_signal_connect_while_alive() is a variant on gtk_signal_connect(); its additional argument is an object to monitor. When the monitored object is destroyed (emits the "destroy" signal), the handler will be disconnected. That is, handlers connected with this function are automatically disconnected when a specified object no longer exists.

There's rarely a need to do so, but you can look up a signal's ID number given the signal name and the object type that emits it. This function is gtk_signal_lookup(). Note that names are not globally unique, but they are unique with respect to a particular object type. On the other hand, signal IDs are globally unique.

During the emission of a signal (that is, during the process of invoking its handlers), you can call gtk_signal_emit_stop() (or its _by_name() variant) to halt the emission. These functions are only useful from within signal handlers, because they must be called during the emission process or they won't have anything to stop. They do not take effect immediately; instead, they set a variable that GTK+ checks at key points during emission. the section called What Happens When A Signal Is Emitted describes this in detail.

Emission hooks can be used to monitor all emissions of a given signal (regardless of the object instance doing the emitting). Emission hooks have the following signature:


typedef gboolean (*GtkEmissionHook) (GtkObject      *object,
                                     guint           signal_id,
                                     guint           n_params,
                                     GtkArg         *params,
                                     gpointer        data);

They are passed the same parameters GTK+ would normally pass to callback marshallers (see the section called Adding a New Signal). You can connect an emission hook with a destroy notify function to be invoked on the user data pointer when the hook is removed. When you add an emission hook, an integer identify is returned. You can remove emission hooks with this ID number.

Emission hooks are rarely useful, but sometimes they are the only way to do something. For example, Gnome optionally plays sound effects when certain signals are emitted (such as button clicks).

Finally, you can ask everything you ever wanted to know about a signal using gtk_signal_query(). This function is intended for GUI builders and language bindings to use; it is probably not useful in application code. It returns a GtkSignalQuery structure filled with information about the signal. The return value should be freed with g_free() but not modified in any way (it contains pointers to internal data which isn't copied). Here is the definition of GtkSignalQuery:


typedef struct _GtkSignalQuery GtkSignalQuery;

struct  _GtkSignalQuery
{
  GtkType          object_type;
  guint            signal_id;
  const gchar     *signal_name;
  guint            is_user_signal : 1;
  GtkSignalRunType signal_flags;
  GtkType          return_val;
  guint            nparams;
  const GtkType   *params;
};
#include <gtk/gtksignal.h>

guint gtk_signal_lookup(const gchar* name, GtkType object_type);

gchar* gtk_signal_name(guint signal_id);

void gtk_signal_emit_stop(GtkObject* object, guint signal_id);

void gtk_signal_emit_stop_by_name(GtkObject* object, const gchar* name);

guint gtk_signal_connect(GtkObject* object, const gchar* name, GtkSignalFunc func, gpointer func_data);

guint gtk_signal_connect_after(GtkObject* object, const gchar* name, GtkSignalFunc func, gpointer func_data);

guint gtk_signal_connect_object(GtkObject* object, const gchar* name, GtkSignalFunc func, GtkObject* slot_object);

guint gtk_signal_connect_object_after(GtkObject* object, const gchar* name, GtkSignalFunc func, GtkObject* slot_object);

guint gtk_signal_connect_full(GtkObject* object, const gchar* name, GtkSignalFunc func, GtkCallbackMarshal marshal, gpointer data, GtkDestroyNotify destroy_func, gint object_signal, gint after);

void gtk_signal_connect_object_while_alive(GtkObject* object, const gchar* signal, GtkSignalFunc func, GtkObject* alive_object);

void gtk_signal_connect_while_alive(GtkObject* object, const gchar* signal, GtkSignalFunc func, gpointer func_data, GtkObject * alive_object);

void gtk_signal_disconnect(GtkObject* object, guint handler_id);

void gtk_signal_disconnect_by_func(GtkObject* object, GtkSignalFunc func, gpointer func_data);

void gtk_signal_disconnect_by_data(GtkObject * object, gpointer func_data);

void gtk_signal_handler_block(GtkObject* object, guint handler_id);

void gtk_signal_handler_block_by_func(GtkObject* object, GtkSignalFunc func, gpointer func_data);

void gtk_signal_handler_block_by_data(GtkObject* object, gpointer func_data);

void gtk_signal_handler_unblock(GtkObject* object, guint handler_id);

void gtk_signal_handler_unblock_by_func(GtkObject* object, GtkSignalFunc func, gpointer func_data);

void gtk_signal_handler_unblock_by_data(GtkObject* object, gpointer func_data);

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);

GtkSignalQuery* gtk_signal_query(guint signal_id);

Figure 4. Using Signals

Gtk+/Gnome Application Development
Prev Home Next

 
 
  Published under free license. Design by Interspire