Chapter 23. Keyboard Events

## Chapter 23. Keyboard Events

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.

## Overview

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);

### Example

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.

Figure 23.1. Keyboard Events - Simple

Source Code

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;
    }

Plugs and Sockets Example |  | Event Propagation