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:
Vadim Zeitlin
2002-01-25 16:02:21 +00:00
parent 74f6bbf951
commit d7cff34d1f
2 changed files with 38 additions and 14 deletions

View File

@@ -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)
}; };

View File

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