fix to segfault in system menu code
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14672 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -602,8 +602,8 @@ class wxWin32SystemMenuEvtHandler;
|
||||
class wxWin32FrameInputHandler : public wxStdFrameInputHandler
|
||||
{
|
||||
public:
|
||||
wxWin32FrameInputHandler(wxInputHandler *handler)
|
||||
: wxStdFrameInputHandler(handler), m_menuHandler(NULL) { }
|
||||
wxWin32FrameInputHandler(wxInputHandler *handler);
|
||||
~wxWin32FrameInputHandler();
|
||||
|
||||
virtual bool HandleMouse(wxInputConsumer *control,
|
||||
const wxMouseEvent& event);
|
||||
@@ -4350,6 +4350,108 @@ bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
|
||||
// wxWin32FrameInputHandler
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxWin32SystemMenuEvtHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
|
||||
|
||||
void Attach(wxInputConsumer *consumer);
|
||||
void Detach();
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
void OnSystemMenu(wxCommandEvent &event);
|
||||
void OnCloseFrame(wxCommandEvent &event);
|
||||
void OnClose(wxCloseEvent &event);
|
||||
|
||||
wxWin32FrameInputHandler *m_inputHnd;
|
||||
wxTopLevelWindow *m_wnd;
|
||||
wxAcceleratorTable m_oldAccelTable;
|
||||
};
|
||||
|
||||
wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
|
||||
wxWin32FrameInputHandler *handler)
|
||||
{
|
||||
m_inputHnd = handler;
|
||||
m_wnd = NULL;
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
|
||||
{
|
||||
wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") );
|
||||
|
||||
m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
|
||||
m_wnd->PushEventHandler(this);
|
||||
|
||||
// VS: This code relies on using generic implementation of
|
||||
// wxAcceleratorTable in wxUniv!
|
||||
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
|
||||
m_oldAccelTable = table;
|
||||
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
|
||||
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
|
||||
m_wnd->SetAcceleratorTable(table);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::Detach()
|
||||
{
|
||||
if ( m_wnd )
|
||||
{
|
||||
m_wnd->SetAcceleratorTable(m_oldAccelTable);
|
||||
m_wnd->RemoveEventHandler(this);
|
||||
m_wnd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
|
||||
EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
|
||||
EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
|
||||
EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
|
||||
{
|
||||
int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
|
||||
!m_wnd->IsMaximized()) ?
|
||||
RESIZEABLE_FRAME_BORDER_THICKNESS :
|
||||
FRAME_BORDER_THICKNESS;
|
||||
wxPoint pt = m_wnd->GetClientAreaOrigin();
|
||||
pt.x = -pt.x + border;
|
||||
pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
|
||||
|
||||
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
|
||||
m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
|
||||
m_inputHnd->PopupSystemMenu(m_wnd, pt);
|
||||
m_wnd->SetAcceleratorTable(table);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
|
||||
{
|
||||
m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
|
||||
wxTOPLEVEL_BUTTON_CLOSE);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
|
||||
{
|
||||
m_wnd = NULL;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
|
||||
: wxStdFrameInputHandler(handler)
|
||||
{
|
||||
m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
|
||||
}
|
||||
|
||||
wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
|
||||
{
|
||||
if ( m_menuHandler )
|
||||
{
|
||||
m_menuHandler->Detach();
|
||||
delete m_menuHandler;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
|
||||
const wxMouseEvent& event)
|
||||
{
|
||||
@@ -4417,104 +4519,17 @@ void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
|
||||
delete menu;
|
||||
}
|
||||
|
||||
class wxWin32SystemMenuEvtHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler,
|
||||
wxInputConsumer *consumer);
|
||||
void RemoveSelf();
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
void OnSystemMenu(wxCommandEvent &event);
|
||||
void OnCloseFrame(wxCommandEvent &event);
|
||||
void OnClose(wxCloseEvent &event);
|
||||
|
||||
wxWin32FrameInputHandler *m_inputHnd;
|
||||
wxTopLevelWindow *m_wnd;
|
||||
wxAcceleratorTable m_oldAccelTable;
|
||||
};
|
||||
|
||||
wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
|
||||
wxWin32FrameInputHandler *handler,
|
||||
wxInputConsumer *consumer)
|
||||
{
|
||||
m_inputHnd = handler;
|
||||
m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
|
||||
m_wnd->PushEventHandler(this);
|
||||
|
||||
// VS: This code relies on using generic implementation of
|
||||
// wxAcceleratorTable in wxUniv!
|
||||
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
|
||||
m_oldAccelTable = table;
|
||||
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
|
||||
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
|
||||
m_wnd->SetAcceleratorTable(table);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::RemoveSelf()
|
||||
{
|
||||
if ( m_wnd )
|
||||
{
|
||||
m_wnd->SetAcceleratorTable(m_oldAccelTable);
|
||||
m_wnd->RemoveEventHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
|
||||
EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
|
||||
EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
|
||||
EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
|
||||
{
|
||||
int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
|
||||
!m_wnd->IsMaximized()) ?
|
||||
RESIZEABLE_FRAME_BORDER_THICKNESS :
|
||||
FRAME_BORDER_THICKNESS;
|
||||
wxPoint pt = m_wnd->GetClientAreaOrigin();
|
||||
pt.x = -pt.x + border;
|
||||
pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
|
||||
|
||||
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
|
||||
m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
|
||||
m_inputHnd->PopupSystemMenu(m_wnd, pt);
|
||||
m_wnd->SetAcceleratorTable(table);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
|
||||
{
|
||||
m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
|
||||
wxTOPLEVEL_BUTTON_CLOSE);
|
||||
}
|
||||
|
||||
void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
|
||||
{
|
||||
m_wnd = NULL;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
|
||||
bool activated)
|
||||
{
|
||||
if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
|
||||
{
|
||||
if ( !activated && m_menuHandler )
|
||||
{
|
||||
m_menuHandler->RemoveSelf();
|
||||
wxDELETE(m_menuHandler);
|
||||
}
|
||||
else if ( activated )
|
||||
{
|
||||
if ( m_menuHandler )
|
||||
{
|
||||
m_menuHandler->RemoveSelf();
|
||||
delete m_menuHandler;
|
||||
}
|
||||
// always detach if active frame changed:
|
||||
m_menuHandler->Detach();
|
||||
|
||||
m_menuHandler = new wxWin32SystemMenuEvtHandler(this, consumer);
|
||||
if ( activated )
|
||||
{
|
||||
m_menuHandler->Attach(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user