Fix key events for native GTK controls such as wxDataViewCtrl

Connect to key-{press,release}-event on the "focus widget" rather than
the main widget, to ensure that we get them before the native control
does and so can generate the key events even for the keys handled by the
control internally.

This allows to get events for the arrow keys in wxDataViewCtrl, for
example, while previously these keys were consumed by the control
itself, as could be seen with the following patch to the sample

---------------------------------- >8 --------------------------------------
diff --git a/samples/treelist/treelist.cpp
b/samples/treelist/treelist.cpp
index af6905cecb..74894cc9a9 100644
--- a/samples/treelist/treelist.cpp
+++ b/samples/treelist/treelist.cpp
@@ -349,6 +349,10 @@ bool MyApp::OnInit()
     sizer->Add(textLog, wxSizerFlags(1).Expand());
     SetSizer(sizer);

+    m_treelist->GetView()->Bind(wxEVT_KEY_DOWN, [](wxKeyEvent& e) {
+        wxLogMessage("Key in tree: %d", e.GetKeyCode());
+        e.Skip();
+    });

     // Finally show everything.
     Show();
---------------------------------- >8 --------------------------------------

Pressing arrow keys didn't generate the expected message before (unless
the focus was on the control header and not on the main area itself).

This may fix similar issues with other controls setting m_focusWidget as
well.
This commit is contained in:
Vadim Zeitlin
2021-05-23 12:29:07 +02:00
parent 43ace6193a
commit c9d7ba3171

View File

@@ -3692,10 +3692,18 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
g_source_unref(source);
}
g_signal_connect (widget, "key_press_event",
// When we're called for the main widget itself (but not when connecting
// events for some other widget, such as individual radio buttons in
// wxRadioBox::Create()), connect to m_focusWidget for the keyboard events
// instead, as it should be used for everything keyboard input-related.
GtkWidget* const focusWidget = widget == m_widget && m_focusWidget
? m_focusWidget
: widget;
g_signal_connect (focusWidget, "key_press_event",
G_CALLBACK (gtk_window_key_press_callback), this);
g_signal_connect (widget, "key_release_event",
g_signal_connect (focusWidget, "key_release_event",
G_CALLBACK (gtk_window_key_release_callback), this);
g_signal_connect (widget, "button_press_event",
G_CALLBACK (gtk_window_button_press_callback), this);
g_signal_connect (widget, "button_release_event",