Re: [gtk-list] calling a function on "destroy" signal



On Wed, 13 Oct 1999, John C Atkeson wrote:

>   
>   I'm trying to catch the event when a particular widget is destroyed, so
> I can free some user_data along with it.

the best way to do this is to use gtk_object_set_data_full(), i.e. like:

typedef struct
{
  int foo;
} MyStuff;

gtk_object_set_data_full (GTK_OBJECT (drawing_area), "MyStuff",
                          g_new0 (MyStuff), free_my_stuff);

retrival then works through
MyStuff *my_stuff = gtk_object_get_data (GTK_OBJECT (drawing_area), "MyStuff");


>   But, even though I've tried a lot of different combinations, the
> free_luggage function is never called.  
>   
>   The code is below, is there something obvious that I'm missing?
>   
>   Thanks in advance,  
>   John
>   
>   
> /* derived from scribble.c */
> 
> #include <gtk/gtk.h>
> #include <stdlib.h>
> #include <stdio.h>
> 
> GtkWidget *window;
> 
> typedef unsigned char byte;
> 
> typedef struct MyLuggageType{
>   char MyString[256];
>   long MyData;
> }MyLuggageT;
> 
> gint free_luggage(GtkWidget *dummy, MyLuggageT *MyLuggage)
> /**************************************************************
> * *Supposed* to be called when this widget is destroyed.
> **************************************************************/
> {
>   long cnt;
>   free(MyLuggage);
>   g_print("Luggage freed!\n");
>   getchar(); /* wait for user to acknowledge */
>   return (FALSE);
> }
> 
> GtkWidget *my_window_create(gdouble wdt,gdouble hgt)
> /**************************************************************
> **************************************************************/
> {
>   GtkWidget *drawing_area = gtk_drawing_area_new ();
>   MyLuggageT *MyLuggage=malloc(sizeof(MyLuggageT)); 
                          ^^^^^^
                          you'd rather use g_malloc() or even better g_new(),
                          the tutorial gives more hints on glib functions and
                          why to use them.
                          
>   MyLuggage->MyData=20;
> 
>   gtk_object_set_user_data (GTK_OBJECT(drawing_area), MyLuggage);
>   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), wdt, hgt);
>   gtk_widget_show (drawing_area);
>   
>   /* this doesn't work */
>   gtk_signal_connect (GTK_OBJECT (drawing_area), "destroy_event",
>                       GTK_SIGNAL_FUNC (free_luggage), MyLuggage);
scratch this one.


> 
>   /* nor this either */
>   gtk_signal_connect (GTK_OBJECT (drawing_area), "destroy",
>                       GTK_SIGNAL_FUNC (free_luggage), MyLuggage);
this is the correct connection.

> 
>   return (drawing_area);
> }/* my_window_create */
> 
> void quit ()
> /**************************************************************
> **************************************************************/
> {
>   gtk_exit (0);
> }

here in quit() you cause the application to immediatedly exit,
gtk_exit(0); will never return.

> 
> int main (int argc, char *argv[])
> /**************************************************************
> **************************************************************/
> {
>   GtkWidget *drawing_area;
> 
>   gtk_init (&argc, &argv);
> 
>   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
>   gtk_widget_set_name (window, "Test Input");
> 
>   gtk_signal_connect (GTK_OBJECT (window), "destroy",
>                       GTK_SIGNAL_FUNC (quit), NULL);
and here you connect quit() to the window's destroy signal.

now think about it, once a container gets the ::destroy signal emitted
on it, it will also destroy its children. but before that, the destroy
handlers get invoked, thus quit() is called before the window gets a
chance to destroy drawing_area.
thus the progarm exits before the drawin_garea's ::destroy callbacks can
be called, of course you don't leak memory with that because everything
is freed on a program exit, but you'd do better just calling gtk_main_quit()
from quit() and have you program exit through main().

> 
>   /* Create the drawing area */
>   drawing_area = my_window_create(200, 200);
> 
>   gtk_container_add (GTK_CONTAINER (window), drawing_area);
> 
>   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
>                          | GDK_LEAVE_NOTIFY_MASK
>                          | GDK_DESTROY
>                          | GDK_DELETE);
> 
>   gtk_widget_show (window);
> 
>   gtk_main ();
> 
>   return 0;
> }
> /* example-end */
> 

---
ciaoTJ



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