From 6abf7b639c8f6827c7784d5707ea4733a375d4eb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Apr 2010 15:08:00 +0000 Subject: [PATCH] Don't use invoking window in wxGTK wxMenuBar implementation. wxGTK wxMenuBar used its own SetInvokingWindow/UnsetInvokingWindow() and related functions instead of reusing the base class Attach/Detach() which exist for exactly the same purpose. This resulted in unnecessary code duplication and confusion and, since the changes of r64104, resulted in asserts due to use of SetInvokingWindow() for non-popup menus. Fix this by removing the wxGTK-specific functions and doing the work they used to do in (now overridden) Attach() and Detach(). Also call Attach/Detach() instead of these functions from wxGTK wxFrame and wxMDIParentFrame code. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64127 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/menu.h | 7 ++-- src/gtk/frame.cpp | 4 --- src/gtk/mdi.cpp | 16 ++++++--- src/gtk/menu.cpp | 80 ++++++++++++++++++------------------------- 4 files changed, 47 insertions(+), 60 deletions(-) diff --git a/include/wx/gtk/menu.h b/include/wx/gtk/menu.h index 80e6156acc..06eaca1e54 100644 --- a/include/wx/gtk/menu.h +++ b/include/wx/gtk/menu.h @@ -43,19 +43,16 @@ public: // window virtual bool GTKNeedsParent() const { return false; } - void Attach(wxFrame *frame); + virtual void Attach(wxFrame *frame); + virtual void Detach(); // implementation only from now on - void SetInvokingWindow( wxWindow *win ); - void UnsetInvokingWindow( wxWindow *win ); GtkWidget *m_menubar; // Public for hildon support private: // common part of Append and Insert bool GtkAppend(wxMenu *menu, const wxString& title, int pos=-1); - wxWindow *m_invokingWindow; - void Init(size_t n, wxMenu *menus[], const wxString titles[], long style); DECLARE_DYNAMIC_CLASS(wxMenuBar) diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp index bcb72003fe..05635a131e 100644 --- a/src/gtk/frame.cpp +++ b/src/gtk/frame.cpp @@ -281,8 +281,6 @@ void wxFrame::DetachMenuBar() #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 hildon_window_set_menu(HILDON_WINDOW(m_widget), NULL); #else // !wxUSE_LIBHILDON && !wxUSE_LIBHILDON2 - m_frameMenuBar->UnsetInvokingWindow( this ); - gtk_widget_ref( m_frameMenuBar->m_widget ); gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget ); @@ -305,8 +303,6 @@ void wxFrame::AttachMenuBar( wxMenuBar *menuBar ) hildon_window_set_menu(HILDON_WINDOW(m_widget), GTK_MENU(m_frameMenuBar->m_menubar)); #else // !wxUSE_LIBHILDON && !wxUSE_LIBHILDON2 - m_frameMenuBar->SetInvokingWindow( this ); - m_frameMenuBar->SetParent(this); // menubar goes into top of vbox (m_mainWidget) diff --git a/src/gtk/mdi.cpp b/src/gtk/mdi.cpp index 9778056ad3..1a3c3f570d 100644 --- a/src/gtk/mdi.cpp +++ b/src/gtk/mdi.cpp @@ -123,7 +123,7 @@ void wxMDIParentFrame::OnInternalIdle() wxMenuBar *menu_bar = active_child_frame->m_menuBar; if (menu_bar) { - menu_bar->SetInvokingWindow(active_child_frame); + menu_bar->Attach(active_child_frame); } } m_justInserted = false; @@ -149,7 +149,13 @@ void wxMDIParentFrame::OnInternalIdle() { if (menu_bar->Show(true)) { - menu_bar->SetInvokingWindow( child_frame ); + // Attach() asserts if we call it for an already + // attached menu bar so don't do it if we're already + // associated with this frame (it would be nice to get + // rid of this check and ensure that this doesn't + // happen...) + if ( menu_bar->GetFrame() != child_frame ) + menu_bar->Attach( child_frame ); } visible_child_menu = true; } @@ -157,7 +163,7 @@ void wxMDIParentFrame::OnInternalIdle() { if (menu_bar->Show(false)) { - menu_bar->UnsetInvokingWindow( child_frame ); + menu_bar->Detach(); } } } @@ -173,12 +179,12 @@ void wxMDIParentFrame::OnInternalIdle() if (visible_child_menu) { m_frameMenuBar->Show( false ); - m_frameMenuBar->UnsetInvokingWindow( this ); + m_frameMenuBar->Detach(); } else { m_frameMenuBar->Show( true ); - m_frameMenuBar->SetInvokingWindow( this ); + m_frameMenuBar->Attach( this ); } } } diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 55fc27dbca..53869105fb 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -48,9 +48,10 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event) if (handler && handler->SafelyProcessEvent(event)) return; - wxWindow *win = menu->GetInvokingWindow(); - if (win) - win->HandleWindowEvent( event ); + wxWindow *win = menu->GetWindow(); + wxCHECK_RET( win, "event for a menu without associated window?" ); + + win->HandleWindowEvent( event ); } //----------------------------------------------------------------------------- @@ -61,8 +62,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow) void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long style) { - m_invokingWindow = NULL; - #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 // Hildon window uses a single menu instead of a menu bar, so wxMenuBar is // the same as menu in this case @@ -115,16 +114,20 @@ wxMenuBar::wxMenuBar() Init(0, NULL, NULL, 0); } -static void -wxMenubarUnsetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) +// recursive helpers for wxMenuBar::Attach() and Detach(): they are called to +// associate the menus with the frame they belong to or dissociate them from it +namespace { - menu->SetInvokingWindow( NULL ); +void +DetachFromFrame(wxMenu* menu, wxFrame* frame) +{ // support for native hot keys if (menu->m_accel) { - if (tlw == NULL) - tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget); + // Note that wxGetTopLevelParent() is really needed because this frame + // can be an MDI child frame which is a fake frame and not a TLW at all + GtkWindow * const tlw = GTK_WINDOW(wxGetTopLevelParent(frame)->m_widget); if (g_slist_find(menu->m_accel->acceleratables, tlw)) gtk_window_remove_accel_group(tlw, menu->m_accel); } @@ -134,21 +137,18 @@ wxMenubarUnsetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) { wxMenuItem *menuitem = node->GetData(); if (menuitem->IsSubMenu()) - wxMenubarUnsetInvokingWindow(menuitem->GetSubMenu(), win, tlw); + DetachFromFrame(menuitem->GetSubMenu(), frame); node = node->GetNext(); } } -static void -wxMenubarSetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) +void +AttachToFrame(wxMenu* menu, wxFrame* frame) { - menu->SetInvokingWindow( win ); - // support for native hot keys if (menu->m_accel) { - if (tlw == NULL) - tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget); + GtkWindow * const tlw = GTK_WINDOW(wxGetTopLevelParent(frame)->m_widget); if (!g_slist_find(menu->m_accel->acceleratables, tlw)) gtk_window_add_accel_group(tlw, menu->m_accel); } @@ -158,23 +158,12 @@ wxMenubarSetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) { wxMenuItem *menuitem = node->GetData(); if (menuitem->IsSubMenu()) - wxMenubarSetInvokingWindow(menuitem->GetSubMenu(), win, tlw); + AttachToFrame(menuitem->GetSubMenu(), frame); node = node->GetNext(); } } -void wxMenuBar::SetInvokingWindow( wxWindow *win ) -{ - m_invokingWindow = win; - - wxMenuList::compatibility_iterator node = m_menus.GetFirst(); - while (node) - { - wxMenu *menu = node->GetData(); - wxMenubarSetInvokingWindow( menu, win ); - node = node->GetNext(); - } -} +} // anonymous namespace void wxMenuBar::SetLayoutDirection(wxLayoutDirection dir) { @@ -217,20 +206,28 @@ void wxMenuBar::Attach(wxFrame *frame) { wxMenuBarBase::Attach(frame); + wxMenuList::compatibility_iterator node = m_menus.GetFirst(); + while (node) + { + wxMenu *menu = node->GetData(); + AttachToFrame( menu, frame ); + node = node->GetNext(); + } + SetLayoutDirection(wxLayout_Default); } -void wxMenuBar::UnsetInvokingWindow( wxWindow *win ) +void wxMenuBar::Detach() { - m_invokingWindow = NULL; - wxMenuList::compatibility_iterator node = m_menus.GetFirst(); while (node) { wxMenu *menu = node->GetData(); - wxMenubarUnsetInvokingWindow( menu, win ); + DetachFromFrame( menu, m_menuBarFrame ); node = node->GetNext(); } + + wxMenuBarBase::Detach(); } bool wxMenuBar::Append( wxMenu *menu, const wxString &title ) @@ -285,10 +282,8 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos) else gtk_menu_shell_insert( GTK_MENU_SHELL(m_menubar), menu->m_owner, pos ); - // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables - // addings menu later on. - if (m_invokingWindow) - wxMenubarSetInvokingWindow( menu, m_invokingWindow ); + if ( m_menuBarFrame ) + AttachToFrame( menu, m_menuBarFrame ); return true; } @@ -331,8 +326,7 @@ wxMenu *wxMenuBar::Remove(size_t pos) gtk_widget_destroy( menu->m_owner ); menu->m_owner = NULL; - if (m_invokingWindow) - wxMenubarUnsetInvokingWindow( menu, m_invokingWindow ); + DetachFromFrame( menu, m_menuBarFrame ); return menu; } @@ -812,12 +806,6 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos) gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), mitem->GetSubMenu()->m_menu ); gtk_widget_show( mitem->GetSubMenu()->m_menu ); - - // if adding a submenu to a menu already existing in the menu bar, we - // must set invoking window to allow processing events from this - // submenu - if ( m_invokingWindow ) - wxMenubarSetInvokingWindow(mitem->GetSubMenu(), m_invokingWindow); } else { -- 2.45.2