]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/menu.cpp
workaround, see #14856
[wxWidgets.git] / src / gtk / menu.cpp
index f0b8b6ff9e5452a85a90bd7ba73c2595a3a41e3a..fe3a0c1d68a7caddfa379e7b0514da6aeb1c4fdf 100644 (file)
@@ -30,6 +30,9 @@
 #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;
 
@@ -45,6 +48,10 @@ static void wxGetGtkAccel(const wxMenuItem*, guint*, GdkModifierType*);
 
 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();
@@ -63,12 +70,14 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
 
 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);
     }
 }
@@ -478,6 +487,16 @@ static void menuitem_activate(GtkWidget*, wxMenuItem* item)
     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)
     {
@@ -747,7 +766,8 @@ wxMenu::~wxMenu()
     // 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);
@@ -910,6 +930,10 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
         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