From 06d2b836a06a6b541fde8f7ada0af31cc6061e22 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Jul 2018 23:41:53 +0200 Subject: [PATCH] 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. --- include/wx/compositewin.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/wx/compositewin.h b/include/wx/compositewin.h index 8483414686..23ee6f738b 100644 --- a/include/wx/compositewin.h +++ b/include/wx/compositewin.h @@ -186,8 +186,21 @@ private: // support) to hook into its event processing. 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);