Re: Calling gtk_widget_destroy()



Programming a windowing system like GTK requires wrapping your mind
around "event driven" programming.  In this paradigm, you set up all
your fcns, and then sit in a loop (gtk_main), and wait for events to
take place.  Usually, the events are mouse button clicks, or keys
pressed.  For each event, you have defined a callback which tells the
computer what to do in the case of that event.  After the callback has
run, you return to the event loop.

In your case, foo has two events it handles: "delete_event", and
"clicked".  When you run your program, foo creates the window and
registers the callbacks with the event handler (loop).  Then your prog
enters the event handling loop gtk_main.  

As for your problem: when you click "delete_event", gtk_main calls
gtk_main_quit. Gtk_main_quit kills all its windows, and then returns
to gtk_main. Then, gtk_main returns,  and you proceed to the next
statement gtk_window_destroy.  However, all the windows are already
gone and the memory has already been freed!  Therefore, you get a
segfault.    

The proper way to write your program is exactly has you have written
it, but remove the gtk_window_destroy after gtk_main (as you did to
make it work).

I find it helpful to remember that calling gtk_main is always the last
thing to do, and that your program lives inside gtk_main's event loop.
When you press a button or click the mouse, the loop invokes the 
corresponding callback, and then returns to the loop to wait for the
next event.  This is *not* a sequential way of coding an algorithm,
and you shouldn't think about it sequentially.

Stuart


Hello there,

I've came across a situation with a code like this (GTK+-2 app):

<pseudo-code>
foo()
{
      window = gtk_window_new();
      button = gtk_button_new_with_label("foo");
      gtk_container_add(window, button);
      gtk_widget_show(button);

      g_signal_connect(window, "delete_event",
              G_CALLBACK (gtk_main_quit), NULL);
      g_signal_connect(button, "clicked",
              G_CALLBACK (gtk_main_quit), NULL);
      return (window);
}

main()
{
      gtk_init();
      window = foo();
      gtk_widget_show(window);
      gtk_main();
      gtk_widget_destroy(window);     // !!!!!
      return (0);
}
</pseudo-code>

Now, as you might have guessed, this simple app creates a window with a
button, and then makes it so the window can be closed by either closing
the window with window manager, or by clicking the button ``foo'', both
ways via gtk_main_quit().

The actual question is that on practice, two ways do not behave
identically.  Clicking the button closes the all nice and clean.  But,
closing the window with window manager, it blows with segfault:

GLib-GObject-WARNING **: invalid uninstantiatable type `(null)' in cast to `GtkWidget'
Segmentation fault

If I remove the line in main() marked with `!!!!', everything magically
start to work correctly (e.g., both ways are closing the window
cleanly).

Can anyone poor some light on this?  Is gtk_widget_destroy() gets called
somewhere deep in gtk_main_quit() ?  If this is true, how come clicking
the button does work (via the very same gtk_main_quit()) ?  Or maybe
there is some other (on "destroy"?) hook I'm missing?  Am I right
thinking that segfault is triggered by gtk_widget_destroy() being called
twice, in the first place?  Finally, what is the correct way of coding
this sort of thing? :-)

I know this differs from ``Hello, world!'' application in GTK+-2.0
tutorial on gtk.org, but that how the real-life code is coded that I
have to work with (it's not mine).

Any help would be greatly appreciated.

Thanks!

./danfe
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list





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