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

Reply via email to