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.
To receive the keyboard events, you must first call the
Gtk::Widget::add_events()
function with a bit
mask of the events you're interested in. 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) ); m_entry.add_events(Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
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 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); private: //Override default signal handler: bool on_key_press_event(GdkEventKey* event) override; Gtk::Grid m_container; Gtk::RadioButton m_first; Gtk::RadioButton m_second; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc
(For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); ExampleWindow window; //Shows the window and returns when it is closed. return app->run(window); }
File: examplewindow.cc
(For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h" ExampleWindow::ExampleWindow() { set_title("Keyboard Events"); set_border_width(10); add(m_container); // Radio buttons: m_first.set_label("First"); m_second.set_label("Second"); m_second.join_group(m_first); m_first.set_active(); // Main Container: m_container.add(m_first); m_container.add(m_second); // Events. // We override the default event signal handler. add_events(Gdk::KEY_PRESS_MASK); show_all_children(); } bool ExampleWindow::on_key_press_event(GdkEventKey* key_event) { //GDK_MOD1_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((key_event->keyval == GDK_KEY_1) && (key_event->state &(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_MOD1_MASK) { m_first.set_active(); //returning true, cancels the propagation of the event return true; } else if((key_event->keyval == GDK_KEY_2) && (key_event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_MOD1_MASK) { //and the second radio button, when we press alt + 2 m_second.set_active(); return true; } else if(key_event->keyval == GDK_KEY_Escape) { //close the window, when the 'esc' key is pressed hide(); return true; } //if the event has not been handled, call the base class return Gtk::Window::on_key_press_event(key_event); } ExampleWindow::~ExampleWindow() { }