From 2279b45ad97be45fc59105ac5ec54735d06bfa6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Sun, 17 Mar 2002 21:44:59 +0000 Subject: [PATCH] fix to segfault in system menu code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14672 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/univ/themes/win32.cpp | 203 ++++++++++++++++++++------------------ 1 file changed, 109 insertions(+), 94 deletions(-) diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index ec3d13ca87..ca0b2fd4bc 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -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); } }