Table of Contents
Event signals differ in some ways from other signals. These differences are described in the Event signals section in the appendix. Here we will use keyboard events to show how events can be used in a program.
Whenever you press or release a key, an event is emitted. You can add an event controller and connect a signal handler to handle such events.
The event signal handler will receive arguments that depend on the type of event.
For key press events the arguments are (guint keyval
,
guint keycode
, Gdk::ModifierType state
).
As described in the appendix,
the key press event signal handler returns a bool value, to indicate that
the signal is fully handled (true
) or allow event propagation
(false
).
To determine which key was pressed or released, you read the value of
the keyval
argument and compare it with a constant in the
<gdk/gdkkeysyms.h>
header file. The states of
modifier keys (shift, ctrl, etc.) are available as bit-flags in
state
.
Here's a simple example:
bool MyClass::on_key_pressed(guint keyval, guint, Gdk::ModifierType state) { if (keyval == GDK_KEY_1 && (state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK | Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK) { handle_alt_press(); return true; } return false; } // in MyClass constructor auto controller = Gtk::EventControllerKey::create(); controller->signal_key_pressed().connect( sigc::mem_fun(*this, &MyClass::on_key_pressed), false); add_controller(controller);
In this example there are three keyboard shortcuts: Alt+1 selects the first radio button, Alt+2 selects the second one, and the Esc key hides (closes) the window.
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); private: // Signal handler: bool on_window_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state); Gtk::Box m_container; Gtk::CheckButton m_first; Gtk::CheckButton m_second; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h" ExampleWindow::ExampleWindow() { set_title("Keyboard Events"); m_container.set_margin(10); set_child(m_container); // Radio buttons: m_first.set_label("First"); m_second.set_label("Second"); m_second.set_group(m_first); m_first.set_active(); // Main Container: m_container.set_orientation(Gtk::Orientation::HORIZONTAL); m_container.append(m_first); m_container.append(m_second); // Events. auto controller = Gtk::EventControllerKey::create(); controller->signal_key_pressed().connect( sigc::mem_fun(*this, &ExampleWindow::on_window_key_pressed), false); add_controller(controller); } bool ExampleWindow::on_window_key_pressed(guint keyval, guint, Gdk::ModifierType state) { //Gdk::ModifierType::ALT_MASK -> the 'Alt' key(mask) //GDK_KEY_1 -> the '1' key //GDK_KEY_2 -> the '2' key //select the first radio button, when we press alt + 1 if((keyval == GDK_KEY_1) && (state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK | Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK) { m_first.set_active(); //returning true, cancels the propagation of the event return true; } else if((keyval == GDK_KEY_2) && (state & (Gdk::ModifierType::SHIFT_MASK | Gdk::ModifierType::CONTROL_MASK | Gdk::ModifierType::ALT_MASK)) == Gdk::ModifierType::ALT_MASK) { //and the second radio button, when we press alt + 2 m_second.set_active(); return true; } else if(keyval == GDK_KEY_Escape) { //close the window, when the 'esc' key is pressed set_visible(false); return true; } //the event has not been handled return false; } ExampleWindow::~ExampleWindow() { }
File: main.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }