From 61d4dbc66b855331836ea0083ade6f342ca95cf1 Mon Sep 17 00:00:00 2001 From: New Pagodi Date: Sat, 13 Jul 2019 12:40:27 -0500 Subject: [PATCH] Fix crash with wxSTC autocomp on macOS On macOS, the autocompletion popup maintains a pointer to its parent control since it sometimes needs to set a cursor on the control. However when the control is destroyed while the popup is active, the control is destroyed before the popup because of the delayed destruction used by the popup. This leaves the popup with a dangling pointer and can lead to crashes. To prevent this, let the popup handle the window destroy event for the control. Reset the pointer to NULL in that handler so that the popup will no longer try to access its parent control after it is deleted. --- src/stc/PlatWX.cpp | 33 ++++++++++++++++++++++++++++++--- src/stc/PlatWX.h | 4 ++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/stc/PlatWX.cpp b/src/stc/PlatWX.cpp index cb51295f68..8fb73b8d7b 100644 --- a/src/stc/PlatWX.cpp +++ b/src/stc/PlatWX.cpp @@ -2010,9 +2010,14 @@ PRectangle Window::GetMonitorRect(Point pt) { wxNonOwnedWindow::Create(parent, m_nativeWin); m_stc = wxDynamicCast(parent, wxStyledTextCtrl); m_isShown = false; + m_cursorSetByPopup = false; + m_prevCursor = wxSTC_CURSORNORMAL; Bind(wxEVT_ENTER_WINDOW, &wxSTCPopupBase::OnMouseEnter, this); Bind(wxEVT_LEAVE_WINDOW, &wxSTCPopupBase::OnMouseLeave, this); + + if ( m_stc ) + m_stc->Bind(wxEVT_DESTROY, &wxSTCPopupBase::OnParentDestroy, this); } wxSTCPopupBase::~wxSTCPopupBase() @@ -2020,7 +2025,11 @@ PRectangle Window::GetMonitorRect(Point pt) { UnsubclassWin(); CloseFloatingWindow(m_nativeWin); - SetSTCCursor(wxSTC_CURSORNORMAL); + if ( m_stc ) + { + m_stc->Unbind(wxEVT_DESTROY, &wxSTCPopupBase::OnParentDestroy,this); + RestoreSTCCursor(); + } } bool wxSTCPopupBase::Show(bool show) @@ -2038,7 +2047,7 @@ PRectangle Window::GetMonitorRect(Point pt) { else { HideFloatingWindow(m_nativeWin); - SetSTCCursor(wxSTC_CURSORNORMAL); + RestoreSTCCursor(); } return true; @@ -2056,7 +2065,20 @@ PRectangle Window::GetMonitorRect(Point pt) { void wxSTCPopupBase::SetSTCCursor(int cursor) { if ( m_stc ) + { + m_cursorSetByPopup = true; + m_prevCursor = m_stc->GetSTCCursor(); m_stc->SetSTCCursor(cursor); + } + } + + void wxSTCPopupBase::RestoreSTCCursor() + { + if ( m_stc != NULL && m_cursorSetByPopup ) + m_stc->SetSTCCursor(m_prevCursor); + + m_cursorSetByPopup = false; + m_prevCursor = wxSTC_CURSORNORMAL; } void wxSTCPopupBase::OnMouseEnter(wxMouseEvent& WXUNUSED(event)) @@ -2066,7 +2088,12 @@ PRectangle Window::GetMonitorRect(Point pt) { void wxSTCPopupBase::OnMouseLeave(wxMouseEvent& WXUNUSED(event)) { - SetSTCCursor(wxSTC_CURSORNORMAL); + RestoreSTCCursor(); + } + + void wxSTCPopupBase::OnParentDestroy(wxWindowDestroyEvent& WXUNUSED(event)) + { + m_stc = NULL; } #elif wxUSE_POPUPWIN diff --git a/src/stc/PlatWX.h b/src/stc/PlatWX.h index c24bd4f50e..8d1a73e63f 100644 --- a/src/stc/PlatWX.h +++ b/src/stc/PlatWX.h @@ -81,12 +81,16 @@ public: protected: virtual void DoSetSize(int, int, int, int, int) wxOVERRIDE; void SetSTCCursor(int); + void RestoreSTCCursor(); void OnMouseEnter(wxMouseEvent&); void OnMouseLeave(wxMouseEvent&); + void OnParentDestroy(wxWindowDestroyEvent& event); private: WX_NSWindow m_nativeWin; wxStyledTextCtrl* m_stc; + bool m_cursorSetByPopup; + int m_prevCursor; }; #elif wxUSE_POPUPWIN