]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
wxRTC: save and load the 'shown' status in case there's a situation where layout...
[wxWidgets.git] / src / msw / window.cpp
index d16f4990ff566e57bebf931d95ba69f10cbd9df6..a08d1fa2ab3e6dd7e547e5e90b0dd42e126ac51a 100644 (file)
@@ -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;
 }
@@ -1189,6 +1200,11 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd)
     if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
     {
         wxSetWindowProc(hwnd, wxWndProc);
+
+        // If the window didn't use our window proc during its creation, the
+        // code in HandleCreate() hasn't been executed, so do it here.
+        if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
+            EnsureParentHasControlParentStyle(GetParent());
     }
     else
     {
@@ -2287,7 +2303,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
 {
     // wxUniversal implements tab traversal itself
 #ifndef __WXUNIVERSAL__
-    if ( m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL) )
+    // Notice that we check for WS_EX_CONTROLPARENT and not wxTAB_TRAVERSAL
+    // here. While usually they are both set or both unset, doing it like this
+    // also works if there is ever a bug that results in wxTAB_TRAVERSAL being
+    // set but not WS_EX_CONTROLPARENT as we must not call IsDialogMessage() in
+    // this case, it would simply hang (see #15458).
+    if ( m_hWnd != 0 && (wxGetWindowExStyle(this) & WS_EX_CONTROLPARENT) )
     {
         // intercept dialog navigation keys
         MSG *msg = (MSG *)pMsg;
@@ -4544,6 +4565,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();