]> git.saurik.com Git - wxWidgets.git/commitdiff
Tweak wxGTK keyboard handling to allow accelerators to work again.
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 21 Mar 2013 22:36:57 +0000 (22:36 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 21 Mar 2013 22:36:57 +0000 (22:36 +0000)
Accelerators were broken by the changes of r72640 which were done to ensure
that the focused window gets the keyboard event first, before its top level
parent. Fix them now by still passing the events to the focused window first
but also passing them to the parent top level if it hasn't been handled by the
focused child.

Unfortunately this is still not fully compatible with wxMSW because in wxGTK
wxEVT_CHAR handler must skip the event in order to allow the accelerator using
the same key to work, while in wxMSW the accelerator can only be suppressed by
overriding wxWindow::MSWShouldPreProcessMessage(). We will need to make the
two ports behave in the same way when the event is not skipped in the future.

But for now, at least make them both behave correctly when the handler does
skip the event.

Closes #14553.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73692 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

samples/keyboard/keyboard.cpp
src/gtk/toplevel.cpp

index 44456fede1ec138297d2645de09ad69f20700054..7b4bbe9cb61dd1b986c2d78528755b429ad248a8 100644 (file)
@@ -53,7 +53,7 @@ private:
             event.Skip();
     }
     void OnKeyUp(wxKeyEvent& event) { LogEvent("KeyUp", event); }
-    void OnChar(wxKeyEvent& event) { LogEvent("Char", event); }
+    void OnChar(wxKeyEvent& event) { LogEvent("Char", event); event.Skip(); }
     void OnCharHook(wxKeyEvent& event)
     {
         // The logged messages can be confusing if the input window doesn't
index d6ad28c1999a993471f8cdf8c8575313253c0343..0e476e2519300f9ecf1f72e156cc0ee9b38f0212 100644 (file)
@@ -208,6 +208,38 @@ gboolean gtk_frame_focus_out_callback(GtkWidget * WXUNUSED(widget),
 }
 }
 
+// ----------------------------------------------------------------------------
+// key_press_event
+// ----------------------------------------------------------------------------
+extern "C" {
+static
+gint
+wxgtk_tlw_key_press_event(GtkWidget *widget, GdkEventKey *event)
+{
+    GtkWindow* const window = GTK_WINDOW(widget);
+
+    // By default GTK+ checks for the menu accelerators in this (top level)
+    // window first and then propagates the event to the currently focused
+    // child from where it bubbles up the window parent chain. In wxWidgets,
+    // however, we want the child window to have the event first but still
+    // handle it as an accelerator if it's not processed there, so we need to
+    // customize this by reversing the order of the steps done in the standard
+    // GTK+ gtk_window_key_press_event() handler.
+
+    if ( gtk_window_propagate_key_event(window, event) )
+        return TRUE;
+
+    if ( gtk_window_activate_key(window, event) )
+        return TRUE;
+
+    GtkObjectClass* parent_class = &GTK_WIDGET_GET_CLASS(widget)->parent_class;
+    if ( GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event) )
+        return TRUE;
+
+    return FALSE;
+}
+}
+
 //-----------------------------------------------------------------------------
 // "size_allocate" from m_wxwindow
 //-----------------------------------------------------------------------------
@@ -645,13 +677,10 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent,
     g_signal_connect_after (m_widget, "focus_out_event",
                       G_CALLBACK (gtk_frame_focus_out_callback), this);
 
-    // GTK processes key events at the top level first, which handles for
-    // menu accelerators and shortcuts before passing the event on to the
-    // focus child window to begin propagation. We want to propagate
-    // first, so we connect gtk_window_propagate_key_event to
-    // key_press_event.
+    // We need to customize the default GTK+ logic for key processing to make
+    // it conforming to wxWidgets event processing order.
     g_signal_connect (m_widget, "key_press_event",
-                      G_CALLBACK (gtk_window_propagate_key_event), NULL);
+                      G_CALLBACK (wxgtk_tlw_key_press_event), NULL);
 
 #ifdef GDK_WINDOWING_X11
 #ifdef __WXGTK3__