Blame docs/widget_system.txt

Packit 98cdb6
Notes about the inner workings of the widget system of GTK+
Packit 98cdb6
===========================================================
Packit 98cdb6
Packit 98cdb6
This file contains some notes as to how the widget system does
Packit 98cdb6
and should work. It consists of three parts:
Packit 98cdb6
Packit 98cdb6
 I) A description of the meaning of the various flags
Packit 98cdb6
Packit 98cdb6
 II) A list of invariants about the states of the widgets. 
Packit 98cdb6
    (Throughout this document, we refer to the states of the
Packit 98cdb6
     widgets by referring to the flags for GtkWidget)
Packit 98cdb6
Packit 98cdb6
 III) Some notes about the ways that a widget changes states
Packit 98cdb6
Packit 98cdb6
 IV) A list of responsibilities of various widget signals when
Packit 98cdb6
    the states change.
Packit 98cdb6
Packit 98cdb6
Any action necessary to maintain the invariants in II which is not
Packit 98cdb6
explicitly mentioned in IV), is the responsibility of the core GTK
Packit 98cdb6
code, which is roughly defined as:
Packit 98cdb6
Packit 98cdb6
  gtkobject.c
Packit 98cdb6
  gtkwidget.c
Packit 98cdb6
  gtkcontainer.c
Packit 98cdb6
  gtkmain.c
Packit 98cdb6
  gtksignal.c
Packit 98cdb6
Packit 98cdb6
Section II is mostly of interest to those maintaining GTK, the
Packit 98cdb6
other sections may also be interesting to people writing
Packit 98cdb6
new widgets.
Packit 98cdb6
Packit 98cdb6
Main outline:
Packit 98cdb6
	- Owen Taylor <owt1@cornell.edu>
Packit 98cdb6
	  1998/02/03
Packit 98cdb6
Packit 98cdb6
Flag descriptions:
Packit 98cdb6
	- Tim Janik <timj@gimp.org>
Packit 98cdb6
	  1998/02/04
Packit 98cdb6
Packit 98cdb6
I. Flags
Packit 98cdb6
--------
Packit 98cdb6
Packit 98cdb6
GtkObject:
Packit 98cdb6
Packit 98cdb6
GTK_DESTROYED:
Packit 98cdb6
	This flagged is set for a GtkObject right before its
Packit 98cdb6
	destruction code is executed. Its main use is the
Packit 98cdb6
	prevention of multiple destruction invocations.
Packit 98cdb6
	
Packit 98cdb6
GTK_FLOATING:
Packit 98cdb6
	This flag reflects the fact that the holder of the
Packit 98cdb6
	initial reference count is unknown. Refer to refcounting.txt
Packit 98cdb6
	for further details.
Packit 98cdb6
Packit 98cdb6
GTK_RESERVED_1:
Packit 98cdb6
GTK_RESERVED_2:
Packit 98cdb6
	Reserved flags.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
GtkWidget, public flags:
Packit 98cdb6
Packit 98cdb6
GTK_TOPLEVEL:
Packit 98cdb6
	Widgets without a real parent, as there are GtkWindows and
Packit 98cdb6
	GtkMenus have this flag set throughout their lifetime.
Packit 98cdb6
	Toplevel widgets always contain their own GdkWindow.
Packit 98cdb6
	
Packit 98cdb6
GTK_NO_WINDOW:
Packit 98cdb6
	This flag is indicative for a widget that does not provide
Packit 98cdb6
	its own GdkWindow. Visible action (e.g. drawing) is performed
Packit 98cdb6
	on the parent's GdkWindow.
Packit 98cdb6
Packit 98cdb6
GTK_REALIZED:
Packit 98cdb6
	Set by gtk_widget_realize, unset by gtk_widget_unrealize.
Packit 98cdb6
	Relies on ((widget->parent && widget->parent->window)
Packit 98cdb6
	           || GTK_WIDGET_TOPLEVEL (widget));
Packit 98cdb6
	Means: widget has an associated GdkWindow (XWindow).
Packit 98cdb6
Packit 98cdb6
GTK_MAPPED:
Packit 98cdb6
	Set by gtk_widget_map, unset by gtk_widget_unmap.
Packit 98cdb6
	May only be set if GTK_WIDGET_REALIZED (widget).
Packit 98cdb6
	Means: gdk_window_show() has been called on the widgets window(s).
Packit 98cdb6
Packit 98cdb6
GTK_VISIBLE:
Packit 98cdb6
	Set by gtk_widget_show.
Packit 98cdb6
	Implies that a widget will be flagged GTK_MAPPED as soon as its
Packit 98cdb6
	parent is mapped.
Packit 98cdb6
!GTK_VISIBLE:
Packit 98cdb6
	Set by gtk_widget_hide.
Packit 98cdb6
	Implies that a widget is not onscreen, therefore !GTK_MAPPED.
Packit 98cdb6
Packit 98cdb6
GTK_CHILD_VISIBLE
Packit 98cdb6
        Set by gtk_widget_set_child_visible, and if FALSE indicates that 
Packit 98cdb6
        the widget should not be mapped even if the parent is mapped
Packit 98cdb6
        and visible. Containers like GtkNotebook use this flag.
Packit 98cdb6
        A private flag, not a public flag, so if you need to check
Packit 98cdb6
        this flag, you should call gtk_widget_get_child_visible().
Packit 98cdb6
        (Should be very rarely necessary.)
Packit 98cdb6
Packit 98cdb6
GTK_SENSITIVE:
Packit 98cdb6
	Set and unset by gtk_widget_set_sensitive.
Packit 98cdb6
	The sensitivity of a widget determines whether it will receive
Packit 98cdb6
	certain events (e.g. button or key presses). One premise for
Packit 98cdb6
	the widgets sensitivity is to have GTK_SENSITIVE set.
Packit 98cdb6
Packit 98cdb6
GTK_PARENT_SENSITIVE:
Packit 98cdb6
	Set and unset by gtk_widget_set_sensitive operations on the
Packit 98cdb6
	parents of the widget.
Packit 98cdb6
	This is the second premise for the widgets sensitivity. Once
Packit 98cdb6
	it has GTK_SENSITIVE and GTK_PARENT_SENSITIVE set, its state is
Packit 98cdb6
	effectively sensitive. This is expressed (and can be examined) by
Packit 98cdb6
	the GTK_WIDGET_IS_SENSITIVE macro.
Packit 98cdb6
Packit 98cdb6
GTK_CAN_FOCUS:
Packit 98cdb6
	There are no directly corresponding functions for setting/unsetting
Packit 98cdb6
	this flag, but it can be affected by the GtkWidget::has_focus argument
Packit 98cdb6
	via gtk_widget_set_arg.
Packit 98cdb6
	This flag determines whether a widget is able to handle focus grabs.
Packit 98cdb6
Packit 98cdb6
GTK_HAS_FOCUS:
Packit 98cdb6
	This flag will be set by gtk_widget_grab_focus for widgets that also
Packit 98cdb6
	have GTK_CAN_FOCUS set. The flag will be unset once another widget
Packit 98cdb6
	grabs the focus.
Packit 98cdb6
	
Packit 98cdb6
GTK_CAN_DEFAULT:
Packit 98cdb6
GTK_HAS_DEFAULT:
Packit 98cdb6
	These two flags are mostly equal in functionality to their *_FOCUS
Packit 98cdb6
	counterparts, but for the default widget.
Packit 98cdb6
Packit 98cdb6
GTK_HAS_GRAB:
Packit 98cdb6
	Set by gtk_grab_add, unset by gtk_grab_remove.
Packit 98cdb6
	Means: widget is in the grab_widgets stack, and will be the preferred
Packit 98cdb6
	one for receiving events other than ones of cosmetic value.
Packit 98cdb6
Packit 98cdb6
GTK_BASIC:
Packit 98cdb6
	The GTK_BASIC flag is an attempt at making a distinction
Packit 98cdb6
	between widgets that handle user input e.g. key/button presses
Packit 98cdb6
	and those that don't. Subsequent parent<->child relation ships
Packit 98cdb6
	of non `basic' widgets should be avoided. The checking for
Packit 98cdb6
	this is currently not properly enforced in the code. For
Packit 98cdb6
	example GtkButton is a non `basic' widget, that will therefore
Packit 98cdb6
	disallow to act as a container for another GtkButton. Now the
Packit 98cdb6
	gnit is, one can add a GtkHBox (which is a `basic' widget) to
Packit 98cdb6
	the first button, and put the second into the box.
Packit 98cdb6
Packit 98cdb6
GTK_RESERVED_3:
Packit 98cdb6
Packit 98cdb6
GTK_RC_STYLE:
Packit 98cdb6
	This flag indicates that its style has been looked up through
Packit 98cdb6
	the rc mechanism. It does not imply that the widget actually
Packit 98cdb6
	had a style defined through the rc mechanism.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
GtkWidget, private flags:
Packit 98cdb6
Packit 98cdb6
GTK_USER_STYLE:
Packit 98cdb6
	A widget is flagged to have a user style, once gtk_widget_set_style
Packit 98cdb6
	has been invoked for it. The use of this flag is to tell widgets
Packit 98cdb6
	which share a global user style from the ones which got a certain
Packit 98cdb6
	style assign from outside the toolkit.
Packit 98cdb6
	
Packit 98cdb6
GTK_RESIZE_PENDING:
Packit 98cdb6
	First, this is only valid for GtkContainers.
Packit 98cdb6
	[some of the code should move to gtkcontainer.c therefore]
Packit 98cdb6
	Relies on GTK_WIDGET_REALIZED(widget)
Packit 98cdb6
	[this is not really enforced throughout the code, but should
Packit 98cdb6
	 be. it only requires a few checks for GTK_WIDGET_REALIZED and
Packit 98cdb6
	 minor changes to gtk_widget_unrealize, we can then remove the check
Packit 98cdb6
	 in gtk_widget_real_destroy]
Packit 98cdb6
	Means: there is an idle handler waiting for the container to
Packit 98cdb6
	resize it.
Packit 98cdb6
Packit 98cdb6
GTK_RESIZE_NEEDED:
Packit 98cdb6
	Relies on GTK_WIDGET_REALIZED(widget)
Packit 98cdb6
	[this is not really enforced throughout the code, but should
Packit 98cdb6
	 be. once this is done special checking in gtk_widget_real_destroy
Packit 98cdb6
	 can be avoided]
Packit 98cdb6
	Means: a widget has been added to the resize_widgets list of
Packit 98cdb6
	its _toplevel_ container (keep this in mind for GtkViewport).
Packit 98cdb6
	Remark: this flag is also used internally by gtkwindow.c during
Packit 98cdb6
	the evaluation of resizing worthy widgets.
Packit 98cdb6
Packit 98cdb6
GTK_LEAVE_PENDING:
Packit 98cdb6
	A widget is flagged as such if there is a leave_notify event
Packit 98cdb6
	pending for it. It will receive this event regardless of a grab
Packit 98cdb6
	through another widget or its current sensitivity.
Packit 98cdb6
	[this should be made relying on GTK_REALIZED]
Packit 98cdb6
Packit 98cdb6
GTK_HAS_SHAPE_MASK:
Packit 98cdb6
	Set by gtk_widget_shape_combine_mask if a widget got a shape mask
Packit 98cdb6
	assigned (making use of the X11 shaped window extension).
Packit 98cdb6
Packit 98cdb6
GTK_IN_REPARENT:
Packit 98cdb6
	During the act of reparentation widgets which are already
Packit 98cdb6
	realized and will be added to an already realized parent need
Packit 98cdb6
	to have this flag set to prevent natural unrealization on the
Packit 98cdb6
	process of getting unparented.
Packit 98cdb6
Packit 98cdb6
GTK_NEED_REQUEST:
Packit 98cdb6
	This flag is set if the widget doesn't have an up to date 
Packit 98cdb6
	requisition. If this flag is set, we must actually emit ::size-request
Packit 98cdb6
        when gtk_widget_size_request() is called. Otherwise, we can
Packit 98cdb6
        simply widget->requisition. We keep track of this all the time
Packit 98cdb6
        however, widgets with this flag set are only added to the resize 
Packit 98cdb6
	queue if they are viewable.
Packit 98cdb6
Packit 98cdb6
GTK_NEED_ALLOCATION:
Packit 98cdb6
	This flag is set if the widget doesn't have an up to date 
Packit 98cdb6
	allocation. If this flag is set, we must actually emit ::size-allocate
Packit 98cdb6
        when gtk_widget_size_allocate() is called, even if the new allocation
Packit 98cdb6
        is the same as the current allocation.
Packit 98cdb6
 
Packit 98cdb6
Related Macros:
Packit 98cdb6
Packit 98cdb6
GTK_WIDGET_DRAWABLE:
Packit 98cdb6
	This macro examines whether a widget is flagged as GTK_WIDGET_VISIBLE
Packit 98cdb6
	and GTK_WIDGET_MAPPED.
Packit 98cdb6
	Means: it _makes sense_ to draw in a widgets window.
Packit 98cdb6
Packit 98cdb6
GTK_WIDGET_IS_SENSITIVE:
Packit 98cdb6
	This macro tells the real sensitivity state of a widget. It returns
Packit 98cdb6
	whether both the widget and all its parents are in sensitive state.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
II. Invariants:
Packit 98cdb6
---------------
Packit 98cdb6
Packit 98cdb6
This section describes various constraints on the states of 
Packit 98cdb6
the widget:
Packit 98cdb6
Packit 98cdb6
In the following
Packit 98cdb6
Packit 98cdb6
  A => B     means  if A is true, than B is true
Packit 98cdb6
  A <=> B    means  A is true, if and only if B is true
Packit 98cdb6
                    (equivalent to A => B and A <= B)
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
1)  GTK_WIDGET_DESTROYED (widget) => !GTK_WIDGET_REALIZED (widget)
Packit 98cdb6
                                  => !GTK_WIDGET_VISIBLE (widget)
Packit 98cdb6
[ The latter is not currently in place, but it should be ] 
Packit 98cdb6
 
Packit 98cdb6
2) GTK_WIDGET_MAPPED (widget) => GTK_WIDGET_REALIZED (widget)
Packit 98cdb6
Packit 98cdb6
3) if GTK_WIDGET_TOPLEVEL (widget):
Packit 98cdb6
   GTK_WIDGET_VISIBLE (widget) <=> GTK_WIDGET_MAPPED (widget)
Packit 98cdb6
Packit 98cdb6
4) if !GTK_WIDGET_TOPLEVEL (widget):
Packit 98cdb6
  widget->parent && GTK_WIDGET_REALIZED (widget->parent) <=>
Packit 98cdb6
     GTK_WIDGET_REALIZED (widget)
Packit 98cdb6
Packit 98cdb6
5) if !GTK_WIDGET_TOPLEVEL (widget):
Packit 98cdb6
Packit 98cdb6
   GTK_WIDGET_MAPPED (widget) => GTK_WIDGET_VISIBLE (widget)
Packit 98cdb6
                              => GTK_WIDGET_CHILD_VISIBLE (widget)
Packit 98cdb6
                              => GTK_WIDGET_REALIZED (widget)
Packit 98cdb6
Packit 98cdb6
   widget->parent && GTK_WIDGET_MAPPED (widget->parent) && 
Packit 98cdb6
     GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_CHILD_VISIBLE 
Packit 98cdb6
       => GTK_WIDGET_MAPPED (widget)
Packit 98cdb6
Packit 98cdb6
Note:, the definition
Packit 98cdb6
Packit 98cdb6
[  GTK_WIDGET_DRAWABLE = GTK_WIDGET_VISIBLE && GTK_WIDGET_MAPPED
Packit 98cdb6
   is made in gtkwidget.h, but by 3) and 5), 
Packit 98cdb6
     
Packit 98cdb6
      GTK_WIDGET_MAPPED => GTK_WIDGET_VISIBLE
Packit 98cdb6
]
Packit 98cdb6
Packit 98cdb6
6) GTK_REDRAW_PENDING => GTK_WIDGET_REALIZED
Packit 98cdb6
   GTK_RESIZE_PENDING =>         "
Packit 98cdb6
   GTK_LEAVE_PENDING  =>         "
Packit 98cdb6
   GTK_RESIZE_NEEDED  =>         "
Packit 98cdb6
Packit 98cdb6
III. How states are changed:
Packit 98cdb6
----------------------------
Packit 98cdb6
Packit 98cdb6
How can the user control the state of a widget:
Packit 98cdb6
-----------------------------------------------
Packit 98cdb6
Packit 98cdb6
(In the following, set flag means set the flag, do appropriate
Packit 98cdb6
actions, and enforce above invariants) 
Packit 98cdb6
Packit 98cdb6
gtk_widget_show: 
Packit 98cdb6
 if !GTK_DESTROYED sets GTK_VISIBLE
Packit 98cdb6
Packit 98cdb6
gtk_widget_hide:
Packit 98cdb6
 if !GTK_VISIBLE for widget
Packit 98cdb6
Packit 98cdb6
gtk_widget_destroy:
Packit 98cdb6
 sets GTK_DESTROYED
Packit 98cdb6
 For a top-level widget
Packit 98cdb6
Packit 98cdb6
gtk_widget_realize:
Packit 98cdb6
 if !GTK_DESTROYED sets GTK_REALIZED
Packit 98cdb6
- Calling gtk_widget_realize when the widget is not a descendant
Packit 98cdb6
  of a toplevel is an ERROR.
Packit 98cdb6
Packit 98cdb6
gtk_container_add (container, widget) [ and container-specific variants ]
Packit 98cdb6
 Sets widget->parent 
Packit 98cdb6
Packit 98cdb6
gtk_container_remove (container, widget)
Packit 98cdb6
 unsets widget->parent
Packit 98cdb6
Packit 98cdb6
gtk_widget_reparent (widget, new_parent)
Packit 98cdb6
 Equivalent to removing widget from old parent and adding it to
Packit 98cdb6
 the new parent, except that the widget will not be temporarily 
Packit 98cdb6
 unrealized if both the old parent and the new parent are realized.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
gtk_widget_unrealize
Packit 98cdb6
gtk_widget_map
Packit 98cdb6
gtk_widget_unmap
Packit 98cdb6
Packit 98cdb6
These functions are not meant to be used by applications - they
Packit 98cdb6
are used only by GTK and widgets to enforce invariants on the
Packit 98cdb6
state.
Packit 98cdb6
Packit 98cdb6
When The X window corresponding to a GTK window is destroyed:
Packit 98cdb6
-------------------------------------------------------------
Packit 98cdb6
Packit 98cdb6
gtk_widget_destroy is called (as above).
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
IV. Responsibilities of widgets
Packit 98cdb6
--------------------------------
Packit 98cdb6
Packit 98cdb6
Adding to a container
Packit 98cdb6
---------------------
Packit 98cdb6
Packit 98cdb6
When a widget is added to a container, the container:
Packit 98cdb6
Packit 98cdb6
  1) calls gtk_widget_set_parent_window (widget, window) if 
Packit 98cdb6
     the widget is being added to something other than container->window
Packit 98cdb6
  2) calls gtk_widget_set_parent (widget, container)
Packit 98cdb6
Packit 98cdb6
Removing from a container
Packit 98cdb6
-------------------------
Packit 98cdb6
Packit 98cdb6
When a widget is removed to a container, the container:
Packit 98cdb6
Packit 98cdb6
  1) Calls gtk_widget_unparent (widget)
Packit 98cdb6
  2) Queues a resize.
Packit 98cdb6
Packit 98cdb6
Notes:
Packit 98cdb6
Packit 98cdb6
 gtk_widget_unparent unrealizes the widget except in the 
Packit 98cdb6
   special case GTK_IN_REPARENT is set.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
At widget creation
Packit 98cdb6
------------------
Packit 98cdb6
Packit 98cdb6
Widgets are created in an unrealized state. 
Packit 98cdb6
Packit 98cdb6
 1) The widget should allocate and initialize needed data structures
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The Realize signal
Packit 98cdb6
------------------
Packit 98cdb6
Packit 98cdb6
When a widget receives the "realize" signal it should:
Packit 98cdb6
Packit 98cdb6
 NO_WINDOW widgets: (probably OK to use default handler)
Packit 98cdb6
Packit 98cdb6
  1) set the realized flag
Packit 98cdb6
  2) set widget->window
Packit 98cdb6
      widget->window = gtk_widget_get_parent_window (widget);
Packit 98cdb6
      g_object_ref (widget->window);
Packit 98cdb6
  3) attach the widget's style
Packit 98cdb6
Packit 98cdb6
  widget->style = gtk_style_attach (widget->style, widget->window);
Packit 98cdb6
Packit 98cdb6
 widget with window(s)
Packit 98cdb6
Packit 98cdb6
  1) set the REALIZED flag
Packit 98cdb6
  2) create windows with the parent obtained from
Packit 98cdb6
      gtk_widget_get_parent_window (widget);
Packit 98cdb6
  3) attach the widget's style
Packit 98cdb6
  4) set the background color for the new window based on the style
Packit 98cdb6
Packit 98cdb6
The Map signal
Packit 98cdb6
--------------
Packit 98cdb6
Packit 98cdb6
  1) Set the MAPPED flag
Packit 98cdb6
  2) If the widget has any windows, gdk_window_show those windows
Packit 98cdb6
  3) call gtk_widget_map for all child widgets that are 
Packit 98cdb6
     VISIBLE, CHILD_VISIBLE and !MAPPED. (A widget will only
Packit 98cdb6
     be !CHILD_VISIBLE if the container set it that way, so
Packit 98cdb6
     most containers will not have to check this.)
Packit 98cdb6
  3) Do any other functions related to putting the widget onscreen.
Packit 98cdb6
     (for instance, showing extra popup windows...)
Packit 98cdb6
Packit 98cdb6
The Unmap signal
Packit 98cdb6
----------------
Packit 98cdb6
Packit 98cdb6
When a widget receives the unmap signal, it must:
Packit 98cdb6
Packit 98cdb6
 1) If the widget has a window, gdk_window_hide that window, 
Packit 98cdb6
 2) If the widget does not have a window, unmap all child widgets
Packit 98cdb6
 3) Do any other functions related to taking the widget offscreen
Packit 98cdb6
     (for instance, removing popup windows...)
Packit 98cdb6
 4) Unset GTK_MAPPED
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The Unrealize signal
Packit 98cdb6
--------------------
Packit 98cdb6
Packit 98cdb6
When a widget receives the unrealize signal, it must
Packit 98cdb6
Packit 98cdb6
 1) For any windows other than widget->window do:
Packit 98cdb6
Packit 98cdb6
    gdk_window_set_user_data (window, NULL);
Packit 98cdb6
    gdk_window_destroy (window);
Packit 98cdb6
Packit 98cdb6
 2) Call the parent's unrealize handler
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The Widget class unrealize handler will take care of unrealizing
Packit 98cdb6
all children if necessary. [should this be made consistent with
Packit 98cdb6
unmap???]
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The Destroy Signal
Packit 98cdb6
------------------
Packit 98cdb6
Packit 98cdb6
Commentary:
Packit 98cdb6
Packit 98cdb6
  The destroy signal probably shouldn't exist at all. A widget
Packit 98cdb6
  should merely be unrealized and removed from its parent
Packit 98cdb6
  when the user calls gtk_widget_destroy or a GDK_DESTROY event
Packit 98cdb6
  is received. However, a large body of code depends on
Packit 98cdb6
  getting a definitive signal when a widget goes away.
Packit 98cdb6
Packit 98cdb6
  That could be put in the finalization step, but, especially
Packit 98cdb6
  with language bindings, the cleanup step may need to refer
Packit 98cdb6
  back to the widget. (To use gtk_widget_get_data, for instance)
Packit 98cdb6
  If it does so via a pointer in a closure (natural for
Packit 98cdb6
  Scheme, or Perl), then the finalization procedure will never
Packit 98cdb6
  be called. 
Packit 98cdb6
Packit 98cdb6
  Also, if we made that the finalization step, we would have
Packit 98cdb6
  to propagate the GDK_DESTROY event in any case, since it is
Packit 98cdb6
  at that point at which user-visible actions need to be taken.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
When a widget receives the destroy signal, it must:
Packit 98cdb6
Packit 98cdb6
  1) If the widget "owns" any widgets other than its child
Packit 98cdb6
     widgets, (for instance popup windows) it should
Packit 98cdb6
     call gtk_widget_destroy () for them.
Packit 98cdb6
Packit 98cdb6
  2) Call the parent class's destroy handler.
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The "destroy" signal will only be received once. A widget
Packit 98cdb6
will never receive any other signals after the destroy
Packit 98cdb6
signal (but see the section on "Finalize" below)
Packit 98cdb6
Packit 98cdb6
The widget must handle calls to all publically accessible
Packit 98cdb6
functions in an innocuous manner even after a "destroy"
Packit 98cdb6
signal. (A widget can assume that it will not be realized 
Packit 98cdb6
after a "destroy" signal is received, which may simplify
Packit 98cdb6
handling this requirement)
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
The Finalize Pseudo-signal
Packit 98cdb6
--------------------------
Packit 98cdb6
Packit 98cdb6
The finalize pseudo-signal is received after all references
Packit 98cdb6
to the widget have been removed. The finalize callback
Packit 98cdb6
cannot make any GTK calls with the widget as a parameter.
Packit 98cdb6
Packit 98cdb6
1) Free any memory allocated by the widget. (But _not_
Packit 98cdb6
   the widget structure itself.
Packit 98cdb6
Packit 98cdb6
2) Call the parent class's finalize signal
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
A note on chaining "destroy" signals and finalize signals:
Packit 98cdb6
---------------------------------------------------------
Packit 98cdb6
Packit 98cdb6
This is done by code like:
Packit 98cdb6
Packit 98cdb6
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
Packit 98cdb6
    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
Packit 98cdb6
Packit 98cdb6
It may not be completely obvious why this works. Note
Packit 98cdb6
that parent_class is a static variable on a per-class
Packit 98cdb6
basis. So say: we have
Packit 98cdb6
Packit 98cdb6
  GtkFoo <- GtkBar <- GtkWidget <-GtkObject
Packit 98cdb6
Packit 98cdb6
And that Foo, Widget, and Object all have destructors, but
Packit 98cdb6
not Bar.
Packit 98cdb6
Packit 98cdb6
Then gtk_foo_destroy will call gtk_widget_destroy (because
Packit 98cdb6
it was not overridden in the Bar class structure) and
Packit 98cdb6
gtk_widget_destroy will call gtk_object_destroy because
Packit 98cdb6
the parent_class variable referenced by gtk_foo_destroy is the 
Packit 98cdb6
static variable in gtkwidget.c: GtkObjectClass.