From bf2c43c76e2819be443ab1d830ab68d9569d66b1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Aug 2013 13:28:19 +0000 Subject: [PATCH] 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 --- src/msw/window.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index d16f4990ff..c3e8c7faec 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -59,6 +59,7 @@ #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 @@ -240,6 +241,9 @@ EraseBgHooks gs_eraseBgHooks; // needed. int gs_modalEntryWindowCount = 0; +// Indicates whether we are currently processing WM_CAPTURECHANGED message. +bool gs_insideCaptureChanged = false; + } // anonymous namespace // --------------------------------------------------------------------------- @@ -804,6 +808,13 @@ void wxWindowMSW::DoReleaseMouse() /* 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; } @@ -4544,6 +4555,12 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) 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(); -- 2.47.2