Return NULL from wxWindow::GetCapture() when the capture is being lost.

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
This commit is contained in:
Vadim Zeitlin
2013-08-18 13:28:19 +00:00
parent 2d145378f6
commit bf2c43c76e

View File

@@ -59,6 +59,7 @@
#include "wx/hashmap.h" #include "wx/hashmap.h"
#include "wx/evtloop.h" #include "wx/evtloop.h"
#include "wx/power.h" #include "wx/power.h"
#include "wx/scopeguard.h"
#include "wx/sysopt.h" #include "wx/sysopt.h"
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
@@ -240,6 +241,9 @@ EraseBgHooks gs_eraseBgHooks;
// needed. // needed.
int gs_modalEntryWindowCount = 0; 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(); HWND hwnd = ::GetCapture();
return hwnd ? wxFindWinFromHandle(hwnd) : NULL; 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 // 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): // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
wxWindowBase::NotifyCaptureLost(); wxWindowBase::NotifyCaptureLost();