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.
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:
bool on_key_press_event(GdkEventKey *event);
Gtk::Grid m_container;
Gtk::RadioButton m_first;
Gtk::RadioButton m_second;
};
#endif //GTKMM_EXAMPLEWINDOW_H
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");
Gtk::RadioButton::Group group = m_first.get_group();
m_second.set_group(group);
m_first.set_active();
// Main Container:
m_container.add(m_first);
m_container.add(m_second);
// Events
add_events(Gdk::KEY_PRESS_MASK);
signal_key_press_event().connect(sigc::mem_fun(*this,
&ExampleWindow::on_key_press_event));
show_all_children();
}
bool ExampleWindow::on_key_press_event(GdkEventKey *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((event->keyval == GDK_KEY_1) &&
(event->state &(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_MOD1_MASK)
{
m_first.set_active();
}
else if((event->keyval == GDK_KEY_2) &&
(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();
}
else if(event->keyval == GDK_KEY_Escape)
{
//close the window, when the 'esc' key is pressed
hide();
}
//returning true, cancels the propagation of the event
return true;
}
ExampleWindow::~ExampleWindow()
{
}
File: main.cc (For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h"
#include <gtkmm/main.h>
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
//Shows the window and returns when it is closed.
Gtk::Main::run(window);
return 0;
}