fix a crash when dismissing the popup window because of a key press
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13807 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -107,9 +107,14 @@ protected:
|
|||||||
// the window which has the focus while we're shown
|
// the window which has the focus while we're shown
|
||||||
wxWindow *m_focus;
|
wxWindow *m_focus;
|
||||||
|
|
||||||
|
// these classes may call our DismissAndNotify()
|
||||||
friend class wxPopupWindowHandler;
|
friend class wxPopupWindowHandler;
|
||||||
friend class wxPopupFocusHandler;
|
friend class wxPopupFocusHandler;
|
||||||
|
|
||||||
|
// the handlers we created, may be NULL (if not, must be deleted)
|
||||||
|
wxPopupWindowHandler *m_handlerPopup;
|
||||||
|
wxPopupFocusHandler *m_handlerFocus;
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxPopupTransientWindow)
|
DECLARE_DYNAMIC_CLASS(wxPopupTransientWindow)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// event handlers
|
// event handlers
|
||||||
void OnKillFocus(wxFocusEvent& event);
|
void OnKillFocus(wxFocusEvent& event);
|
||||||
void OnKeyUp(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxPopupTransientWindow *m_popup;
|
wxPopupTransientWindow *m_popup;
|
||||||
@@ -113,7 +113,7 @@ END_EVENT_TABLE()
|
|||||||
|
|
||||||
BEGIN_EVENT_TABLE(wxPopupFocusHandler, wxEvtHandler)
|
BEGIN_EVENT_TABLE(wxPopupFocusHandler, wxEvtHandler)
|
||||||
EVT_KILL_FOCUS(wxPopupFocusHandler::OnKillFocus)
|
EVT_KILL_FOCUS(wxPopupFocusHandler::OnKillFocus)
|
||||||
EVT_KEY_UP(wxPopupFocusHandler::OnKeyUp)
|
EVT_KEY_DOWN(wxPopupFocusHandler::OnKeyDown)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -178,6 +178,9 @@ void wxPopupTransientWindow::Init()
|
|||||||
{
|
{
|
||||||
m_child =
|
m_child =
|
||||||
m_focus = (wxWindow *)NULL;
|
m_focus = (wxWindow *)NULL;
|
||||||
|
|
||||||
|
m_handlerFocus = NULL;
|
||||||
|
m_handlerPopup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxPopupTransientWindow::wxPopupTransientWindow(wxWindow *parent, int style)
|
wxPopupTransientWindow::wxPopupTransientWindow(wxWindow *parent, int style)
|
||||||
@@ -190,20 +193,34 @@ wxPopupTransientWindow::wxPopupTransientWindow(wxWindow *parent, int style)
|
|||||||
wxPopupTransientWindow::~wxPopupTransientWindow()
|
wxPopupTransientWindow::~wxPopupTransientWindow()
|
||||||
{
|
{
|
||||||
PopHandlers();
|
PopHandlers();
|
||||||
|
|
||||||
|
delete m_handlerFocus;
|
||||||
|
delete m_handlerPopup;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxPopupTransientWindow::PopHandlers()
|
void wxPopupTransientWindow::PopHandlers()
|
||||||
{
|
{
|
||||||
if ( m_child )
|
if ( m_child )
|
||||||
{
|
{
|
||||||
m_child->PopEventHandler(TRUE /* delete it */);
|
if ( !m_child->RemoveEventHandler(m_handlerPopup) )
|
||||||
|
{
|
||||||
|
// something is very wrong and someone else probably deleted our
|
||||||
|
// handler - so don't risk deleting it second time
|
||||||
|
m_handlerPopup = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
m_child->ReleaseMouse();
|
m_child->ReleaseMouse();
|
||||||
m_child = NULL;
|
m_child = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_focus )
|
if ( m_focus )
|
||||||
{
|
{
|
||||||
m_focus->PopEventHandler(TRUE /* delete it */);
|
if ( !m_focus->RemoveEventHandler(m_handlerFocus) )
|
||||||
|
{
|
||||||
|
// see above
|
||||||
|
m_handlerFocus = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
m_focus = NULL;
|
m_focus = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,25 +241,27 @@ void wxPopupTransientWindow::Popup(wxWindow *winFocus)
|
|||||||
// first
|
// first
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
|
delete m_handlerPopup;
|
||||||
|
m_handlerPopup = new wxPopupWindowHandler(this);
|
||||||
|
|
||||||
m_child->CaptureMouse();
|
m_child->CaptureMouse();
|
||||||
m_child->PushEventHandler(new wxPopupWindowHandler(this));
|
m_child->PushEventHandler(m_handlerPopup);
|
||||||
|
|
||||||
m_focus = winFocus ? winFocus : this;
|
m_focus = winFocus ? winFocus : this;
|
||||||
m_focus->SetFocus();
|
m_focus->SetFocus();
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
// FIXME: I don't know why does this happen but sometimes SetFocus() simply
|
// MSW doesn't allow to set focus to the popup window, but we need to
|
||||||
// refuses to work under MSW - no error happens but the focus is not
|
// subclass the window which has the focus, and not winFocus passed in or
|
||||||
// given to the window, i.e. the assert below is triggered
|
// otherwise everything else breaks down
|
||||||
//
|
|
||||||
// Try work around this as we can...
|
|
||||||
|
|
||||||
//wxASSERT_MSG( FindFocus() == m_focus, _T("setting focus failed") );
|
|
||||||
m_focus = FindFocus();
|
m_focus = FindFocus();
|
||||||
if ( m_focus )
|
if ( m_focus )
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
{
|
{
|
||||||
m_focus->PushEventHandler(new wxPopupFocusHandler(this));
|
delete m_handlerFocus;
|
||||||
|
m_handlerFocus = new wxPopupFocusHandler(this);
|
||||||
|
|
||||||
|
m_focus->PushEventHandler(m_handlerFocus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +422,7 @@ void wxPopupFocusHandler::OnKillFocus(wxFocusEvent& event)
|
|||||||
m_popup->DismissAndNotify();
|
m_popup->DismissAndNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxPopupFocusHandler::OnKeyUp(wxKeyEvent& event)
|
void wxPopupFocusHandler::OnKeyDown(wxKeyEvent& event)
|
||||||
{
|
{
|
||||||
// let the window have it first, it might process the keys
|
// let the window have it first, it might process the keys
|
||||||
if ( !m_popup->ProcessEvent(event) )
|
if ( !m_popup->ProcessEvent(event) )
|
||||||
|
Reference in New Issue
Block a user