]> git.saurik.com Git - wxWidgets.git/commitdiff
Use wxFindWindowAtPoint() for hit testing in wxPopupTransientWindow.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 18 Aug 2013 13:28:23 +0000 (13:28 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 18 Aug 2013 13:28:23 +0000 (13:28 +0000)
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

src/common/popupcmn.cpp

index 6921a0ceb83e0aa8123b0738832c180a1290e78d..09d012c6c140cf91336268fb9e3526089f89ff66 100644 (file)
@@ -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();
+                }
             }
         }
     }