Search code examples
cgtkgtk3

Gtk3 - How to listen to accelerators via GAction in my GtkApplication?


I did not find any good example for that, and I failed to get accelerators to work with GAction.

Would be great if someone could point me on what is wrong with my code:

static void
thunar_application_cb (GtkApplication *application)
{
  printf("thunar_application_cb\n");
}

static GActionEntry actions[] = {
  { "test", thunar_application_cb, NULL, NULL, NULL },
};

void activate_main_gui(GtkApplication *app)
{
    GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_show_all (window);
    gtk_main();
}

int main( int   argc, char *argv[] )
{
    GtkApplication *app = gtk_application_new ("org.gtk.cron-asdf", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate_main_gui),NULL);

    g_action_map_add_action_entries(G_ACTION_MAP(app), actions, G_N_ELEMENTS(actions), NULL);

    const char *accels[] = {"<Ctrl>C", NULL};
    gtk_application_set_accels_for_action (app, "test", accels);

    int status = g_application_run (G_APPLICATION (app), 0, NULL);
    g_object_unref (app);
    return 0;
}

Edit:

Here the fixed example, which runs fine:

#include <gtk/gtk.h>

void callback ( GSimpleAction *action, GVariant *parameter, gpointer user_data )
{
    g_print ( "<Ctrl>C pressed\n" );
}

static GActionEntry actions[] = {
  { "test", callback, NULL, NULL, NULL },
};


static void startup ( GtkApplication *app )
{
  g_action_map_add_action_entries(G_ACTION_MAP(app), actions, G_N_ELEMENTS(actions), NULL);

  const char *accels[] = {"<Ctrl>C", NULL};
  gtk_application_set_accels_for_action (app, "app.test", accels);
}

static void activate ( GtkApplication *app )
{
    GtkWidget *window;
    window = gtk_application_window_new ( app );

    gtk_window_set_application ( GTK_WINDOW ( window ), GTK_APPLICATION ( app ) );
    gtk_window_set_title ( GTK_WINDOW ( window ), "Hello GNOME" );

    gtk_widget_show_all ( GTK_WIDGET ( window ) );
}


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

  GtkApplication *app;
  int status;

  app = gtk_application_new  ( "org.gtk.cron-asdf",G_APPLICATION_FLAGS_NONE );
  g_signal_connect_swapped   ( app, "startup",  G_CALLBACK ( startup ),  app );
  g_signal_connect_swapped   ( app, "activate", G_CALLBACK ( activate ), app );
  status = g_application_run ( G_APPLICATION ( app ), 0, NULL );
  g_object_unref ( app );
  return status;
}

Solution

  • Well if you are interested in calling that callback and later to use a Menu as well a good approach will be something like this:

    #include <gtk/gtk.h>
    
    void open_file_callback ( GSimpleAction *action, GVariant *parameter, gpointer user_data );
    
    static void startup ( GtkApplication *app )
    {
        GMenu *menu;
        GSimpleAction *open_action;
        GActionMap *action_map;
        const gchar *const open_accels[] = { "<Ctrl>O", NULL };
    
        /// ***
        menu = g_menu_new ();
        open_action = g_simple_action_new ( "open", NULL);
        g_signal_connect( open_action, "activate", G_CALLBACK ( open_file_callback ),  NULL );
    
        /// ***
        action_map = G_ACTION_MAP ( app );
        g_action_map_add_action ( action_map, G_ACTION ( open_action ) );
        g_menu_append ( menu, "Open", "app.open");
    
        /// ***
        gtk_application_set_accels_for_action ( GTK_APPLICATION ( app ), "app.open", open_accels );
        gtk_application_set_app_menu    ( app, G_MENU_MODEL ( menu ) );
        /// ***
        g_object_unref ( menu );
    }
    
    static void activate ( GtkApplication *app )
    {
        GtkWidget *window;
        window = gtk_application_window_new ( app );
    
        gtk_window_set_application ( GTK_WINDOW ( window ), GTK_APPLICATION ( app ) );
        gtk_window_set_title ( GTK_WINDOW ( window ), "Hello GNOME" );
    
        gtk_widget_show_all ( GTK_WIDGET ( window ) );
    }
    
    int main ( void )
    {
        GtkApplication *app;
        int status;
    
        app = gtk_application_new  ( "org.gtk.cron-asdf",G_APPLICATION_FLAGS_NONE );
        g_signal_connect_swapped   ( app, "startup",  G_CALLBACK ( startup ),  app );
        g_signal_connect_swapped   ( app, "activate", G_CALLBACK ( activate ), app );
        status = g_application_run ( G_APPLICATION ( app ), 0, NULL );
        g_object_unref ( app );
        return status;
    }
    
    void open_file_callback ( GSimpleAction *action, GVariant *parameter, gpointer user_data )
    {
        ( void )action;
        ( void )parameter;
        ( void )user_data;
        g_print ( "Open File.\n" );
    }