GTK3 migration to GMenu/GAction accelerator action not showing

Hi there,

I am preparing my code to GTK4, and try to get rid of GtkMenu in profit of GMenu and GAction, as the migration document recommend.

I do face a problem with accelerator/shortcuts that stay hidden in a popmenu. Whatever I do, the ‘Ctrl+T’ refuse to display.

Here is my code:


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


static void test_action_cb(GSimpleAction *action, GVariant *parameter,
                           gpointer user_data) {
    g_print("Test action activated! (Ctrl+T or menu)\n");
}

static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
 GtkMenu *menu = user_data;

    if (event->button == GDK_BUTTON_SECONDARY) {  // Right-click
        gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent *)event);
        return TRUE;
    }
    return FALSE;
}

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

    GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
    gtk_window_set_title(window, "GTK3 Context Menu Test");
    gtk_window_set_default_size(window, 400, 300);

    // Create menu with test item
    GMenu *menu = g_menu_new();
    GMenu *section = g_menu_new ();
    g_menu_append_section (menu, "Flag", G_MENU_MODEL(section));

		GMenuItem *menuitem = g_menu_item_new("Test 1", "win.test1");
		g_menu_append_item (section, menuitem);
		g_object_unref (menuitem);
		menuitem = g_menu_item_new("Test 2", "win.test2");
		g_menu_append_item (section, menuitem);
		g_object_unref (menuitem);

	g_object_unref (section);

    GtkWidget *gtkmenu = gtk_menu_new_from_model(G_MENU_MODEL(menu));

	//always attach to get sensitive gaction
	gtk_menu_attach_to_widget(GTK_MENU(gtkmenu), GTK_WIDGET(window), NULL);

    //create actiongroup
    GActionGroup *actions = (GActionGroup*)g_simple_action_group_new();
    gtk_widget_insert_action_group (GTK_WIDGET(window), "win", actions);

    //create action
    GSimpleAction *test_action = g_simple_action_new("test1", NULL);
    g_signal_connect(test_action, "activate", G_CALLBACK(test_action_cb), NULL);
    g_action_map_add_action(G_ACTION_MAP(actions), G_ACTION(test_action));


    // Add accel group for Ctrl+T
    GtkAccelGroup *accel_group = gtk_accel_group_new();
    gtk_window_add_accel_group(window, accel_group);
    gtk_accel_group_connect(accel_group, GDK_KEY_T, GDK_CONTROL_MASK,
                            GTK_ACCEL_VISIBLE,
                            g_cclosure_new_swap(G_CALLBACK(test_action_cb),
                                                test_action, NULL));

    // Connect right-click
    g_signal_connect(window, "button-press-event",
                     G_CALLBACK(on_button_press), gtkmenu);

    gtk_widget_show_all(GTK_WIDGET(window));
    gtk_main();

    return 0;
}

Thanks in advance for any help.

Maxime.

Hi,

I personally always use the menus and actions together with a GtkApplication and GtkApplicationWindow, as recommended by our tutorial (this part is compatible with gtk3).

The GtkApplicationWindow implements the actionmap interface to provide a group named win, so you don’t need to create your own one (g_simple_action_group_new in your example). Just call g_action_map_add_action() on the window instead.

Then, to map with an accelerator, use gtk_application_set_accels_for_action on the GtkApplication.

Hi,

Indeed I did this, with help of the tutorial, for some of my ‘main’ window with menubars, what works well.

Meanwhile, at present, I still have a lot a GtkDialog and GtkWindow modal, my question was more if there is a way to make this transitional GMenu/GAction work ?
Other option I have to resign will be:

  • switch all my GtkDialog/GtkWindow to GtkApplicationWindow

  • or keep GtkMenu in such untill I do effectively migrate to GTK4

Thx,
Maxime.

Also get rid of gtk_main and use gtkapplication instead. And gtkdialog is deprecated in gtk4 but using plain gtkwindow I think is fine.

Checked now and gtk_main is gone in gtk4. Gtk – 4.0: Migrating from GTK 3.x to GTK 4

In gtk4, if not working with a GtkApplication + GtkApplicationWindow, there is the possibility to add shurtcuts to specific widgets with Gtk.WidgetClass.add_binding_action . If a menu is added to the widget or its descendants, the accel will appear in the menu item.

gtk3 is a bit old for me to remember, I can’t tell if there are equivalents…