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:
@@ -2010,9 +2010,14 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
wxNonOwnedWindow::Create(parent, m_nativeWin);
|
wxNonOwnedWindow::Create(parent, m_nativeWin);
|
||||||
m_stc = wxDynamicCast(parent, wxStyledTextCtrl);
|
m_stc = wxDynamicCast(parent, wxStyledTextCtrl);
|
||||||
m_isShown = false;
|
m_isShown = false;
|
||||||
|
m_cursorSetByPopup = false;
|
||||||
|
m_prevCursor = wxSTC_CURSORNORMAL;
|
||||||
|
|
||||||
Bind(wxEVT_ENTER_WINDOW, &wxSTCPopupBase::OnMouseEnter, this);
|
Bind(wxEVT_ENTER_WINDOW, &wxSTCPopupBase::OnMouseEnter, this);
|
||||||
Bind(wxEVT_LEAVE_WINDOW, &wxSTCPopupBase::OnMouseLeave, this);
|
Bind(wxEVT_LEAVE_WINDOW, &wxSTCPopupBase::OnMouseLeave, this);
|
||||||
|
|
||||||
|
if ( m_stc )
|
||||||
|
m_stc->Bind(wxEVT_DESTROY, &wxSTCPopupBase::OnParentDestroy, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSTCPopupBase::~wxSTCPopupBase()
|
wxSTCPopupBase::~wxSTCPopupBase()
|
||||||
@@ -2020,7 +2025,11 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
UnsubclassWin();
|
UnsubclassWin();
|
||||||
CloseFloatingWindow(m_nativeWin);
|
CloseFloatingWindow(m_nativeWin);
|
||||||
|
|
||||||
SetSTCCursor(wxSTC_CURSORNORMAL);
|
if ( m_stc )
|
||||||
|
{
|
||||||
|
m_stc->Unbind(wxEVT_DESTROY, &wxSTCPopupBase::OnParentDestroy,this);
|
||||||
|
RestoreSTCCursor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSTCPopupBase::Show(bool show)
|
bool wxSTCPopupBase::Show(bool show)
|
||||||
@@ -2038,7 +2047,7 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
HideFloatingWindow(m_nativeWin);
|
HideFloatingWindow(m_nativeWin);
|
||||||
SetSTCCursor(wxSTC_CURSORNORMAL);
|
RestoreSTCCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2056,7 +2065,20 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
void wxSTCPopupBase::SetSTCCursor(int cursor)
|
void wxSTCPopupBase::SetSTCCursor(int cursor)
|
||||||
{
|
{
|
||||||
if ( m_stc )
|
if ( m_stc )
|
||||||
|
{
|
||||||
|
m_cursorSetByPopup = true;
|
||||||
|
m_prevCursor = m_stc->GetSTCCursor();
|
||||||
m_stc->SetSTCCursor(cursor);
|
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))
|
void wxSTCPopupBase::OnMouseEnter(wxMouseEvent& WXUNUSED(event))
|
||||||
@@ -2066,7 +2088,12 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
|
|
||||||
void wxSTCPopupBase::OnMouseLeave(wxMouseEvent& WXUNUSED(event))
|
void wxSTCPopupBase::OnMouseLeave(wxMouseEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
SetSTCCursor(wxSTC_CURSORNORMAL);
|
RestoreSTCCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxSTCPopupBase::OnParentDestroy(wxWindowDestroyEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_stc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif wxUSE_POPUPWIN
|
#elif wxUSE_POPUPWIN
|
||||||
|
@@ -81,12 +81,16 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void DoSetSize(int, int, int, int, int) wxOVERRIDE;
|
virtual void DoSetSize(int, int, int, int, int) wxOVERRIDE;
|
||||||
void SetSTCCursor(int);
|
void SetSTCCursor(int);
|
||||||
|
void RestoreSTCCursor();
|
||||||
void OnMouseEnter(wxMouseEvent&);
|
void OnMouseEnter(wxMouseEvent&);
|
||||||
void OnMouseLeave(wxMouseEvent&);
|
void OnMouseLeave(wxMouseEvent&);
|
||||||
|
void OnParentDestroy(wxWindowDestroyEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WX_NSWindow m_nativeWin;
|
WX_NSWindow m_nativeWin;
|
||||||
wxStyledTextCtrl* m_stc;
|
wxStyledTextCtrl* m_stc;
|
||||||
|
bool m_cursorSetByPopup;
|
||||||
|
int m_prevCursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif wxUSE_POPUPWIN
|
#elif wxUSE_POPUPWIN
|
||||||
|
Reference in New Issue
Block a user