Table of Contents
X events differ in some ways from other signals. These differences are described in the X Event signals section in the appendix. Here we will use keyboard events to show how X events can be used in a program.
Whenever you press or release a key, an event is emitted. You can connect a signal handler to handle such events.
The event signal handler will
receive an argument that depends on the type of event. For keyboard
events it's a GdkEventKey*. As discribed in the
appendix, the 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
GdkEventKey::keyval
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
GdkEventKey::state
.
Here's a simple example:
bool on_key_press_or_release_event(GdkEventKey* event) { if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_1 && (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_MOD1_MASK) { handle_alt_1_press(); // GDK_MOD1_MASK is normally the Alt key return true; } return false; } Gtk::Entry m_entry; // in a class definition // in the class constructor m_entry.signal_key_press_event().connect( sigc::ptr_fun(&on_key_press_or_release_event) ); m_entry.signal_key_release_event().connect( sigc::ptr_fun(&on_key_press_or_release_event) );
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. The default event signal handler is overridden, as described in the Overriding default signal handlers section in the appendix.
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 hide(); 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); }