2.6. Destroying Widgets   

The Intrinsics provide support

To destroy all the pop-up children of the widget being destroyed and destroy all children of composite widgets.

To remove (and unmap) the widget from its parent.

To call the callback procedures that have been registered to trigger when the widget is destroyed.

To minimize the number of things a widget has to deallocate when destroyed.

To minimize the number of XDestroyWindow calls when destroying a widget tree.

To destroy a widget instance, use XtDestroyWidget.


void XtDestroyWidget(w)
Widget w;
w Specifies the widget. Must be of class Object or any subclass thereof.
The XtDestroyWidget function provides the only method of destroying a widget, including widgets that need to destroy themselves. It can be called at any time, including from an application callback routine of the widget being destroyed. This requires a two-phase destroy process in order to avoid dangling references to destroyed widgets.

In phase 1, XtDestroyWidget performs the following:

If the being_destroyed field of the widget is True, it returns immediately.

Recursively descends the widget tree and sets the being_destroyed field to True for the widget and all normal and pop-up children.

Adds the widget to a list of widgets (the destroy list) that should be destroyed when it is safe to do so.

Entries on the destroy list satisfy the invariant that if w2 occurs after w1 on the destroy list, then w2 is not a descendent, either normal or pop-up, of w1.

Phase 2 occurs when all procedures that should execute as a result of the current event have been called, including all procedures registered with the event and translation managers, that is, when the current invocation of XtDispatchEvent is about to return, or immediately if not in XtDispatchEvent.

In phase 2, XtDestroyWidget performs the following on each entry in the destroy list in the order specified:

Calls the destroy callback procedures registered on the widget and all normal and pop-up descendants in postorder (it calls child callbacks before parent callbacks).

If the widget is not a pop-up child and the widget's parent is a subclass of compositeWidgetClass, and if the parent is not being destroyed, it calls XtUnmanageChild on the widget and then calls the widget's parent's delete_child procedure.

If the widget is not a pop-up child and the widget's parent is a subclass of constraintWidgetClass, it calls the ConstraintClassPart destroy procedure for the parent, then for the parent's superclass, until finally it calls the ConstraintClassPart destroy procedure for constraintWidgetClass.

Calls the destroy procedures for the widget and all normal and pop-up descendants in postorder. For each such widget, it calls the CoreClassPart destroy procedure declared in the widget class, then the destroy procedure declared in its superclass, until finally it calls the destroy procedure declared in the Object class record.

Calls XDestroyWindow if the specified widget is realized (that is, has an X window). The server recursively destroys all normal descendant windows.

Recursively descends the tree and destroys the windows for all realized pop-up descendants, deallocates all pop-up descendants, constraint records, callback lists, and if the widget's class is a subclass of compositeWidgetClass , children.

2.6.1. Adding and Removing Destroy Callbacks   

When an application needs to perform additional processing during the destruction of a widget, it should register a destroy callback procedure for the widget. The destroy callback list is identified by the resource name XtNdestroyCallback.

For example, the following adds an application-supplied destroy callback procedure ClientDestroy with client data to a widget by calling XtAddCallback. XtAddCallback(w, XtNdestroyCallback, ClientDestroy, client_data)

Similarly, the following removes the application-supplied destroy callback procedure ClientDestroy by calling XtRemoveCallback. XtRemoveCallback(w, XtNdestroyCallback, ClientDestroy, client_data)

The ClientDestroy argument is of type XtCallbackProc.

2.6.2. Dynamic Data Deallocation: the destroy Procedure   

The destroy procedure pointers in the ObjectClassPart, RectObjClassPart, and CoreClassPart structures are of type XtWidgetProc.


typedef void (*XtWidgetProc)(Widget);
Widget w;
w Specifies the widget being destroyed.
The destroy procedures are called in subclass-to-superclass order. Therefore, a widget's destroy procedure only should deallocate storage that is specific to the subclass and should ignore the storage allocated by any of its superclasses. The destroy procedure should only deallocate resources that have been explicitly created by the subclass. Any resource that was obtained from the resource database or passed in an argument list was not created by the widget and therefore should not be destroyed by it. If a widget does not need to deallocate any storage, the destroy procedure entry in its class record can be NULL.

Deallocating storage includes, but is not limited to, the following steps:

Calling XtFree on dynamic storage allocated with XtMalloc, XtCalloc, and so on.

Calling XFreePixmap on pixmaps created with direct X calls.

Calling XtReleaseGC on GCs allocated with XtGetGC.

Calling XFreeGC on GCs allocated with direct X calls.

Calling XtRemoveEventHandler on event handlers added to other widgets.

Calling XtRemoveTimeOut on timers created with XtAppAddTimeOut.

Calling XtDestroyWidget for each child if the widget has children and is not a subclass of compositeWidgetClass.

During destroy phase 2 for each widget, the Intrinsics remove the widget from the modal cascade, unregister all event handlers, remove all key, keyboard, button, and pointer grabs and remove all callback procedures registered on the widget. Any outstanding selection transfers will time out.

2.6.3. Dynamic Constraint Data Deallocation: the ConstraintClassPart destroy Procedure   

The constraint destroy procedure identified in the ConstraintClassPart structure is called for a widget whose parent is a subclass of constraintWidgetClass. This constraint destroy procedure pointer is of type XtWidgetProc. The constraint destroy procedures are called in subclass-to-superclass order, starting at the class of the widget's parent and ending at constraintWidgetClass. Therefore, a parent's constraint destroy procedure only should deallocate storage that is specific to the constraint subclass and not storage allocated by any of its superclasses.

If a parent does not need to deallocate any constraint storage, the constraint destroy procedure entry in its class record can be NULL.