From 1c25a4c2aef8c001e48a99df271d72d1372ce398 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Thu, 13 Jun 2013 13:57:28 +0000
Subject: [PATCH] Use two step creation of wxListHeaderWindow to avoid
 reentrancy under OSX.

This improves the solution of the problem already solved in r74197 by
separating setting of m_headerWin variable from the window creation instead of
using an explicit recursion check.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74231 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 include/wx/generic/private/listctrl.h | 17 ++++++-----
 src/generic/listctrl.cpp              | 42 +++++++++++++--------------
 2 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/include/wx/generic/private/listctrl.h b/include/wx/generic/private/listctrl.h
index 2267ca3dd7..d7aa7883e5 100644
--- a/include/wx/generic/private/listctrl.h
+++ b/include/wx/generic/private/listctrl.h
@@ -336,13 +336,16 @@ protected:
 public:
     wxListHeaderWindow();
 
-    wxListHeaderWindow( wxWindow *win,
-                        wxWindowID id,
-                        wxListMainWindow *owner,
-                        const wxPoint &pos = wxDefaultPosition,
-                        const wxSize &size = wxDefaultSize,
-                        long style = 0,
-                        const wxString &name = wxT("wxlistctrlcolumntitles") );
+    // We provide only Create(), not the ctor, because we need to create the
+    // C++ object before creating the window, see the explanations in
+    // CreateOrDestroyHeaderWindowAsNeeded()
+    bool Create( wxWindow *win,
+                 wxWindowID id,
+                 wxListMainWindow *owner,
+                 const wxPoint &pos = wxDefaultPosition,
+                 const wxSize &size = wxDefaultSize,
+                 long style = 0,
+                 const wxString &name = wxT("wxlistctrlcolumntitles") );
 
     virtual ~wxListHeaderWindow();
 
diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp
index bf9448a331..1ababf3a26 100644
--- a/src/generic/listctrl.cpp
+++ b/src/generic/listctrl.cpp
@@ -952,15 +952,17 @@ wxListHeaderWindow::wxListHeaderWindow()
     m_resizeCursor = NULL;
 }
 
-wxListHeaderWindow::wxListHeaderWindow( wxWindow *win,
-                                        wxWindowID id,
-                                        wxListMainWindow *owner,
-                                        const wxPoint& pos,
-                                        const wxSize& size,
-                                        long style,
-                                        const wxString &name )
-                  : wxWindow( win, id, pos, size, style, name )
-{
+bool wxListHeaderWindow::Create( wxWindow *win,
+                                 wxWindowID id,
+                                 wxListMainWindow *owner,
+                                 const wxPoint& pos,
+                                 const wxSize& size,
+                                 long style,
+                                 const wxString &name )
+{
+    if ( !wxWindow::Create(win, id, pos, size, style, name) )
+        return false;
+
     Init();
 
     m_owner = owner;
@@ -978,6 +980,8 @@ wxListHeaderWindow::wxListHeaderWindow( wxWindow *win,
     if (!m_hasFont)
         SetOwnFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT ));
 #endif
+
+    return true;
 }
 
 wxListHeaderWindow::~wxListHeaderWindow()
@@ -4509,18 +4513,13 @@ void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded()
 
     if (needs_header)
     {
-        // since there is no separate Create method for the wxListHeaderWindow
-        // we have to guard against reentrancy which happens via new wxListHeaderWindow ->
-        // wxNavigationEnabled::AddChild -> ToggleWindowStyle -> SetWindowStyleFlag
-        // since has_header is still false then
-        static bool blockreentrancy = false;
-        
-        if ( blockreentrancy )
-            return;
-
-        blockreentrancy = true;
-
-        m_headerWin = new wxListHeaderWindow
+        // Notice that we must initialize m_headerWin first, and create the
+        // real window only later, so that the test in the beginning of the
+        // function blocks repeated creation of the header as it could happen
+        // before via wxNavigationEnabled::AddChild() -> ToggleWindowStyle() ->
+        // SetWindowStyleFlag().
+        m_headerWin = new wxListHeaderWindow();
+        m_headerWin->Create
                       (
                         this, wxID_ANY, m_mainWin,
                         wxPoint(0,0),
@@ -4531,7 +4530,6 @@ void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded()
                         ),
                         wxTAB_TRAVERSAL
                       );
-        blockreentrancy = false;
         
 #if defined( __WXMAC__ )
         static wxFont font( wxOSX_SYSTEM_FONT_SMALL );
-- 
2.45.2