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
This commit is contained in:
Vadim Zeitlin
2010-04-24 15:08:00 +00:00
parent 7739f9c947
commit 6abf7b639c
4 changed files with 51 additions and 64 deletions

View File

@@ -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);
SetLayoutDirection(wxLayout_Default);
}
void wxMenuBar::UnsetInvokingWindow( wxWindow *win )
{
m_invokingWindow = NULL;
wxMenuList::compatibility_iterator node = m_menus.GetFirst();
while (node)
{
wxMenu *menu = node->GetData();
wxMenubarUnsetInvokingWindow( menu, win );
AttachToFrame( menu, frame );
node = node->GetNext();
}
SetLayoutDirection(wxLayout_Default);
}
void wxMenuBar::Detach()
{
wxMenuList::compatibility_iterator node = m_menus.GetFirst();
while (node)
{
wxMenu *menu = node->GetData();
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
{