X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5e6f2fe9210327222ff2e244d2722a0d3641109a..04ee05f92add0ab92ce08ecb827e3be41336aa06:/src/gtk/menu.cpp diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index e0f55864f5..133442129f 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -27,16 +27,6 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/mnemonics.h" -// FIXME: is this right? somehow I don't think so (VZ) - -#define gtk_accel_group_attach(g, o) gtk_window_add_accel_group((o), (g)) -#define gtk_accel_group_detach(g, o) gtk_window_remove_accel_group((o), (g)) -//#define gtk_menu_ensure_uline_accel_group(m) gtk_menu_get_accel_group(m) - -#define ACCEL_OBJECT GtkWindow -#define ACCEL_OBJECTS(a) (a)->acceleratables -#define ACCEL_OBJ_CAST(obj) ((GtkWindow*) obj) - // we use normal item but with a special id for the menu title static const int wxGTK_TITLE_ID = -3; @@ -46,11 +36,8 @@ extern "C" static void gtk_menu_clicked_callback(GtkWidget *widget, wxMenu *menu); } -//----------------------------------------------------------------------------- -// idle system -//----------------------------------------------------------------------------- - #if wxUSE_ACCEL +static bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key); static wxString GetGtkHotKey( const wxMenuItem& item ); #endif @@ -63,12 +50,12 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event) event.SetEventObject( menu ); wxEvtHandler* handler = menu->GetEventHandler(); - if (handler && handler->ProcessEvent(event)) + if (handler && handler->SafelyProcessEvent(event)) return; wxWindow *win = menu->GetInvokingWindow(); if (win) - win->GetEventHandler()->ProcessEvent( event ); + win->HandleWindowEvent( event ); } extern "C" { @@ -105,7 +92,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow) void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long style) { - m_style = style; m_invokingWindow = NULL; #if wxUSE_LIBHILDON @@ -169,48 +155,50 @@ wxMenuBar::~wxMenuBar() { } -static void wxMenubarUnsetInvokingWindow( wxMenu *menu, wxWindow *win ) +static void +wxMenubarUnsetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) { menu->SetInvokingWindow( (wxWindow*) NULL ); - wxWindow *top_frame = win; - while (top_frame->GetParent() && !(top_frame->IsTopLevel())) - top_frame = top_frame->GetParent(); - // support for native hot keys - ACCEL_OBJECT *obj = ACCEL_OBJ_CAST(top_frame->m_widget); - if ( menu->m_accel && g_slist_find( ACCEL_OBJECTS(menu->m_accel), obj ) ) - gtk_accel_group_detach( menu->m_accel, obj ); + if (menu->m_accel) + { + if (tlw == NULL) + tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget); + if (g_slist_find(menu->m_accel->acceleratables, tlw)) + gtk_window_remove_accel_group(tlw, menu->m_accel); + } wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); while (node) { wxMenuItem *menuitem = node->GetData(); if (menuitem->IsSubMenu()) - wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu(), win ); + wxMenubarUnsetInvokingWindow(menuitem->GetSubMenu(), win, tlw); node = node->GetNext(); } } -static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win ) +static void +wxMenubarSetInvokingWindow(wxMenu* menu, wxWindow* win, GtkWindow* tlw = NULL) { menu->SetInvokingWindow( win ); - wxWindow *top_frame = win; - while (top_frame->GetParent() && !(top_frame->IsTopLevel())) - top_frame = top_frame->GetParent(); - // support for native hot keys - ACCEL_OBJECT *obj = ACCEL_OBJ_CAST(top_frame->m_widget); - if ( !g_slist_find( ACCEL_OBJECTS(menu->m_accel), obj ) ) - gtk_accel_group_attach( menu->m_accel, obj ); + if (menu->m_accel) + { + if (tlw == NULL) + tlw = GTK_WINDOW(wxGetTopLevelParent(win)->m_widget); + if (!g_slist_find(menu->m_accel->acceleratables, tlw)) + gtk_window_add_accel_group(tlw, menu->m_accel); + } wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); while (node) { wxMenuItem *menuitem = node->GetData(); if (menuitem->IsSubMenu()) - wxMenubarSetInvokingWindow( menuitem->GetSubMenu(), win ); + wxMenubarSetInvokingWindow(menuitem->GetSubMenu(), win, tlw); node = node->GetNext(); } } @@ -218,9 +206,6 @@ static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win ) void wxMenuBar::SetInvokingWindow( wxWindow *win ) { m_invokingWindow = win; - wxWindow *top_frame = win; - while (top_frame->GetParent() && !(top_frame->IsTopLevel())) - top_frame = top_frame->GetParent(); wxMenuList::compatibility_iterator node = m_menus.GetFirst(); while (node) @@ -278,9 +263,6 @@ void wxMenuBar::Attach(wxFrame *frame) void wxMenuBar::UnsetInvokingWindow( wxWindow *win ) { m_invokingWindow = (wxWindow*) NULL; - wxWindow *top_frame = win; - while (top_frame->GetParent() && !(top_frame->IsTopLevel())) - top_frame = top_frame->GetParent(); wxMenuList::compatibility_iterator node = m_menus.GetFirst(); while (node) @@ -387,7 +369,7 @@ wxMenu *wxMenuBar::Remove(size_t pos) if ( !menu ) return (wxMenu*) NULL; - gtk_menu_item_remove_submenu( GTK_MENU_ITEM(menu->m_owner) ); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->m_owner), NULL); gtk_container_remove(GTK_CONTAINER(m_menubar), menu->m_owner); gtk_widget_destroy( menu->m_owner ); @@ -576,7 +558,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu ) if (item->IsCheckable()) commandEvent.SetInt(item->IsChecked()); - frame->GetEventHandler()->ProcessEvent(commandEvent); + frame->HandleWindowEvent(commandEvent); } else { @@ -604,11 +586,11 @@ static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu ) event.SetEventObject( menu ); wxEvtHandler* handler = menu->GetEventHandler(); - if (handler && handler->ProcessEvent(event)) + if (handler && handler->SafelyProcessEvent(event)) return; wxWindow *win = menu->GetInvokingWindow(); - if (win) win->GetEventHandler()->ProcessEvent( event ); + if (win) win->HandleWindowEvent( event ); } } @@ -630,12 +612,12 @@ static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu ) event.SetEventObject( menu ); wxEvtHandler* handler = menu->GetEventHandler(); - if (handler && handler->ProcessEvent(event)) + if (handler && handler->SafelyProcessEvent(event)) return; wxWindow *win = menu->GetInvokingWindow(); if (win) - win->GetEventHandler()->ProcessEvent( event ); + win->HandleWindowEvent( event ); } } @@ -844,7 +826,7 @@ void wxMenuItem::SetItemLabel( const wxString& str ) accel_key, accel_mods ); } -#endif // wxUSE_FILECTRL +#endif // wxUSE_ACCEL } // NOTE: this function is different from the similar functions GTKProcessMnemonics() @@ -974,7 +956,8 @@ void wxMenu::Init() m_menu = gtk_menu_new(); // NB: keep reference to the menu so that it is not destroyed behind // our back by GTK+ e.g. when it is removed from menubar: - gtk_widget_ref(m_menu); + g_object_ref(m_menu); + gtk_object_sink(GTK_OBJECT(m_menu)); m_owner = (GtkWidget*) NULL; @@ -1003,21 +986,15 @@ wxMenu::~wxMenu() if ( GTK_IS_WIDGET( m_menu )) { // see wxMenu::Init - gtk_widget_unref( m_menu ); - g_object_unref( m_accel ); + g_object_unref(m_menu); // if the menu is inserted in another menu at this time, there was // one more reference to it: if ( m_owner ) gtk_widget_destroy( m_menu ); - } - // This must come after we release GTK resources above. Otherwise, GTK will - // give warnings/errors when attempting to free accelerator resources from - // child items that just were destroyed (the m_menu widget can contain - // references to accelerators in child items. Problem detected when removing - // a menu from a wxMenuBar, and the removed menu had submenus with accelerators.) - WX_CLEAR_LIST(wxMenuItemList, m_items); + g_object_unref(m_accel); + } } void wxMenu::SetLayoutDirection(const wxLayoutDirection dir) @@ -1057,6 +1034,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos) if ( mitem->IsSeparator() ) { menuItem = gtk_separator_menu_item_new(); + m_prevRadio = NULL; } else if ( mitem->GetBitmap().Ok() || (mitem->GetKind() == wxITEM_NORMAL && isstock) ) @@ -1176,7 +1154,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos) accel_mods, GTK_ACCEL_VISIBLE); } -#endif // wxUSE_FILECTRL +#endif // wxUSE_ACCEL if (pos == -1) gtk_menu_shell_append(GTK_MENU_SHELL(m_menu), menuItem); @@ -1248,11 +1226,19 @@ wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item) wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) { if ( !wxMenuBase::DoRemove(item) ) - return (wxMenuItem *)NULL; + return NULL; + + GtkWidget * const mitem = item->GetMenuItem(); + if ( m_prevRadio == mitem ) + { + // deleting an item starts a new radio group (has to as we shouldn't + // keep a deleted pointer anyhow) + m_prevRadio = NULL; + } // TODO: this code doesn't delete the item factory item and this seems // impossible as of GTK 1.2.6. - gtk_widget_destroy( item->GetMenuItem() ); + gtk_widget_destroy( mitem ); return item; } @@ -1762,6 +1748,8 @@ const char *wxGetStockGtkID(wxWindowID id) return NULL; } +#if wxUSE_ACCEL +static bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key) { if (!id) @@ -1781,5 +1769,6 @@ bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key) return false; } +#endif // wxUSE_ACCEL #endif // wxUSE_MENUS