Event signals

Event signals are emitted as a result of some user input, for instance a key press or a mouse motion. Usually you don't handle these events directly. Instead, you use a subclass of Gtk::EventController, such as Gtk::EventControllerKey or Gtk::GestureClick. Event controllers can be added to a widget with Gtk::Widget::add_controller().

You might occasionally find it useful to handle events when there's something you can't accomplish with normal signals. Gtk::Button, for example, does not send mouse-pointer coordinates with its clicked signal, but you could handle Gtk::GestureClick::signal_pressed() if you needed this information. Gtk::EventControllerKey::signal_key_pressed() is often used to handle key-presses.

Some event controller signals behave slightly differently. The value returned from the signal handler indicates whether it has fully "handled" the event. If the value is false then gtkmm will pass the event on to the next signal handler. If the value is true then no other signal handlers will need to be called.

Handling an event doesn't affect the Widget's other signals. If you handle Gtk::GestureClick::signal_pressed() for Gtk::Button, you'll still be able to get the clicked signal. They are emitted at (nearly) the same time.

Here's a simple example:

void on_button_press(int n_press, double x, double y);
Gtk::Button button("label");
auto controller = Gtk::GestureClick::create();
controller->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
controller->signal_pressed().connect(sigc::ptr_fun(&on_button_press));
button.add_controller(controller);

When the mouse is over the button and a mouse button is pressed, on_button_press() will be called.

The call to set_propagation_phase() is necessary in this case because the GtkButton C class adds an event controller, handling button clicks in the capture phase. GtkButton claims the event, meaning that the event is not propagated in the bubble phase, where event controllers handle events by default.

Signal Handler sequence

By default, signal handlers that return void are called after any previously-connected signal handlers. However, this can be a problem with event signals that can stop event propagation by returning true. For instance, the existing signal handlers, or the default signal handler, might return true to stop other signal handlers from being called. To specify that your signal handler should be called before the other signal handlers, you can specify false for the after parameter. This connect() parameter is optional, if the signal handler returns void. For instance,

key_controller->signal_key_pressed().connect(sigc::ptr_fun(&on_mywindow_key_pressed), false);

The event is propagated between widgets in 3 phases.

  1. Capture phase - runs from the toplevel down to the event widget.
  2. Target phase - runs only on the event widget.
  3. Bubble phase - runs from the event widget up to the toplevel.

The Input Handling chapter in the GTK documentation describes user input handling in more detail.