From e87544ae70cb1ab3bb97419b76a45fdce6e33739 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 28 Feb 2018 16:55:16 +0100 Subject: [PATCH] Fix possible hang after clearing wxTAB_TRAVERSAL style in wxMSW Clearing this style by calling SetWindowStyleFlag() could reset WS_EX_CONTROLPARENT extended flags bit, breaking the invariant that the parent of any window with this bit set has it as well and resulting in hangs due to infinite loops inside Windows own code iterating over the controls. Prevent this from happening by always preserving this style bit if it was previously set in MSWUpdateStyle(). This is a bit ugly, but there doesn't seem to be any obviously better way to do it. Closes #18091. --- docs/changes.txt | 4 ++++ src/msw/window.cpp | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/changes.txt b/docs/changes.txt index f4867d6ac6fe..73471219dd4f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -71,6 +71,10 @@ All: - Make wxList and wxVector iterators conform to input iterator requirements. +wxMSW: + +- Fix hang after clearing wxTAB_TRAVERSAL style on a window with children. + 3.1.1: (released 2018-02-19) ---------------------------- diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 0082cef587d2..ca8fccb9da40 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1409,7 +1409,14 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld) WS_SYSMENU) ) != 0; } - // and the extended style + // There is one extra complication with the extended style: we must never + // reset WS_EX_CONTROLPARENT because it may break the invariant that the + // parent of any window with this style bit set has it as well. We enforce + // this invariant elsewhere and must not clear it here to avoid the fatal + // problems (hangs) which happen if we break it, so ensure it is preserved. + if ( exstyleOld & WS_EX_CONTROLPARENT ) + exstyle |= WS_EX_CONTROLPARENT; + wxMSWWinExStyleUpdater updateExStyle(GetHwnd()); if ( updateExStyle.TurnOff(exstyleOld).TurnOn(exstyle).Apply() ) {