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
#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
// 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
// ---------------------------------------------------------------------------
/* 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;
}
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();