Ok,
I was working on understanding the issue, indeed with the debug symbols installed GDB is working as you describe @dboles, so thanks for the idea !
And I figured that it could actually be a GTK bug.
I noticed that the gtk_popover_menu_bar_add_child()
function was calling the gtk_popover_menu_add_child()
function as many times as the number of menu items in the upper (top) level of the menu bar. Then I realised that it might not call it for lower levels of the menu. And that is actually the case.
What do you think ?
Here is an example code that demonstrates the behaviour:
#include <gtk/gtk.h>
GtkApplication * TestApp = NULL;
void menu_bar_action (GSimpleAction * action, GVariant * parameter, gpointer data)
{
gchar * name = g_strdup_printf ("%s", g_action_get_name(G_ACTION(action)));
if (g_strcmp0 (name, "quit") == 0)
{
g_application_quit (G_APPLICATION(TestApp));
}
}
GMenuItem * create_gmenu_item (const gchar * label, const gchar * action, const gchar * custom)
{
GMenuItem * item;
item = g_menu_item_new (label, action);
g_menu_item_set_attribute (item, "use-markup", "s", "TRUE", NULL);
// Setting custom here:
if (custom)
{
g_menu_item_set_attribute (item, "custom", "s", custom, NULL);
/* Checking custom value: */
GVariant * cust = g_menu_item_get_attribute_value (item, "custom", g_variant_type_new("s"));
if (cust) g_print ("item is:: %s, custom is:: %s\n", label, g_variant_get_string (cust, NULL));
}
return item;
}
void append_menu_item (GMenu * menu, const gchar * label, const gchar * action, const gchar * custom)
{
GMenuItem * item = create_gmenu_item (label, action, custom);
g_menu_append_item (menu, item);
g_object_unref (item);
}
GMenu * second_level_menu ()
{
GMenu * menu = g_menu_new ();
append_menu_item (menu, "Level 2: C(H)<sub>2</sub>", "None", "CH2-2");
append_menu_item (menu, "Level 2: C(H)<sub>3</sub>", "None", NULL);
append_menu_item (menu, "Level 2: C(H)<sub>4</sub>", "None", NULL);
return menu;
}
void run_program (GApplication * app, gpointer data)
{
GtkWidget * window = gtk_application_window_new (GTK_APPLICATION(app));
gtk_window_set_title (GTK_WINDOW(window), "Test");
gtk_window_set_resizable (GTK_WINDOW(window), TRUE);
gtk_widget_set_size_request (window, 900, 450);
GMenu * menubar = g_menu_new ();
GMenu * menu = g_menu_new ();
// Trying different things just in case:
append_menu_item (menu, "C(H)<sub>2</sub>", "None", "CH2");
append_menu_item (menu, "C(H)<sub>3</sub>", "None", NULL);
append_menu_item (menu, "C(H)<sub>4</sub>", "None", NULL);
g_menu_append_submenu (menu, "Second level", (GMenuModel*)second_level_menu());
append_menu_item (menu, "Quit", "app.quit", NULL);
g_menu_append_submenu (menubar, "First level", G_MENU_MODEL (menu));
g_object_unref (menu);
GtkWidget * menu_bar = gtk_popover_menu_bar_new_from_model (G_MENU_MODEL(menubar));
// Adding a widget at custom 'CH2', this is working
gtk_popover_menu_bar_add_child ((GtkPopoverMenuBar *)menu_bar, gtk_label_new("Level 1: Custom CH2"), "CH2");
// Adding a widget at custom 'CH2-2' second level, this is not working
gtk_popover_menu_bar_add_child ((GtkPopoverMenuBar *)menu_bar, gtk_label_new("Level 2: Custom CH2"), "CH2-2");
GtkWidget * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child ((GtkWindow *)window, vbox);
GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append (GTK_BOX(vbox), hbox);
gtk_box_append (GTK_BOX(hbox), menu_bar);
gtk_widget_show (menu_bar);
GSimpleAction * act = g_simple_action_new ("quit", NULL);
g_signal_connect (act, "activate", G_CALLBACK(menu_bar_action), NULL);
g_action_map_add_action (G_ACTION_MAP(GTK_APPLICATION(app)), G_ACTION(act));
//gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW(window), TRUE);
gtk_window_present (GTK_WINDOW(window));
}
int main (int argc, char *argv[])
{
// setlocale(LC_ALL,"en_US");
gtk_disable_setlocale ();
#if GLIB_MINOR_VERSION < 74
TestApp = gtk_application_new (g_strdup_printf ("test._%d.gtk", (int)clock()), G_APPLICATION_FLAGS_NONE);
#else
TestApp = gtk_application_new (g_strdup_printf ("test._%d.gtk", (int)clock()), G_APPLICATION_DEFAULT_FLAGS);
#endif
g_signal_connect (G_OBJECT(TestApp), "activate", G_CALLBACK(run_program), NULL);
int status = g_application_run (G_APPLICATION (TestApp), 0, NULL);
g_object_unref (TestApp);
return status;
}