5
votes

I have a main window with a menu wich opens another window. This secondary window has a button Close. That button has the signal clicked connected. My problem is that I don't know how to close/destroy that parent window. I have tried with gtk_widget_destroy, but an error appears because window is not a widget .... I haven't found any function to destroy the parent window ....

Can anyone show me the way, please? Thanks in advance.

-----------------------------------------------

Ok. I post a piece of code. When I execute the program I click in "Open window" button. A new window is openned with one button "Close". If I click in "Close" button I get next error in terminal: (Windows:13801): Gtk-CRITICAL **: gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed

The code is:

#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

void open_window(GtkWidget *widget, gpointer window);
void close_window(GtkWidget *widget, gpointer window);

int main( int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Windows");
    gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);

    button = gtk_button_new_with_label("Open window");

    gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50);
    gtk_widget_set_size_request(button, 80, 35);

    g_signal_connect(G_OBJECT(button), "clicked",
                     G_CALLBACK(open_window), G_OBJECT(window));

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
                             G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;

}


void open_window(GtkWidget *widget, gpointer window)
{
    GtkBuilder *builder;
    GtkWidget *secondWindow = NULL;

    builder = gtk_builder_new ();
    gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);

    secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));

    gtk_builder_connect_signals (builder, NULL);

    g_object_unref (G_OBJECT (builder));

    gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
    gtk_widget_show_all(secondWindow);
}

void close_window(GtkWidget *widget, gpointer window)
{
    gtk_widget_destroy(GTK_WIDGET(window));
}

In file "secondWindow.glade" is defined a window, a table and a button placed in the middle cell of the table. Also, it is defined a handle for the "clicked" event button named "close_window".

Link to glade file if anyone wants to execute it: https://sites.google.com/site/marvalsiteimages/secondWindow.glade

I hope this could help you to understand my problem. Thansk.

-------------------------------------------------

Final code based on the response:

void open_window(GtkWidget *widget, gpointer window)
{
    GtkBuilder *builder;
    GtkWidget *secondWindow = NULL;
    GtkWidget *closeButton = NULL;

    builder = gtk_builder_new ();
    gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);

    secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));
    closeButton = GTK_WIDGET (gtk_builder_get_object (builder, "closeWindowButton"));

    g_signal_connect (G_OBJECT (closeButton),
                      "clicked",
                      G_CALLBACK (close_window),
                      G_OBJECT (secondWindow)); // here is the magic: the callback will get the window to close

    g_object_unref (G_OBJECT (builder));

    gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
    gtk_widget_show_all(secondWindow);
}
1
GtkWindow is a GtkWidget. You can hide it.Kwariz
From a user experience point of view, having a click on a secondary windows closing the first one looks a bit weird. What are you trying to achieve? There may be a better way to do it. Please specify also you GTK version.liberforce
By the way, gtk_widget_destroy on a GtkWindow should work, as GtkWindow is derived from GtkWidget. Please show us some code.liberforce
It is the parent window of the close button. So I'd like to close the second window with its button ... not the main ...NEBUC
Then gtk_widget_destroy is the way to go. Please give us some code.liberforce

1 Answers

5
votes

Your problem is that the "clicked" signal of the button of the second window is connected from the glade file. But the signal handler needs a pointer to the window to destroy it. This is passed through the "user_data" parameter of the signal callback.

One way would be by passing the second window as the user_data argument in Glade (give a look at this Glade tutorial), but the argument is supposed to be a pointer, and I don't know how one can do it with glade. EDIT: just click on the user data field associated to this signal in glade, and a popup will allow you to select the object to pass to the signal handler. Just select your "secondWindow" object.

Another way to do it would be to just remove the signal handling from the glade file, and connect manually the clicked signal from code, passing a pointer to the second window as user data:

void open_window(GtkWidget *widget, gpointer window)
{
    GtkBuilder *builder;
    GtkWidget *secondWindow = NULL;
    GtkWidget *closeButton = NULL;

    builder = gtk_builder_new ();
    gtk_builder_add_from_file (builder, "secondWindow.glade", NULL);

    secondWindow = GTK_WIDGET (gtk_builder_get_object (builder, "secondWindow"));
    closeButton = GTK_WIDGET (gtk_builder_get_object (builder, "closeWindowButton"));

    g_signal_connect (G_OBJECT (closeButton),
        "clicked",
        G_CALLBACK (close_window),
        G_OBJECT (secondWindow)); // here is the magic: the callback will get the window to close

    g_object_unref (G_OBJECT (builder));

    gtk_window_set_modal(GTK_WINDOW(secondWindow), TRUE);
    gtk_widget_show_all(secondWindow);
}