Re: emitting the "delete_event" in a "key_press_event" --> crash



Olivier wrote:

Hi all,

I want my dialogs to close when the user presses the escape key. So I
attached to the key_press_event, and if the key is escape I emit the
delete event. Immediately the delete event destroys the window, and then
the programs continues with the key-press-event (on a widget that doesn't
exist anymore!!) and crashes (tha backtrace says it segfaults somewhere
inside gtk).

how do I do this in a way that doesn't crash gtk?

The usual solution is to pass gtk_main_quit as callback to "delete_event"
of root window of your app. This trivial solution will always work, I changed
this way the code you posted (look at attach). This doesnt explain
however why app not terminated when hitting ESC in root.

BTW: you code produce no seg faults in my system, just not exit to console
after main window unmaps.

Olexiy


/*
escape_testcase.c
compile with
gcc escape_testcase.c -o escape_testcase `pkg-config --cflags --libs gtk+-2.0
*/

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

static void create_testwin();

static gboolean create_window_key_press_event_lcb(GtkWidget *widget, GdkEventKey *event,GtkWidget *win)
{
        if (event->keyval == GDK_Escape) {
                g_signal_emit_by_name(G_OBJECT(win), "delete_event");
/*              gtk_widget_destroy(win);*/
                return TRUE;
        }
        return FALSE;
}
                                
GtkWidget *create_window(GCallback close_func,gpointer close_data) {
GtkWidget *returnwidget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

        g_signal_connect(G_OBJECT(returnwidget), "delete_event", close_func, close_data);
        g_signal_connect(G_OBJECT(returnwidget), "destroy", close_func, close_data);
        g_signal_connect(G_OBJECT(returnwidget), "key_press_event", 
G_CALLBACK(create_window_key_press_event_lcb), returnwidget);
        return returnwidget;
}

GtkWidget *create_root_window(GCallback close_func,gpointer close_data) {
GtkWidget *returnwidget = gtk_window_new(GTK_WINDOW_TOPLEVEL);

        g_signal_connect(G_OBJECT(returnwidget), "delete_event", gtk_main_quit, NULL);
/*      g_signal_connect(G_OBJECT(returnwidget), "destroy", close_func, close_data); */
        g_signal_connect(G_OBJECT(returnwidget), "key_press_event", 
G_CALLBACK(create_window_key_press_event_lcb), returnwidget);
        return returnwidget;
}
                                                
typedef struct {
        GtkWidget *win;
        int various_other_data;
} TestWinStruct;
                                                                
void testwin_destroy_cb(GtkWidget * widget, GdkEvent *event, TestWinStruct *testwin) {
        g_signal_handlers_destroy(G_OBJECT(testwin->win));
        gtk_widget_destroy(testwin->win);
        g_free(testwin);
}
                                                                
static void testwin_button_clicked_cb(GtkWidget *widget, gpointer data) {
        create_testwin();
}
                                                                        
static void create_testwin() {
GtkWidget *button;
TestWinStruct *testwin;

        testwin = g_new(TestWinStruct,1);
        testwin->win = create_window(G_CALLBACK(testwin_destroy_cb), testwin);
        button = gtk_button_new_with_label("create another testwin\n");
        g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(testwin_button_clicked_cb), NULL);
        gtk_container_add(GTK_CONTAINER(testwin->win), button);
        gtk_widget_show_all(testwin->win);
}

static void create_root_testwin() {
GtkWidget *button;
TestWinStruct *testwin;

        testwin = g_new(TestWinStruct,1);
        testwin->win = create_root_window(G_CALLBACK(testwin_destroy_cb), testwin);
        button = gtk_button_new_with_label("create another testwin\n");
        g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(testwin_button_clicked_cb), NULL);
        gtk_container_add(GTK_CONTAINER(testwin->win), button);
        gtk_widget_show_all(testwin->win);
}
                                                                                                              
          
int main(int argc, char *argv[]) {
        gtk_init(&argc, &argv);
        create_root_testwin();
        gtk_main();
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]