]> git.saurik.com Git - wxWidgets.git/commitdiff
Fixed a rare wxAuiFloatingFrame dtor crash on MSW using a registration mechanism...
authorBryan Petty <bryan@ibaku.net>
Tue, 22 Jan 2008 08:20:18 +0000 (08:20 +0000)
committerBryan Petty <bryan@ibaku.net>
Tue, 22 Jan 2008 08:20:18 +0000 (08:20 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51324 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/aui/floatpane.h
include/wx/aui/framemanager.h
src/aui/floatpane.cpp
src/aui/framemanager.cpp

index 837a9d789e5ed5558a3c0da6b38e151a72f00f08..8c7360567624037bfb40c80ea196da28a88a4551 100644 (file)
@@ -31,6 +31,8 @@
 
 class WXDLLIMPEXP_AUI wxAuiFloatingFrame : public wxAuiFloatingFrameBaseClass
 {
+    friend class wxAuiManager;
+
 public:
     wxAuiFloatingFrame(wxWindow* parent,
                    wxAuiManager* owner_mgr,
@@ -45,6 +47,7 @@ public:
     wxAuiManager* GetOwnerManager() const;
     
 protected:
+    void SetOwnerManager(wxAuiManager* owner_mgr);
     virtual void OnMoveStart();
     virtual void OnMoving(const wxRect& window_rect, wxDirection dir);
     virtual void OnMoveFinished();
index 77a7d8b1d6cd054f7d992a635353a1e14f8db6e9..4043147af00fa06c360aa86a7254168ab57ee4d4 100644 (file)
@@ -121,6 +121,7 @@ enum wxAuiPaneInsertLevel
 
 
 // forwards and array declarations
+class WXDLLIMPEXP_FWD_AUI wxAuiFloatingFrame;
 class wxAuiDockUIPart;
 class wxAuiPaneButton;
 class wxAuiPaneInfo;
@@ -133,6 +134,7 @@ WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiDockInfo, wxAuiDockInfoArray, WXDLLIMPEXP
 WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiDockUIPart, wxAuiDockUIPartArray, WXDLLIMPEXP_AUI);
 WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiPaneButton, wxAuiPaneButtonArray, WXDLLIMPEXP_AUI);
 WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiPaneInfo, wxAuiPaneInfoArray, WXDLLIMPEXP_AUI);
+WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiFloatingFrame*, wxAuiFloatingFramePtrArray, class WXDLLIMPEXP_AUI);
 WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiPaneInfo*, wxAuiPaneInfoPtrArray, class WXDLLIMPEXP_AUI);
 WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxAuiDockInfo*, wxAuiDockInfoPtrArray, class WXDLLIMPEXP_AUI);
 #endif // SWIG
@@ -419,11 +421,9 @@ public:
 
 
 
-class WXDLLIMPEXP_FWD_AUI wxAuiFloatingFrame;
-
 class WXDLLIMPEXP_AUI wxAuiManager : public wxEvtHandler
 {
-friend class wxAuiFloatingFrame;
+    friend class wxAuiFloatingFrame;
 
 public:
 
@@ -511,6 +511,12 @@ public:
 
 protected:
 
+    // Sometimes floating frames are deleted after wxAuiManager, so we need
+    // to clear m_owner_mgr in the floating frame to avoid a crash. To do so,
+    // we register frames with wxAuiManager so it can keep track.
+    void RegisterFloatingFrame(wxAuiFloatingFrame* frame);
+    void UnregisterFloatingFrame(wxAuiFloatingFrame* frame);
+
     void UpdateHintWindowConfig();
 
     void DoFrameLayout();
@@ -601,6 +607,7 @@ protected:
     wxAuiPaneInfoArray m_panes;     // array of panes structures
     wxAuiDockInfoArray m_docks;     // array of docks structures
     wxAuiDockUIPartArray m_uiparts; // array of UI parts (captions, buttons, etc)
+    wxAuiFloatingFramePtrArray m_floating_frames; // array of floating frames
 
     int m_action;                // current mouse action
     wxPoint m_action_start;      // position where the action click started
index 1a7357f824635252ba69c45b20d4c8a125c0f2ed..ab81810d615cad41a22cc9dae25d1edadefbdcb5 100644 (file)
@@ -73,10 +73,13 @@ wxAuiFloatingFrame::wxAuiFloatingFrame(wxWindow* parent,
 wxAuiFloatingFrame::~wxAuiFloatingFrame()
 {
     // if we do not do this, then we can crash...
-    if(m_owner_mgr && m_owner_mgr->m_action_window == this)
+    if(m_owner_mgr)
     {
-        m_owner_mgr->m_action_window = NULL;
+        if(m_owner_mgr->m_action_window == this)
+            m_owner_mgr->m_action_window = NULL;
+        m_owner_mgr->UnregisterFloatingFrame(this);
     }
+
     m_mgr.UnInit();
 }
 
@@ -133,7 +136,7 @@ void wxAuiFloatingFrame::SetPaneWindow(const wxAuiPaneInfo& pane)
             size = pane.min_size;
         if (size == wxDefaultSize)
             size = m_pane_window->GetSize();
-        if (pane.HasGripper())
+        if (m_owner_mgr && pane.HasGripper())
         {
             if (pane.HasGripperTop())
                 size.y += m_owner_mgr->m_art->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
@@ -150,16 +153,28 @@ wxAuiManager* wxAuiFloatingFrame::GetOwnerManager() const
     return m_owner_mgr;
 }
 
+void wxAuiFloatingFrame::SetOwnerManager(wxAuiManager* owner_mgr)
+{
+    // we want to allow for NULL here to avoid crashing in dtor
+    m_owner_mgr = owner_mgr;
+}
 
 void wxAuiFloatingFrame::OnSize(wxSizeEvent& event)
 {
-    m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
+    if (m_owner_mgr)
+    {
+        m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
+    }
 }
 
 void wxAuiFloatingFrame::OnClose(wxCloseEvent& evt)
 {
-    m_owner_mgr->OnFloatingPaneClosed(m_pane_window, evt);
-    if (!evt.GetVeto()) {
+    if (m_owner_mgr)
+    {
+        m_owner_mgr->OnFloatingPaneClosed(m_pane_window, evt);
+    }
+    if (!evt.GetVeto())
+    {
         m_mgr.DetachPane(m_pane_window);
         Destroy();
     }
@@ -271,25 +286,34 @@ void wxAuiFloatingFrame::OnIdle(wxIdleEvent& event)
 void wxAuiFloatingFrame::OnMoveStart()
 {
     // notify the owner manager that the pane has started to move
-    m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
+    if (m_owner_mgr)
+    {
+        m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
+    }
 }
 
 void wxAuiFloatingFrame::OnMoving(const wxRect& WXUNUSED(window_rect), wxDirection dir)
 {
     // notify the owner manager that the pane is moving
-    m_owner_mgr->OnFloatingPaneMoving(m_pane_window, dir);
+    if (m_owner_mgr)
+    {
+        m_owner_mgr->OnFloatingPaneMoving(m_pane_window, dir);
+    }
     m_lastDirection = dir;
 }
 
 void wxAuiFloatingFrame::OnMoveFinished()
 {
     // notify the owner manager that the pane has finished moving
-    m_owner_mgr->OnFloatingPaneMoved(m_pane_window, m_lastDirection);
+    if (m_owner_mgr)
+    {
+        m_owner_mgr->OnFloatingPaneMoved(m_pane_window, m_lastDirection);
+    }
 }
 
 void wxAuiFloatingFrame::OnActivate(wxActivateEvent& event)
 {
-    if (event.GetActive())
+    if (m_owner_mgr && event.GetActive())
     {
         m_owner_mgr->OnFloatingPaneActivated(m_pane_window);
     }
index c94279ccd65962b8d605d784e8b725e955965044..4c856f2c52b6c2c4a2ae8dc2a4dc1135e07d7b1a 100644 (file)
@@ -610,6 +610,17 @@ wxAuiManager::~wxAuiManager()
     }
 #endif
 
+    // We need to remove any reference to this wxAuiManager in any of the
+    // wxAuiFloatingFrames associated with this manager in case they haven't
+    // been deleted just yet.
+    // We need an array copy since Unregister removes the items.
+    wxAuiFloatingFramePtrArray array_copy = m_floating_frames;
+    int i, count = array_copy.GetCount();
+    for (i = 0; i < count; ++i)
+    {
+        UnregisterFloatingFrame(array_copy.Item(i));
+    }
+
     delete m_art;
 }
 
@@ -617,7 +628,9 @@ wxAuiManager::~wxAuiManager()
 wxAuiFloatingFrame* wxAuiManager::CreateFloatingFrame(wxWindow* parent,
                                                       const wxAuiPaneInfo& pane_info)
 {
-    return new wxAuiFloatingFrame(parent, this, pane_info);
+    wxAuiFloatingFrame* frame = new wxAuiFloatingFrame(parent, this, pane_info);
+    RegisterFloatingFrame(frame);
+    return frame;
 }
 
 bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p))
@@ -627,6 +640,37 @@ bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p))
     return !(wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT));
 }
 
+// registers a floating frame with this manager (see header)
+void wxAuiManager::RegisterFloatingFrame(wxAuiFloatingFrame* frame)
+{
+    frame->SetOwnerManager(this);
+    int i, count = m_floating_frames.GetCount();
+    for (i = 0; i < count; ++i)
+    {
+        wxAuiFloatingFrame* f = m_floating_frames.Item(i);
+        if (f == frame)
+            // this frame is already registered
+            return;
+    }
+    m_floating_frames.Add(frame);
+}
+
+// unregisters a floating frame from this manager (see header)
+void wxAuiManager::UnregisterFloatingFrame(wxAuiFloatingFrame* frame)
+{
+    frame->SetOwnerManager(NULL);
+    int i, count = m_floating_frames.GetCount();
+    for (i = 0; i < count; ++i)
+    {
+        wxAuiFloatingFrame* f = m_floating_frames.Item(i);
+        if (f == frame)
+        {
+            m_floating_frames.Remove(f);
+            return;
+        }
+    }
+}
+
 // GetPane() looks up a wxAuiPaneInfo structure based
 // on the supplied window pointer.  Upon failure, GetPane()
 // returns an empty wxAuiPaneInfo, a condition which can be checked