From d7b88827b80bc5c0397ba0158ee18e65263e7f0f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 3 Feb 2018 22:32:37 +0100 Subject: [PATCH] Avoid spurious focus events for composite windows in wxMSW Composite windows, i.e. wxWindows composed of several HWNDs at MSW level, didn't handle focus events correctly and, for example, generated wxEVT_KILL_FOCUS event when the focus simply switched from wxComboBox itself to the EDIT control inside it, which broke using non-readonly wxComboBox as in-place editor inside wxDataViewCtrl. Check if the focus event notifies about the focus switching to, or from, another HWND belonging to the same window, and suppress wx event generation in this case as they don't make sense because the focus doesn't change at wx level. See #17034. --- src/msw/window.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index ead90f0321..0082cef587 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -4169,6 +4169,14 @@ bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) return false; } + if ( ContainsHWND(hwnd) ) + { + // If another subwindow of this window already had focus before, this + // window should already have focus at wx level, no need for another + // event. + return false; + } + // notify the parent keeping track of focus for the kbd navigation // purposes that we got it wxChildFocusEvent eventFocus((wxWindow *)this); @@ -4193,6 +4201,20 @@ bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) { + // Don't send the event when in the process of being deleted. This can + // only cause problems if the event handler tries to access the object. + if ( m_isBeingDeleted ) + { + return false; + } + + if ( ContainsHWND(hwnd) ) + { + // If the focus switches to another HWND which is part of the same + // wxWindow, we must not generate a wxEVT_KILL_FOCUS. + return false; + } + #if wxUSE_CARET // Deal with caret if ( m_caret ) @@ -4201,13 +4223,6 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) } #endif // wxUSE_CARET - // Don't send the event when in the process of being deleted. This can - // only cause problems if the event handler tries to access the object. - if ( m_isBeingDeleted ) - { - return false; - } - wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); event.SetEventObject(this);