Bind focus events to direct children only in wxCompositeWindow

Previously, wxEVT_{SET,KILL}_FOCUS event handlers were connected to all
children, even the indirect ones, which resulted in duplicate focus
events if a grandchildren forward its focus event to its parent window,
as happens e.g. with wxComboCtrl, which contains a text control that
forwards its focus events to the containing control itself.

This change seems globally sound, even if it might break some controls
whose children don't get the expected focus events themselves, because
the right thing to do is to fix those children. And it fixes duplicate
focus events in wxDatePickerCtrlGeneric.
This commit is contained in:
Vadim Zeitlin 2018-07-22 23:41:53 +02:00
parent 97e217e175
commit 06d2b836a0

View File

@ -186,8 +186,21 @@ private:
// support) to hook into its event processing. // support) to hook into its event processing.
wxWindow *child = event.GetWindow(); wxWindow *child = event.GetWindow();
if ( child == this )
return; // not a child, we don't want to bind to ourselves // Check that it's one of our children: it could also be this window
// itself (for which we don't need to handle focus at all) or one of
// its grandchildren and we don't want to bind to those as child
// controls are supposed to be well-behaved and get their own focus
// event if any of their children get focus anyhow, so binding to them
// would only result in duplicate events.
//
// Notice that we can't use GetCompositeWindowParts() here because the
// member variables that are typically used in its implementation in
// the derived classes would typically not be initialized yet, as this
// event is generated by "m_child = new wxChildControl(this, ...)" code
// before "m_child" is assigned.
if ( child->GetParent() != this )
return;
child->Bind(wxEVT_SET_FOCUS, &wxCompositeWindow::OnSetFocus, this); child->Bind(wxEVT_SET_FOCUS, &wxCompositeWindow::OnSetFocus, this);