From: Vadim Zeitlin Date: Sun, 18 Aug 2013 13:28:23 +0000 (+0000) Subject: Use wxFindWindowAtPoint() for hit testing in wxPopupTransientWindow. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/5f9e369af0c834bbde0f7f5d2047abd736967f58 Use wxFindWindowAtPoint() for hit testing in wxPopupTransientWindow. This works even with irregularly shaped windows such as wxRichToolTip unlike the old naive test using wxRect::Contains() which didn't and resulted in us believing that the mouse was outside the window when it was still in it and (somehow, the details are not totally clear) recapturing the mouse again and again in the same window which resulted in assert failures with the new checks in wxWindowBase::CaptureMouse() or the capture stack corruption before this. Closes #15288. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74679 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/common/popupcmn.cpp b/src/common/popupcmn.cpp index 6921a0ceb8..09d012c6c1 100644 --- a/src/common/popupcmn.cpp +++ b/src/common/popupcmn.cpp @@ -449,21 +449,31 @@ void wxPopupTransientWindow::OnIdle(wxIdleEvent& event) if (IsShown() && m_child) { - wxPoint pos = ScreenToClient(wxGetMousePosition()); - wxRect rect(GetSize()); - - if ( rect.Contains(pos) ) + // Store the last mouse position to minimize the number of calls to + // wxFindWindowAtPoint() which are quite expensive. + static wxPoint s_posLast; + const wxPoint pos = wxGetMousePosition(); + if ( pos != s_posLast ) { - if ( m_child->HasCapture() ) + s_posLast = pos; + + wxWindow* const winUnderMouse = wxFindWindowAtPoint(pos); + + // We release the mouse capture while the mouse is inside the popup + // itself to allow using it normally with the controls inside it. + if ( wxGetTopLevelParent(winUnderMouse) == this ) { - m_child->ReleaseMouse(); + if ( m_child->HasCapture() ) + { + m_child->ReleaseMouse(); + } } - } - else - { - if ( !m_child->HasCapture() ) + else // And we reacquire it as soon as the mouse goes outside. { - m_child->CaptureMouse(); + if ( !m_child->HasCapture() ) + { + m_child->CaptureMouse(); + } } } }