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.
This commit is contained in:
New Pagodi
2019-07-13 12:40:27 -05:00
parent d24f58cc55
commit 61d4dbc66b
2 changed files with 34 additions and 3 deletions

View File

@@ -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

View File

@@ -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