Programming with Gtk2-Perl/Signals and Callbacks

Signals edit

The Gtk framework is event driven. This means it will remain idle in Gtk's main loop until an event occurs, at which point a signal will be emitted. If we have connected a callback to the signal, it will be executed before returning control back to the main loop.


In the last chapter we connected to the clicked signal of a button in order save some user input to a file.

$save_btn->signal_connect('clicked' => \&save_note, $entry);

sub save_note {
    my ($save_btn, $entry) = @_;
    my $text  = $entry->get_text;
    $entry->set_text('');
 
    open my $OUTFILE, '>>notes.txt'
        or die "could not open notes.txt for appending";
    flock $OUTFILE, 2;
    print $OUTFILE join '|', time, $text . "\n";
    close $OUTFILE;
}


Signal Connect edit

Here is the syntax of the signal_connect method which is provided in the Glib::Object base class - which all widgets inherit from. In addition to the name of the signal and callback, you may optionally pass in a scalar to be passed to the callback function when it is executed.

$widget->signal_connect($signal_name, \&callback, [$data])


Callbacks edit

Callbacks are subroutine references that will be executed when a signal is emitted. When you define your callback function you will get the emitting widget and optionally a $data value as arguments.

sub callback {
    my ($widget, $data) = @_;

    #...
}


Callbacks can also be anonymous subroutines. You can then use encapsulation to avoid passing in an argument. This approach is best used for short, simple callbacks. Take the example below.

$entry = Gtk2::Entry->new;

$button->signal_connect(clicked => sub {
    print $entry->get_text, "\n";
});

Events edit

There also exists a set of events that you can connect callbacks to. Use the same signal_connect method in exactly the same manner as when connecting to signals. These events reflect the those of the x event mechanism. Here is a complete listing.

  • event
  • button_press_event
  • button_release_event
  • scroll_event
  • motion_notify_event
  • delete_event
  • destroy_event
  • expose_event
  • key_press_event
  • key_release_event
  • enter_notify_event
  • leave_notify_event
  • configure_event
  • focus_in_event
  • focus_out_event
  • map_event
  • unmap_event
  • property_notify_event
  • selection_clear_event
  • selection_request_event
  • selection_notify_event
  • proximity_in_event
  • proximity_out_event
  • visibility_notify_event
  • client_event
  • no_expose_event
  • window_state_event


Callbacks edit

The callback function is slightly different for events.

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

The $event argument is an object that inherits from Gtk2::Gdk::Event. The actual package name will depend on the which event occurred. You can call the 'type' method on the $event to retrieve the type of event that occurred. You may also be able to call other methods on the $event that may be of interest, but that will vary depending on the type of event.


Event Types edit

Here is a list of possible values that could be returned from the type method.

  • nothing
  • delete
  • destroy
  • expose
  • motion-notify
  • button-press
  • 2button-press
  • 3button-press
  • button-release
  • key-press
  • key-release
  • enter-notify
  • leave-notify
  • focus-change
  • configure
  • map
  • unmap
  • property-notify
  • selection-clear
  • selection-request
  • selection-notify
  • proximity-in
  • proximity-out
  • drag-enter
  • drag-leave
  • drag-motion
  • drag-status
  • drop-start
  • drop-finished
  • client-event
  • visibility-notify
  • no-expose
  • scroll
  • window-state
  • setting


Return Values edit

The value returned from your callback function determines whether events should be propagated further. Returning a TRUE value will stop the propagation of events, while a FALSE value will continue one with normal event handling.


Disconnecting and Blocking edit

By storing the Integer value returned from the 'signal_connect' method, we can disconnect the callback later.

$id = $widget->signal_connect($signal => \&callback, $data );

$widget->signal_handler_disconnect($id);


You can also temporarily disable a callback from firing.

$widget->signal_handler_block($id);

$widget->signal_handlers_block_by_func(\&callback, $data);

$widget->signal_handler_unblock($id);

$widget->signal_handlers_unblock_by_func(\&callback, $data);