Send wxEVT_SET_FOCUS for composite window when a child gets focus

wxCompositeWindow already connected to child wxEVT_KILL_FOCUS events and
generated the same event for the composite window itself, but didn't do
it for wxEVT_SET_FOCUS, resulting in not getting these events for the
main window as expected. E.g. this resulted in never getting any
wxEVT_SET_FOCUS events for wxSearchCtrl when using its generic version
(i.e. not under Mac).

Fix this by connecting to wxEVT_SET_FOCUS events for the children too.
Note that this relies on having a correct "previously focused window" in
these events, if this doesn't work reliably for some ports, we might
need to maintain a "bool m_hasFocus" field in wxCompositeWindow itself
instead.

Also note that we might avoid having all this code in wxCompositeWindow
if we translated the underlying native focus event to wxFocusEvents for
both the real window and its GetMainWindowOfCompositeControl() if it's
different. This could potentially be simpler and would definitely be
more efficient, but would require more changes.

Closes #15569.
This commit is contained in:
Vadim Zeitlin
2018-01-29 18:32:54 +01:00
parent 21823bd37a
commit 3b40ff0d41

View File

@@ -193,7 +193,10 @@ private:
if ( child == this )
return; // not a child, we don't want to Connect() to ourselves
// Always capture wxEVT_KILL_FOCUS:
child->Connect(wxEVT_SET_FOCUS,
wxFocusEventHandler(wxCompositeWindow::OnSetFocus),
NULL, this);
child->Connect(wxEVT_KILL_FOCUS,
wxFocusEventHandler(wxCompositeWindow::OnKillFocus),
NULL, this);
@@ -221,6 +224,27 @@ private:
event.Skip();
}
void OnSetFocus(wxFocusEvent& event)
{
event.Skip();
// When a child of a composite window gains focus, the entire composite
// focus gains focus as well -- unless it had it already.
//
// We suppose that we hadn't had focus if the event doesn't carry the
// previously focused window as it normally means that it comes from
// outside of this program.
wxWindow* const oldFocus = event.GetWindow();
if ( !oldFocus || oldFocus->GetMainWindowOfCompositeControl() != this )
{
wxFocusEvent eventThis(wxEVT_SET_FOCUS, this->GetId());
eventThis.SetEventObject(this);
eventThis.SetWindow(event.GetWindow());
this->ProcessWindowEvent(eventThis);
}
}
void OnKillFocus(wxFocusEvent& event)
{
// Ignore focus changes within the composite control: