How to show a menu in a GtkWindow

I created a program displaying a menu. Everything works, if I use a GtkApplicationWindow. However, I can’t get it to work using a GtkWindow.

If I use a GtkApplicationWindow, a menu is shown

  GtkWindow *window = GTK_WINDOW (gtk_application_window_new (app));

If I use a GtkWindow, no menu is shown.

  GtkWindow *window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
  gtk_window_set_application (window, app);
  gtk_application_add_window (app, window);

Q: How do I make a menu available in GtkWindows?

Full example code

#include <gtk/gtk.h>
#include <stdio.h>

static void
menu_item_clicked (GSimpleAction *action,
                   GVariant      *parameter,
                   gpointer       gtk_application)
{
  g_print ("Menu item clicked\n");
}


static void
create_menu (GtkWindow      * window,
             GtkApplication * app)
{

  GMenu * menubar = g_menu_new();

  // Create one menu button
  {
    GMenuItem * menu_button = g_menu_item_new ("_App", "unused");
    // set callback
    //g_menu_item_set_attribute (menu_button,"submenu-action", "&s",
    //                            "app.menu_edit_clicked", NULL);
    GMenu * menu_content = g_menu_new();
    {
      g_menu_append (menu_content, "Action_1" ,   "app.action1"  );
      g_menu_append (menu_content, "Action_2" ,   "app.action2"  );
    }

    // create "on-click" event
    {
      // insert the content of menu
      g_menu_item_set_submenu (menu_button, G_MENU_MODEL (menu_content));
      // add it to menubar
      g_menu_append_item (menubar, menu_button);
    }
  }

  gtk_application_set_menubar (app, G_MENU_MODEL (menubar));
  g_object_unref (menubar);


  // Set menu actions
  {
    GActionEntry actions[] = {
      {.name="action1",  .activate=menu_item_clicked, NULL, NULL, NULL },
      {.name="action2",  .activate=menu_item_clicked, NULL, NULL, NULL },
    };

    GSimpleActionGroup *action_group = g_simple_action_group_new ();
    g_action_map_add_action_entries (G_ACTION_MAP (action_group), actions, G_N_ELEMENTS (actions), NULL);
    gtk_widget_insert_action_group (GTK_WIDGET (window), "app", G_ACTION_GROUP (action_group));
  }

}



void
application_start (GApplication *_self,
                   gpointer      user_data)
{
  GtkApplication *self =  GTK_APPLICATION (_self);

  // ✔️ This works fine:
  //GtkWindow *window = GTK_WINDOW (gtk_application_window_new (self));

  // ❌ No Menu shown for a GtkWindow:
  GtkWindow *window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
  gtk_window_set_application (window, self);
  gtk_application_add_window (self, window);

  create_menu (window, self);

  gtk_widget_show_all (GTK_WIDGET (window));
}


int
main(int argc, char *argv[])
{
  gtk_init (&argc, &argv);

  GtkApplication * app = gtk_application_new("My.Test.App", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (application_start), NULL);

  int status = g_application_run(G_APPLICATION (app), argc, argv);
  g_object_unref(app);
  return status;
}


You don’t. Quoting the GtkApplicationWindow documentation:

GtkApplicationWindow is a GtkWindow subclass that offers some extra functionality for better integration with GtkApplication features. Notably, it can handle both the application menu as well as the menubar. See gtk_application_set_app_menu() and gtk_application_set_menubar().

For plain GtkWindows, you have to explicitly set up a menubar yourself (for instance with gtk_menu_bar_new_from_model())

1 Like