#include "wx/gtk/private/gtk2-compat.h"
#include "wx/gtk/private/mnemonics.h"
+// Number of currently open modal dialogs, defined in src/gtk/toplevel.cpp.
+extern int wxOpenModalDialogsCount;
+
// we use normal item but with a special id for the menu title
static const int wxGTK_TITLE_ID = -3;
static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
{
+ // See the comment about Ubuntu Unity in menuitem_activate().
+ if ( wxOpenModalDialogsCount )
+ return;
+
event.SetEventObject( menu );
wxEvtHandler* handler = menu->GetEventHandler();
wxMenuBar::~wxMenuBar()
{
- if (m_widget)
+ if (m_widget && IsAttached())
{
// Work around a probable bug in Ubuntu 12.04 which causes a warning if
// gtk_widget_destroy() is called on a wxMenuBar attached to a frame
GtkWidget* widget = m_widget;
+ m_focusWidget =
m_widget = NULL;
+ GTKDisconnect(widget);
g_object_unref(widget);
}
}
gtk_widget_destroy( menu->m_owner );
menu->m_owner = NULL;
- DetachFromFrame( menu, m_menuBarFrame );
+ if ( m_menuBarFrame )
+ DetachFromFrame( menu, m_menuBarFrame );
return menu;
}
if (!item->IsEnabled())
return;
+ // Unity hack: under Ubuntu Unity the global menu bar is not affected by a
+ // modal dialog being shown, so the user can select a menu item before
+ // hiding the dialog and, in particular, a new instance of the same dialog
+ // can be shown again, breaking a lot of programs not expecting this.
+ //
+ // So explicitly ignore any menu events generated while any modal dialogs
+ // are opened.
+ if ( wxOpenModalDialogsCount )
+ return;
+
int id = item->GetId();
if (id == wxGTK_TITLE_ID)
{
// "hide" from m_menu
static void menu_hide(GtkWidget*, wxMenu* menu)
{
+ // When using Ubuntu Unity desktop environment we get "hide" signal even
+ // when the window is not shown yet because Unity hides all the menus to
+ // show them only in the global menu bar. Just ignore this even instead of
+ // crashing in DoCommonMenuCallbackCode().
+ if ( !menu->GetWindow() )
+ return;
+
wxMenuEvent event(wxEVT_MENU_CLOSE, menu->m_popupShown ? -1 : 0, menu);
menu->m_popupShown = false;
DoCommonMenuCallbackCode(menu, event);
// Destroying a menu generates a "hide" signal even if it's not shown
// currently, so disconnect it to avoid dummy wxEVT_MENU_CLOSE events
// generation.
- g_signal_handlers_disconnect_by_func(m_menu, (gpointer)menu_hide, this);
+ g_signal_handlers_disconnect_matched(m_menu,
+ GSignalMatchType(G_SIGNAL_MATCH_DATA), 0, 0, NULL, NULL, this);
// see wxMenu::Init
g_object_unref(m_menu);
return NULL;
GtkWidget * const mitem = item->GetMenuItem();
+
+ g_signal_handlers_disconnect_matched(mitem,
+ GSignalMatchType(G_SIGNAL_MATCH_DATA), 0, 0, NULL, NULL, item);
+
#ifdef __WXGTK3__
gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), NULL);
#else
case wx: \
return gtk;
- #if GTK_CHECK_VERSION(2,6,0)
- #define STOCKITEM_26(wx,gtk) STOCKITEM(wx,gtk)
- #else
- #define STOCKITEM_26(wx,gtk)
- #endif
-
#if GTK_CHECK_VERSION(2,8,0)
#define STOCKITEM_28(wx,gtk) STOCKITEM(wx,gtk)
#else
switch (id)
{
- STOCKITEM_26(wxID_ABOUT, GTK_STOCK_ABOUT)
+ STOCKITEM(wxID_ABOUT, GTK_STOCK_ABOUT)
STOCKITEM(wxID_ADD, GTK_STOCK_ADD)
STOCKITEM(wxID_APPLY, GTK_STOCK_APPLY)
STOCKITEM(wxID_BACKWARD, GTK_STOCK_GO_BACK)
STOCKITEM(wxID_CUT, GTK_STOCK_CUT)
STOCKITEM(wxID_DELETE, GTK_STOCK_DELETE)
STOCKITEM(wxID_DOWN, GTK_STOCK_GO_DOWN)
- STOCKITEM_26(wxID_EDIT, GTK_STOCK_EDIT)
+ STOCKITEM(wxID_EDIT, GTK_STOCK_EDIT)
STOCKITEM(wxID_EXECUTE, GTK_STOCK_EXECUTE)
STOCKITEM(wxID_EXIT, GTK_STOCK_QUIT)
- STOCKITEM_26(wxID_FILE, GTK_STOCK_FILE)
+ STOCKITEM(wxID_FILE, GTK_STOCK_FILE)
STOCKITEM(wxID_FIND, GTK_STOCK_FIND)
STOCKITEM(wxID_FIRST, GTK_STOCK_GOTO_FIRST)
STOCKITEM(wxID_FLOPPY, GTK_STOCK_FLOPPY)