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
|
class wxWin32FrameInputHandler : public wxStdFrameInputHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxWin32FrameInputHandler(wxInputHandler *handler)
|
wxWin32FrameInputHandler(wxInputHandler *handler);
|
||||||
: wxStdFrameInputHandler(handler), m_menuHandler(NULL) { }
|
~wxWin32FrameInputHandler();
|
||||||
|
|
||||||
virtual bool HandleMouse(wxInputConsumer *control,
|
virtual bool HandleMouse(wxInputConsumer *control,
|
||||||
const wxMouseEvent& event);
|
const wxMouseEvent& event);
|
||||||
@@ -4350,6 +4350,108 @@ bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
|
|||||||
// wxWin32FrameInputHandler
|
// 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,
|
bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
|
||||||
const wxMouseEvent& event)
|
const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
@@ -4417,104 +4519,17 @@ void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
|
|||||||
delete menu;
|
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 wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
|
||||||
bool activated)
|
bool activated)
|
||||||
{
|
{
|
||||||
if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
|
if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
|
||||||
{
|
{
|
||||||
if ( !activated && m_menuHandler )
|
// always detach if active frame changed:
|
||||||
{
|
m_menuHandler->Detach();
|
||||||
m_menuHandler->RemoveSelf();
|
|
||||||
wxDELETE(m_menuHandler);
|
|
||||||
}
|
|
||||||
else if ( activated )
|
|
||||||
{
|
|
||||||
if ( m_menuHandler )
|
|
||||||
{
|
|
||||||
m_menuHandler->RemoveSelf();
|
|
||||||
delete m_menuHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_menuHandler = new wxWin32SystemMenuEvtHandler(this, consumer);
|
if ( activated )
|
||||||
|
{
|
||||||
|
m_menuHandler->Attach(consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user