[gtkmm-documentation] Update the keyboard_events/propagation example



commit 3a218740412725c3a2c486c2ed7f9bcba12b0139
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Sun Nov 25 17:16:08 2018 +0100

    Update the keyboard_events/propagation example
    
    Show what happens in the three event propagation phases.
    Event propagation in gtk+4 is different from event propagation in gtk+3.

 .../keyboard_events/propagation/examplewindow.cc   | 142 ++++++++++++++-------
 .../keyboard_events/propagation/examplewindow.h    |  18 +--
 2 files changed, 102 insertions(+), 58 deletions(-)
---
diff --git a/examples/book/keyboard_events/propagation/examplewindow.cc 
b/examples/book/keyboard_events/propagation/examplewindow.cc
index 1fd0adf..31350dd 100644
--- a/examples/book/keyboard_events/propagation/examplewindow.cc
+++ b/examples/book/keyboard_events/propagation/examplewindow.cc
@@ -14,53 +14,75 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-//TODO: This example does not work as intended in gtkmm4. The propagation of
-// event signal works differently in gtk+3 and gtk+4. GtkEntry in gtk+4 marks
-// a key press signal as handled. It's not propagated further up to the Grid
-// and the Window.
+// In gtkmm3, this example used an Entry instead of m_label2. This would not work
+// as intended in gtkmm4. GtkEntry in gtk+4 marks a key press signal as handled
+// in the bubble phase. It's not propagated further up to the Grid and the Window.
 
 #include "examplewindow.h"
 #include <iostream>
 
 ExampleWindow::ExampleWindow()
+:
+m_label1("A label"),
+m_label2("Write here"),
+m_checkbutton_can_propagate_down("Can propagate down"),
+m_checkbutton_can_propagate_up("Can propagate up")
 {
   set_title("Event Propagation");
   m_container.set_margin(10);
   add(m_container);
 
-  m_label.set_label("A label");
-  m_checkbutton_can_propagate.set_label("Can Propagate");
-  m_checkbutton_can_propagate.set_active();
+  m_frame.add(m_label2);
+  m_label2.set_selectable();
+  m_checkbutton_can_propagate_down.set_active();
+  m_checkbutton_can_propagate_up.set_active();
 
-  // Main Container
+  // Main container
   m_container.set_orientation(Gtk::Orientation::VERTICAL);
-  m_container.add(m_label);
-  m_container.add(m_entry);
-  m_container.add(m_checkbutton_can_propagate);
+  m_container.add(m_label1);
+  m_container.add(m_frame);
+  m_container.add(m_checkbutton_can_propagate_down);
+  m_container.add(m_checkbutton_can_propagate_up);
 
   // Events
+  const bool after = false; // Run before or after the default signal handlers.
+
+  // Called in the capture phase of the event handling.
   auto controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
   controller->signal_key_pressed().connect(
-    sigc::mem_fun(*this, &ExampleWindow::entry_key_pressed), true);
-  m_entry.add_controller(controller);
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::label2_key_pressed), "capture"), after);
+  m_label2.add_controller(controller);
 
   controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
   controller->signal_key_pressed().connect(
-    sigc::mem_fun(*this, &ExampleWindow::grid_key_pressed), true);
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::grid_key_pressed), "capture"), after);
   m_container.add_controller(controller);
 
-  // Called in the capture phase of the event handling.
   controller = Gtk::EventControllerKey::create();
   controller->set_propagation_phase(Gtk::PropagationPhase::CAPTURE);
   controller->signal_key_pressed().connect(
-    sigc::mem_fun(*this, &ExampleWindow::window_key_pressed_capture), false);
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::window_key_pressed), "capture"), after);
   add_controller(controller);
 
   // Called in the target phase of the event handling.
   controller = Gtk::EventControllerKey::create();
   controller->set_propagation_phase(Gtk::PropagationPhase::TARGET);
   controller->signal_key_pressed().connect(
-    sigc::mem_fun(*this, &ExampleWindow::window_key_pressed_target), false);
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::label2_key_pressed), "target"), after);
+  m_label2.add_controller(controller);
+
+  controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::TARGET);
+  controller->signal_key_pressed().connect(
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::grid_key_pressed), "target"), after);
+  m_container.add_controller(controller);
+
+  controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::TARGET);
+  controller->signal_key_pressed().connect(
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::window_key_pressed), "target"), after);
   add_controller(controller);
 
   // Called in the bubble phase of the event handling.
@@ -68,58 +90,80 @@ ExampleWindow::ExampleWindow()
   controller = Gtk::EventControllerKey::create();
   controller->set_propagation_phase(Gtk::PropagationPhase::BUBBLE);
   controller->signal_key_pressed().connect(
-    sigc::mem_fun(*this, &ExampleWindow::window_key_pressed_bubble), true);
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::label2_key_pressed), "bubble"), after);
+  m_label2.add_controller(controller);
+
+  controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::BUBBLE);
+  controller->signal_key_pressed().connect(
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::grid_key_pressed), "bubble"), after);
+  m_container.add_controller(controller);
+
+  controller = Gtk::EventControllerKey::create();
+  controller->set_propagation_phase(Gtk::PropagationPhase::BUBBLE);
+  controller->signal_key_pressed().connect(
+    sigc::bind(sigc::mem_fun(*this, &ExampleWindow::window_key_pressed), "bubble"), after);
   add_controller(controller);
 }
 
-//By changing the return value we allow, or don't allow, the event to propagate to other elements.
-bool ExampleWindow::entry_key_pressed(guint, guint, Gdk::ModifierType)
+// By changing the return value we allow, or don't allow, the event to propagate to other elements.
+bool ExampleWindow::label2_key_pressed(guint keyval, guint, Gdk::ModifierType, const Glib::ustring& phase)
 {
-  std::cout << "Entry" << std::endl;
+  std::cout << "Label,  " << phase << " phase" << std::endl;
 
-  if(m_checkbutton_can_propagate.get_active())
+  if (phase == "bubble")
   {
-    return false;
+    const gunichar unichar = gdk_keyval_to_unicode(keyval);
+    if (unichar != 0)
+    {
+      if (m_first)
+      {
+        m_label2.set_label("");
+        m_first = false;
+      }
+      if (unichar == '\b')
+        m_label2.set_label("");
+      else
+      {
+        const Glib::ustring newchar(1, unichar);
+        m_label2.set_label(m_label2.get_label() + newchar);
+      }
+    }
+
+    if (!m_checkbutton_can_propagate_up.get_active())
+      return true; // Don't propagate
   }
-
-  return true;
-}
-
-bool ExampleWindow::grid_key_pressed(guint, guint, Gdk::ModifierType)
-{
-  std::cout << "Grid" << std::endl;
-
-  //Let it propagate:
   return false;
 }
 
-bool ExampleWindow::window_key_pressed_capture(guint, guint, Gdk::ModifierType)
+bool ExampleWindow::grid_key_pressed(guint, guint, Gdk::ModifierType, const Glib::ustring& phase)
 {
-  std::cout << "Window, capture phase" << std::endl;
-  return false;
-}
+  std::cout << "Grid,   " << phase << " phase" << std::endl;
 
-bool ExampleWindow::window_key_pressed_target(guint, guint, Gdk::ModifierType)
-{
-  std::cout << "Window, target phase" << std::endl;
+  // Let it propagate
   return false;
 }
 
-// This will set the entry's text in the label, every time a key is pressed.
-bool ExampleWindow::window_key_pressed_bubble(guint, guint, Gdk::ModifierType)
+// This will set the second label's text in the first label every time a key is pressed.
+bool ExampleWindow::window_key_pressed(guint, guint, Gdk::ModifierType, const Glib::ustring& phase)
 {
-  std::cout << "Window, bubble phase";
-
-  //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 m_checkbutton_can_propagate wasn't active
-  if(m_entry.has_focus())
+  if (phase == "capture")
+    std::cout << std::endl;
+  std::cout << "Window, " << phase << " phase";
+
+  // Checking if the second label is on focus, otherwise the label would get
+  // changed by pressing keys on the window (when the label is not on focus),
+  // even if m_checkbutton_can_propagate_up wasn't active.
+  if (phase == "bubble" && m_label2.has_focus())
   {
-    m_label.set_text(m_entry.get_text());
-    std::cout << ", " << m_entry.get_text();
+    m_label1.set_text(m_label2.get_text());
+    std::cout << ", " << m_label2.get_text();
   }
   std::cout << std::endl;
 
-  return true;
+  if (phase == "capture" && !m_checkbutton_can_propagate_down.get_active())
+    return true; // Don't propagate
+  return false;
 }
 
 ExampleWindow::~ExampleWindow()
diff --git a/examples/book/keyboard_events/propagation/examplewindow.h 
b/examples/book/keyboard_events/propagation/examplewindow.h
index faee06b..b72dba2 100644
--- a/examples/book/keyboard_events/propagation/examplewindow.h
+++ b/examples/book/keyboard_events/propagation/examplewindow.h
@@ -28,17 +28,17 @@ public:
 
 private:
   // Signal handlers:
-  bool entry_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state);
-  bool grid_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state);
-  bool window_key_pressed_capture(guint keyval, guint keycode, Gdk::ModifierType state);
-  bool window_key_pressed_target(guint keyval, guint keycode, Gdk::ModifierType state);
-  bool window_key_pressed_bubble(guint keyval, guint keycode, Gdk::ModifierType state);
+  bool label2_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state, const Glib::ustring& phase);
+  bool grid_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state, const Glib::ustring& phase);
+  bool window_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state, const Glib::ustring& phase);
 
+  bool m_first = true;
   Gtk::Grid m_container;
-
-  Gtk::Label m_label;
-  Gtk::Entry m_entry;
-  Gtk::CheckButton m_checkbutton_can_propagate;
+  Gtk::Frame m_frame;
+  Gtk::Label m_label1;
+  Gtk::Label m_label2;
+  Gtk::CheckButton m_checkbutton_can_propagate_down;
+  Gtk::CheckButton m_checkbutton_can_propagate_up;
 };
 
 #endif //GTKMM_EVENT_PROPAGATION_H


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