Iago Rubio > On Mon, 2008-01-21 at 10:47 +0100, Jerome Blondel wrote: > >> Hi >> >> If I set a menu as a submenu for a menu item, is it destroyed when I >> destroy the toplevel menu? >> > > IFAIK yes. > > When you attach a menu to a widget it's referenced with > g_object_ref_sink, so if it only has a floating reference, its ref count > is not increased but converted to a normal reference, so the container > will own the only reference to the menu. > > If you want to maintain the menu, you must increase its ref count. > Even when the ref count of the submenu is increased, the program still crashes on the second time the submenu is popped up. It seems the destruction of the container has other side-effects.
This is the code: Part 1 (in the setup code): // setup of the stars context submenu this->popup_actions = gtk_menu_new(); this->popup_action_center = gtk_menu_item_new_with_label("Center"); this->popup_action_focus = gtk_menu_item_new_with_label("Focus"); this->popup_action_info = gtk_menu_item_new_with_label("Info"); gtk_menu_shell_append(GTK_MENU_SHELL(this->popup_actions), this->popup_action_center); gtk_menu_shell_append(GTK_MENU_SHELL(this->popup_actions), this->popup_action_focus); gtk_menu_shell_append(GTK_MENU_SHELL(this->popup_actions), this->popup_action_info); g_object_set_data(G_OBJECT(this->popup_actions), "body", NULL); g_signal_connect(G_OBJECT(this->popup_action_center), "activate", G_CALLBACK(on_star_center), this); g_signal_connect(G_OBJECT(this->popup_action_focus), "activate", G_CALLBACK(on_star_focus), this); g_signal_connect(G_OBJECT(this->popup_action_info), "activate", G_CALLBACK(on_star_info), this); // don't let them be destroyed... but it doesn't work g_object_ref(this->popup_actions); Part 2 (in the right-click handler) else if (ev->button == 3) { selected_stars = s->find_stars(p, 2.0); // popup a menu if (selected_stars) { GtkWidget *stars; if (s->popup_stars) gtk_widget_destroy(GTK_WIDGET(s->popup_stars)); // setup of the submenu on the fly, fallback solution /* s->popup_actions = gtk_menu_new(); s->popup_action_center = gtk_menu_item_new_with_label("Center"); s->popup_action_focus = gtk_menu_item_new_with_label("Focus"); s->popup_action_info = gtk_menu_item_new_with_label("Info"); gtk_menu_shell_append(GTK_MENU_SHELL(s->popup_actions), s->popup_action_center); gtk_menu_shell_append(GTK_MENU_SHELL(s->popup_actions), s->popup_action_focus); gtk_menu_shell_append(GTK_MENU_SHELL(s->popup_actions), s->popup_action_info); g_object_set_data(G_OBJECT(s->popup_actions), "body", NULL); g_signal_connect(G_OBJECT(s->popup_action_center), "activate", G_CALLBACK(on_star_center), s); g_signal_connect(G_OBJECT(s->popup_action_focus), "activate", G_CALLBACK(on_star_focus), s); g_signal_connect(G_OBJECT(s->popup_action_info), "activate", G_CALLBACK(on_star_info), s); */ // setup of the menu s->popup_stars = gtk_menu_new(); for (k = selected_stars; k != NULL; k = k->next) { Body *b = static_cast<Body *>(k->data); gchar *str = b->pretty_name(); stars = gtk_menu_item_new_with_label(str); g_free(str); g_object_set_data(G_OBJECT(stars), "body", b); gtk_menu_shell_append(GTK_MENU_SHELL(s->popup_stars), stars); gtk_menu_item_set_submenu(GTK_MENU_ITEM(stars), s->popup_actions); g_signal_connect(G_OBJECT(stars), "activate", G_CALLBACK(on_star_item_activate), s); } gtk_widget_show_all(s->popup_stars); gtk_menu_popup(GTK_MENU(s->popup_stars), NULL, NULL, NULL, NULL, ev->button, ev->time); g_slist_free(selected_stars); } Here are the error messages. // first popup of the context menu with two items in it (coords:3110): Gtk-WARNING **: gtk_menu_attach_to_widget(): menu already attached to GtkMenuItem // second popup of the context menu with two items in it (coords:3110): Gtk-CRITICAL **: gtk_window_set_screen: assertion `GTK_IS_WINDOW (window)' failed (coords:3110): Gtk-WARNING **: gtk_menu_attach_to_widget(): menu already attached to GtkMenuItem // trying to popup a submenu now (coords:3110): Gtk-CRITICAL **: gtk_window_set_accept_focus: assertion `GTK_IS_WINDOW (window)' failed (coords:3110): GLib-GObject-CRITICAL **: g_type_instance_get_private: assertion `instance != NULL && instance->g_class != NULL' failed (coords:3110): Gtk-CRITICAL **: gtk_window_set_transient_for: assertion `GTK_IS_WINDOW (window)' failed Program received signal SIGSEGV, Segmentation fault. _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list