Re: Destroying a menu



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.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]