Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code cannot exit from GTK application - apparently no message loops

Tags:

c

gtk

I'm trying to figure out how to get a GTK application to exit automatically after a certain time.

So I have a callback function which is meant to shutdown the application:

static gboolean killOffApp (gpointer userData) {
    gtk_main_quit ();
    return FALSE;
}

Then, in the activate signal handler, I start the five-second timer:

static void activate (GtkApplication* app, gpointer user_data) {
    GtkWidget *window = gtk_application_window_new (app);
    g_timeout_add_seconds (5, killOffApp, NULL);
    gtk_widget_show_all (window);
}

And, for completeness, here is the main that attaches the signal handler and runs the GTK application:

int main (int argc, char **argv) {
    GtkApplication *app = gtk_application_new ("com.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    int status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;
}

My problem is that, when the timer fires, the call to gtk_main_quit appears to be invalid and I'm not sure why:

(MyProg:776): Gtk-CRITICAL **: gtk_main_quit: assertion 'main_loops != NULL' failed

I've researched the problem on the web but only found stuff where either:

  • it's done from a part of the code where there is an inner loop running (such as in a dialog) so it shuts down that one rather than the main loop (not the case here, I believe); or
  • there's no loop running since, for example, the application was run with the one-shot gtk_main_iteration_do (I don't think that's the case here either).

I'm obviously doing something wrong, why does my application appear not to have a message loop running?

like image 845
paxdiablo Avatar asked Apr 28 '16 04:04

paxdiablo


1 Answers

The gtk_main_quit function appears not to be suitable when using GtkApplication. From someone who has been involved in the development of various Gnome projects, one Emmanuele Bassi commented elsewhere (slightly paraphrased and noting in particular the second paragraph):

If you're calling g_application_run() then you don't need to call gtk_main() as well: the run() method will spin the main loop for you.

You also don't use gtk_main_quit() to stop the application's main loop: you should use g_application_quit() instead.


With that in mind, you need to pass the application to the callback, and call the application quit function with it:

static void activate (GtkApplication* app, gpointer user_data) {
    GtkWidget *window = gtk_application_window_new (app);
    g_timeout_add_seconds (forceShutdown, killOffApp, app); // << here
    gtk_widget_show_all (window);
}

static gboolean killOffApp (gpointer userData) {
    g_application_quit (userData); // << and here
    return FALSE;
}
like image 84
paxdiablo Avatar answered Nov 09 '22 11:11

paxdiablo