Chapter 5. Signals and Events

Table of Contents
5.1. Theory of Signals and Callbacks
5.2. Events
5.3. Callback Return Value
5.4. Emitting Signals
5.5. Removing Callbacks
5.6. Temporarily Disabling Callbacks
5.7. Connecting and Disconnecting Signal Handlers
5.8. Signal Emissions and Propagation

5.1. Theory of Signals and Callbacks

GTK is an event driven toolkit, which means it will sleep in main Gtk until an event occurs and control is passed to the appropriate function.

This passing of control is done using the idea of "signals". These signals are not the same as the Unix system signals, and are not implemented using them, although the terminology is almost identical. When something like the press of a mouse button occurs, the appropriate signal will be "emitted" by the widget that was pressed. This is how GTK does most of its useful work. There are signals that all widgets inherit, such as 'destroy', and there are signals that are widget specific, such as the 'toggled' signal on a toggle button.

To make a widget perform an action, we set up a signal handler to catch these signals and call the appropriate function. This is done by using a function like one of these:

$object->signal_connect( "signal_name", \&signal_func );

$object->signal_connect( signal_name => \&signal_func );

$object->signal_connect( "signal_name", \&signal_func, $optional_data ... );

$object->signal_connect( "signal_name", \&signal_func, @optional_data );

To Perl, the first two forms are identical, and the last two forms are also identical because Perl sends all arguments as a single list of scalars. Of course, you can send as many items in the list as you want.

The variable to the left of the signal_connect() is the widget which will be emitting the signal. The first argument is a string representing the signal that you wish to register the callback with. The second argument is the reference to the subroutine you want called. This subroutine is called a callback. If you want to pass any data to the callback, you specify that by putting it at the end of the argument list. Everything after the second argument is passed as a list, so you are allowed to pass as many arguments to the callback as you want.

If you do not understand Perl references, just remember that the subroutine name is preceded by "\&" and you cannot put parenthesis after the subroutine name.

For callbacks that are associated with only one signal and are just a few lines, it is common to see something like this:

$object->signal_connect( "signal_name", sub { do_something; } );

A callback function is usually defined like this:

sub callback_func
  {
    my ( $widget, @data ) = @_;
    ...
  }

The first argument sent to a callback will always be the widget that emitted the signal, and the rest of the arguments are optional data sent by the signal_connect() function. Remember that Perl does not force you to declare or use the arguments sent to a subroutine, but it is good programming practice to do so.

Note that the above form for a signal callback function is only a general guide, as some widget specific signals generate different calling parameters. For example, the CList 'select_row' signal provides both row and column parameters.

5.2. Events

In adddition to the signal mechanism described above, there is a set of events that reflect the X event mechanism. Callback may also be attached to these events. These events are:

In order to connect a callback function to one of these events, you use the function signal_connect(), just as you would connect to a signal, only using one of the above event names instead of a signal name. The last argument passed in to the callback is an event structure, so at the beginning of your callback, you may wish to say:

my ( $widget, $data, $event ) = @_;

or, if you want to pass in array data:

my ( $widget, @data ) = @_;
my $event = pop( @data );

Some of the more common fields in the event structure are button, keyval, and type.

The button field contains a number with the button pushed (typically 1, 2, or 3). The keyval field contains the key that was pressed (if any). And the type field contains one of the following strings:

This makes it really easy to determine the cause of an event. For example, was it caused by an button press? If so, which one? Look at the following example:

sub some_event
  {
    my ( $widget, @data ) = @_;
    my $event = pop( @data );

    if ( ( defined( $event->{'type'} ) ) and
         ( $event->{'type'} eq 'button_press' ) )
      {
        if ( $event->{'button'} == 3 )
          {
            # right click
          }
        else
          {
            # non-right click
          }
      }
  }

Keep in mind that the above code only works if the callback is attached to one of the events mentioned above. Signals do not send an event structure, so unless you know exactly how many arguments are being sent, and you don't need the information in the event structure, I advise against connecting a signal and an event with the same callback.

5.3. Callback Return Value

The return type of the signal_connect() function is a tag that identifies your callback function. You may have as many callbacks per signal and per object as you need, and each will be executed in turn, in the order they were attached.

5.4. Emitting Signals

If you want to emit a specific signal, you can do so by calling on of the following functions:

$widget->signal_emit( $id );

$widget->signal_emit_by_name( $signal_name );

The argument to the first form is the id tag that is returned by signal_connect(). The argument in the second form is the string identifying the name of the signal.

Also, many widgets have functions that will emit the most common signals. For example, the destroy() function will cause the 'destroy' signal to be emitted, and the activate() function will cause the 'activate' signal to be emitted. These functions are preferred over calling signal_emit_by_name(), which is intended to be used by widget implementors who wish to synthesize events.

5.5. Removing Callbacks

The id tag that is returned by the signal_connect() also allows you to remove a callback from the list by using signal_disconnect() like this:

$widget->signal_disconnect( $id );

If you want to remove all the signal handers from a widget, you can call this function:

$widget->signal_handlers_destroy();

This call is fairly self explanatory. It simply removes all the current signal handlers from the object passed in as the first argument. This is done automatically when a widget is destroyed, so you won't usually care about this function.

5.6. Temporarily Disabling Callbacks

You can also temporarily disable signal handlers with the following group of functions:

$widget->signal_handler_block( $callback_id );
$widget->signal_handler_block_by_func( \&callback, $data );
$widget->signal_handler_block_by_data( $data );

$widget->signal_handler_unblock( $callback_id );
$widget->signal_handler_unblock_by_func( \&callback, $data );
$widget->signal_handler_unblock_by_data( $data );

5.7. Connecting and Disconnecting Signal Handlers

Here is an overview of the fuctions used to connect and disconnect signal handlers, as well as each form of signal_connect() that is available. These are provided for your information only. If you want more detail, see the GTK+ documentation.

$id = $object->signal_connect( $signal_name,
                               \&function,
                               @optional_data );

$id = $object->signal_connect_after( $signal_name,
                                     \&function,
                                     @optional_data );

$id = $object->signal_connect_object( $signal_name,
                                      \&function,
                                      $slot_object );

$id = $object->signal_connect_object_after( $signal_name,
                                            \&function,
                                            $slot_object );

# I'm unsure of this one
$id = $object->signal_connect_full( $name,
                                    \&function,
                                    $callback_marshal,
                                    @optional_data,
                                    \&destroy_function,
                                    $object_signal,
                                    $after );

# I'm not sure of this one either
$id = $object->signal_connect_interp( $name,
                                      \&function,
                                      @optional_data,
                                      \&destroy_function,
                                      $after );

$id = $object->signal_connect_object_while_alive( $signal,
                                                  \&function,
                                                  $alive_object );

$id = $object->signal_connect_while_alive( $signal,
                                           \&function,
                                           @optional_data,
                                           $alive_object );

$object->signal_disconnect( $id );

$object->signal_disconnect_by_func( \&function,
                                    @optional_data );

5.8. Signal Emissions and Propagation

Signal emission is the process whereby GTK runs all handlers for a specific object and signal.

First, note that the return value from a signal emission is the return value of the last handler executed. Since event signals are all of type 'last', this will be the default (GTK supplied) handler, unless you connect with signal_connect_after().

The way an event (say "button_press_event") is handled, is:

Some consequences of the above are: