Search code examples
cgtksignalsgtk3

How do I quit a gtk application from a button click?


Im trying to quit an application from a button click. What I'm currently doing Segfaults.

I have tried calling g_application_quit(G_APPLICATION(app)); in main it still segfaults

Calling gtk_widget_destroy(window); also segfaults

#include <stdlib.h>
#include <gtk/gtk.h>
void activate(GtkApplication* app, gpointer data)
{
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_application_add_window(app, GTK_WINDOW(window));
    GtkWidget *button = gtk_button_new_with_label("Button");
    void shutdown()
    {
        g_application_quit(G_APPLICATION(app));
    }
    g_signal_connect(GTK_BUTTON(button), "clicked", G_CALLBACK(shutdown), NULL);
    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show(button);
    gtk_window_present(GTK_WINDOW(window));
}

int main (int argc, char *argv[])
{
    GApplicationFlags flags = G_APPLICATION_FLAGS_NONE;
    GtkApplication *app = gtk_application_new("com.devab.daw", flags);
    GApplication *gapp = G_APPLICATION(app);
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
    g_application_run(gapp, argc, argv);
    g_object_unref (app);
    //g_application_quit(G_APPLICATION(app));
    return 0;
}

Solution

  • I am using gtk3 and this compiles and works for me.

    #include <stdlib.h>
    #include <gtk/gtk.h>
    void activate(GtkApplication* app, gpointer data)
    {
        GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_application_add_window(app, GTK_WINDOW(window));
        GtkWidget *button = gtk_button_new_with_label("Button");
        g_signal_connect_swapped(GTK_BUTTON(button), "clicked", G_CALLBACK(gtk_widget_destroy), window);
        gtk_container_add(GTK_CONTAINER(window), button);
        gtk_widget_show(button);
        gtk_window_present(GTK_WINDOW(window));
    }
    
    int main (int argc, char *argv[])
    {
        GApplicationFlags flags = G_APPLICATION_FLAGS_NONE;
        GtkApplication *app = gtk_application_new("com.devab.daw", flags);
        GApplication *gapp = G_APPLICATION(app);
        g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
        g_application_run(gapp, argc, argv);
        g_object_unref (app);
        //g_application_quit(G_APPLICATION(app));
        return 0;
    }
    

    Move destroy outside activate.

    #include <stdlib.h>
    #include <gtk/gtk.h>
    
    void destroy (GtkWidget* widget, gpointer data)
    {
        g_application_quit(G_APPLICATION(data));
    }
    
    void activate(GtkApplication* app, gpointer data)
    {
        GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_application_add_window(app, GTK_WINDOW(window));
        GtkWidget *button = gtk_button_new_with_label("Button");
        g_signal_connect(GTK_BUTTON(button), "clicked", G_CALLBACK(destroy), app);
        gtk_container_add(GTK_CONTAINER(window), button);
        gtk_widget_show(button);
        gtk_window_present(GTK_WINDOW(window));
    }
    
    int main (int argc, char *argv[])
    {
        GApplicationFlags flags = G_APPLICATION_FLAGS_NONE;
        GtkApplication *app = gtk_application_new("com.devab.daw", flags);
        GApplication *gapp = G_APPLICATION(app);
        g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
        g_application_run(gapp, argc, argv);
        g_object_unref (app);
        //g_application_quit(G_APPLICATION(app));
        return 0;
    }