[gtkmm-documentation] Keyboard Events chapter: Clarify keyboard event propagation.



commit d0816681199ea195da2f899f7eb714367937a503
Author: Pedro Ferreira <darkiiiiii gmail com>
Date:   Mon Jan 30 18:45:31 2012 +0100

    Keyboard Events chapter: Clarify keyboard event propagation.
    
    * docs/tutorial/C/gtkmm-tutorial-in.xml: Mention that keyboard events are
    first tested for keyboard shortcut keys.
    * examples/book/keyboard_events/simple/keyboard_events.[h|cc]:
    on_key_press_event() is an overridden default handler. Don't call connect().
    * examples/book/keyboard_events/propagation/event_propagation.[h|cc]:
    Add on_key_release_event() and windowKeyReleaseBefore().
    Bug #661857, comment 22.

 ChangeLog                                          |   12 +++++++
 docs/tutorial/C/gtkmm-tutorial-in.xml              |   32 ++++++++++++++++++--
 .../keyboard_events/propagation/examplewindow.cc   |   26 +++++++++++++++-
 .../keyboard_events/propagation/examplewindow.h    |   12 ++++----
 .../book/keyboard_events/simple/examplewindow.cc   |   16 +++++----
 .../book/keyboard_events/simple/examplewindow.h    |    5 +--
 6 files changed, 82 insertions(+), 21 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8ee63c5..02b24e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2012-01-30  Pedro Ferreira <darkiiiiii gmail com>
 
+	Keyboard Events chapter: Clarify keyboard event propagation.
+
+	* docs/tutorial/C/gtkmm-tutorial-in.xml: Mention that keyboard events are
+	first tested for keyboard shortcut keys.
+	* examples/book/keyboard_events/simple/keyboard_events.[h|cc]:
+	on_key_press_event() is an overridden default handler. Don't call connect().
+	* examples/book/keyboard_events/propagation/event_propagation.[h|cc]:
+	Add on_key_release_event() and windowKeyReleaseBefore().
+	Bug #661857, comment 22.
+
+2012-01-30  Pedro Ferreira <darkiiiiii gmail com>
+
 	New example programs in the DrawingArea chapter.
 
 	* docs/tutorial/C/gtkmm-tutorial-in.xml: Add a section on drawing thin lines.
diff --git a/docs/tutorial/C/gtkmm-tutorial-in.xml b/docs/tutorial/C/gtkmm-tutorial-in.xml
index 30490bf..ee281fd 100644
--- a/docs/tutorial/C/gtkmm-tutorial-in.xml
+++ b/docs/tutorial/C/gtkmm-tutorial-in.xml
@@ -5737,6 +5737,9 @@ m_entry.add_events(Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
         <keycap>Alt</keycap>+<keycap>1</keycap> selects the first radio button,
         <keycap>Alt</keycap>+<keycap>2</keycap> selects the second one, and the
         <keycap>Esc</keycap> key hides (closes) the window.
+        The default event signal handler is overridden, as described in the
+        <link linkend="sec-overriding-default-signal-handlers">Overriding default signal handlers</link>
+        section in the appendix.
       </para>
 
       <figure id="figure-keyboardevents-simple">
@@ -5759,6 +5762,14 @@ m_entry.add_events(Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
       that handler will be called. 
     </para>
     <para>
+      Contrary to other events, keyboard events are first sent to the toplevel window
+      (<classname>Gtk::Window</classname>), where it will be checked
+      for any keyboard shortcuts that may be set (accelerator keys and mnemonics,
+      used for selecting menu items from the keyboard). After this (and assuming
+      the event wasn't handled), it is sent to the widget which has focus,
+      and the propagation begins from there.
+    </para>
+    <para>
       The event will propagate until it reaches the top-level widget, or until
       you stop the propagation by returning <literal>true</literal> from an
       event handler.
@@ -5771,13 +5782,28 @@ m_entry.add_events(Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
     <sect2 id="keyboardevents-propagation-example">
     <title>Example</title>
       <para>
-        In this example there are three event handlers, one in the
+        In this example there are three event handlers that are called after
+        <classname>Gtk::Window</classname>'s default event handler, one in the
         <classname>Gtk::Entry</classname>, one in the <classname>Gtk::Grid</classname>
         and one in the <classname>Gtk::Window</classname>.
       </para>
       <para>
-        When you write in the entry, a key release event will be emitted first
-        in the <classname>Entry</classname> and, depending on whether we let
+        In the <classname>Gtk::Window</classname>, we have also the default handler
+        overridden (<methodname>on_key_release_event()</methodname>), and
+        another handler being called before the default handler
+        (<methodname>windowKeyReleaseBefore()</methodname>).
+      </para>
+      <para>
+        The purpose of this example is to show the steps the event takes when it is emitted.
+      </para>
+      <para>
+        When you write in the entry, a key release event will be emitted,
+        which will go first to the toplevel window (<classname>Gtk::Window</classname>),
+        since we have one event handler set to be called before, that's what is
+        called first (<methodname>windowKeyReleaseBefore()</methodname>).
+        Then the default handler is called (which we have overridden), and after
+        that the event is sent to the widget that has focus,
+        the <classname>Entry</classname> in our example and, depending on whether we let
         it propagate, it can reach the <classname>Grid</classname>'s and the
         <classname>Window</classname>'s event handlers. If it propagates,
         the text you're writing will appear in the <classname>Label</classname>
diff --git a/examples/book/keyboard_events/propagation/examplewindow.cc b/examples/book/keyboard_events/propagation/examplewindow.cc
index 8e7d201..3ea7745 100644
--- a/examples/book/keyboard_events/propagation/examplewindow.cc
+++ b/examples/book/keyboard_events/propagation/examplewindow.cc
@@ -15,6 +15,7 @@
  */
 
 #include "examplewindow.h"
+#include <iostream>
 
 ExampleWindow::ExampleWindow()
 {
@@ -41,6 +42,11 @@ ExampleWindow::ExampleWindow()
   m_container.signal_key_release_event().connect(
     sigc::mem_fun(*this, &ExampleWindow::gridKeyRelease));
 
+  // Called before the default event signal handler.
+  signal_key_release_event().connect(
+    sigc::mem_fun(*this, &ExampleWindow::windowKeyReleaseBefore), false);
+
+  // Called after the default event signal handler.
   signal_key_release_event().connect(
     sigc::mem_fun(*this, &ExampleWindow::windowKeyRelease));
 
@@ -68,17 +74,33 @@ bool ExampleWindow::gridKeyRelease(GdkEventKey* /* event */ )
   return false;
 }
 
+bool ExampleWindow::windowKeyReleaseBefore(GdkEventKey* /* event */ )
+{
+  std::cout << "Window before" << std::endl;
+  return false;
+}
+
+bool ExampleWindow::on_key_release_event(GdkEventKey* event)
+{
+  std::cout << "Window overridden" << std::endl;
+
+  // call base class function (to get the normal behaviour)
+  return Gtk::Window::on_key_release_event(event);
+}
+
 // This will set the entry's text in the label, every time a key is pressed.
 bool ExampleWindow::windowKeyRelease(GdkEventKey* /* event */ )
 {
-  std::cout << "Window" << std::endl;
+  std::cout << "Window after";
 
   //checking if the entry is on focus, otherwise the label would get changed by pressing keys
-  //on the window (when the entry is not on focus), even if canPropagate wasn't active
+  //on the window (when the entry is not on focus), even if m_checkbutton_can_propagate wasn't active
   if(m_entry.has_focus())
   {
     m_label.set_text(m_entry.get_text());
+    std::cout << ", " << m_entry.get_text();
   }
+  std::cout << std::endl;
 
   return true;
 }
diff --git a/examples/book/keyboard_events/propagation/examplewindow.h b/examples/book/keyboard_events/propagation/examplewindow.h
index 7fe0cde..1e617cc 100644
--- a/examples/book/keyboard_events/propagation/examplewindow.h
+++ b/examples/book/keyboard_events/propagation/examplewindow.h
@@ -18,7 +18,6 @@
 #define GTKMM_EVENT_PROPAGATION_H
 
 #include <gtkmm.h>
-#include <iostream>
 
 class ExampleWindow : public Gtk::Window
 {
@@ -27,12 +26,14 @@ public:
   ExampleWindow();
   virtual ~ExampleWindow();
 
-
 private:
+  //Override default signal handler:
+  virtual bool on_key_release_event(GdkEventKey* event);
 
-  bool entryKeyRelease(GdkEventKey *event);
-  bool gridKeyRelease(GdkEventKey *event);
-  bool windowKeyRelease(GdkEventKey *event);
+  bool entryKeyRelease(GdkEventKey* event);
+  bool gridKeyRelease(GdkEventKey* event);
+  bool windowKeyReleaseBefore(GdkEventKey* event);
+  bool windowKeyRelease(GdkEventKey* event);
 
   Gtk::Grid m_container;
 
@@ -41,5 +42,4 @@ private:
   Gtk::CheckButton m_checkbutton_can_propagate;
 };
 
-
 #endif //GTKMM_EVENT_PROPAGATION_H
diff --git a/examples/book/keyboard_events/simple/examplewindow.cc b/examples/book/keyboard_events/simple/examplewindow.cc
index 0b60e69..06748aa 100644
--- a/examples/book/keyboard_events/simple/examplewindow.cc
+++ b/examples/book/keyboard_events/simple/examplewindow.cc
@@ -34,15 +34,14 @@ ExampleWindow::ExampleWindow()
   m_container.add(m_first);
   m_container.add(m_second);
 
-  // Events
+  // Events.
+  // We override the default event signal handler.
   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)
+bool ExampleWindow::on_key_press_event(GdkEventKey* event)
 {
   //GDK_MOD1_MASK -> the 'alt' key(mask)
   //GDK_KEY_1 -> the '1' key
@@ -53,24 +52,27 @@ bool ExampleWindow::on_key_press_event(GdkEventKey *event)
     (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((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();
+    return true;
   }
   else if(event->keyval == GDK_KEY_Escape)
   {
     //close the window, when the 'esc' key is pressed
     hide();
+    return true;
   }
 
-  //returning true, cancels the propagation of the event
-  return true;
+  //if the event has not been handled, call the base class
+  return Gtk::Window::on_key_press_event(event);
 }
 
-
 ExampleWindow::~ExampleWindow()
 {
 }
diff --git a/examples/book/keyboard_events/simple/examplewindow.h b/examples/book/keyboard_events/simple/examplewindow.h
index 3a40c79..31ea0e3 100644
--- a/examples/book/keyboard_events/simple/examplewindow.h
+++ b/examples/book/keyboard_events/simple/examplewindow.h
@@ -19,7 +19,6 @@
 
 #include <gtkmm.h>
 
-
 class ExampleWindow : public Gtk::Window
 {
 public:
@@ -28,12 +27,12 @@ public:
   virtual ~ExampleWindow();
 
 private:
-  bool on_key_press_event(GdkEventKey *event);
+  //Override default signal handler:
+  virtual bool on_key_press_event(GdkEventKey* event);
 
   Gtk::Grid m_container;
   Gtk::RadioButton m_first;
   Gtk::RadioButton m_second;
 };
 
-
 #endif //GTKMM_EXAMPLEWINDOW_H



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]