]> git.saurik.com Git - wxWidgets.git/commitdiff
Return NULL from wxWindow::GetCapture() when the capture is being lost.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 18 Aug 2013 13:28:19 +0000 (13:28 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 18 Aug 2013 13:28:19 +0000 (13:28 +0000)
Make GetCapture() return NULL during wxEVT_MOUSE_CAPTURE_{LOST,CHANGED} events
processing in wxMSW to help their handlers to avoid calling ReleaseCapture():
this shouldn't be done as the mouse capture is being lost anyhow and results
in reentrancy problems between NotifyCaptureLost() and ReleaseCapture() if
it's called.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74678 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/window.cpp

index d16f4990ff566e57bebf931d95ba69f10cbd9df6..c3e8c7faecbfec971bd108d139fc6ee7fff45bde 100644 (file)
@@ -59,6 +59,7 @@
 #include "wx/hashmap.h"
 #include "wx/evtloop.h"
 #include "wx/power.h"
 #include "wx/hashmap.h"
 #include "wx/evtloop.h"
 #include "wx/power.h"
+#include "wx/scopeguard.h"
 #include "wx/sysopt.h"
 
 #if wxUSE_DRAG_AND_DROP
 #include "wx/sysopt.h"
 
 #if wxUSE_DRAG_AND_DROP
@@ -240,6 +241,9 @@ EraseBgHooks gs_eraseBgHooks;
 // needed.
 int gs_modalEntryWindowCount = 0;
 
 // needed.
 int gs_modalEntryWindowCount = 0;
 
+// Indicates whether we are currently processing WM_CAPTURECHANGED message.
+bool gs_insideCaptureChanged = false;
+
 } // anonymous namespace
 
 // ---------------------------------------------------------------------------
 } // anonymous namespace
 
 // ---------------------------------------------------------------------------
@@ -804,6 +808,13 @@ void wxWindowMSW::DoReleaseMouse()
 
 /* static */ wxWindow *wxWindowBase::GetCapture()
 {
 
 /* static */ wxWindow *wxWindowBase::GetCapture()
 {
+    // When we receive WM_CAPTURECHANGED message, ::GetCapture() still returns
+    // the HWND that is losing the mouse capture. But as we must not release
+    // the capture for it (it's going to happen anyhow), pretend that there is
+    // no capture any more.
+    if ( gs_insideCaptureChanged )
+        return NULL;
+
     HWND hwnd = ::GetCapture();
     return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
 }
     HWND hwnd = ::GetCapture();
     return hwnd ? wxFindWinFromHandle(hwnd) : NULL;
 }
@@ -4544,6 +4555,12 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 
 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
 {
 
 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
 {
+    // Ensure that wxWindow::GetCapture() returns NULL if called from the event
+    // handlers invoked below. This is necessary to avoid wrongly calling
+    // ReleaseMouse() when we're already losing the mouse capture anyhow.
+    gs_insideCaptureChanged = true;
+    wxON_BLOCK_EXIT_SET(gs_insideCaptureChanged, false);
+
     // notify windows on the capture stack about lost capture
     // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
     wxWindowBase::NotifyCaptureLost();
     // notify windows on the capture stack about lost capture
     // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
     wxWindowBase::NotifyCaptureLost();