Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z
faqs.org - Internet FAQ Archives

comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Section - 10. How do I exit but still execute the DestroyCallbacks?

( Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Property taxes ]


Top Document: comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Previous Document: 9. Why doesn't my widget get destroyed when I call XtDestroyWidget()?
Next Document: 11. How do I resize a Shell widget?
See reader questions & answers on this topic! - Help others by sharing your knowledge
----------------------------------------------------------------------

The problem is if a simple and entirely reasonable approach to exiting
an application is used, such as calling exit() directly, then a widget
may not have a chance to clean up any external state -- such as open
sockets, temporary files, allocated X resources, etc.  (this code for
simplicity reasons assumes only a single toplevel widget):


	Widget
	ToplevelGet (gw)
		Widget		gw;		/* widget to find toplevel */
	{
		Widget		top;

		for (top = gw; XtParent (top); top = XtParent (top))
			/* empty */;
		return (top);
	}

	void
	ExitCallback (gw, closure, call_data)
		Widget		gw;		/* widget */
		XtPointer	closure;	/* data the app specified */
		XtPointer	call_data;	/* widget specific data */
	{
		Widget		toplevel;

		toplevel = ToplevelGet (gw);
		XtUnmapWidget (toplevel);	/* make it disappear quickly */
		XtDestroyWidget (toplevel);
		exit (0);
	}

One can see that the above code exit's immediately after destroying
the toplevel widget.  The trouble is the phase 2 destruction may never
occur.  

This works for most widgets and most applications but will not work
for those widgets that have any external state.  You might think that
since it works now it will always work but remember that part of the
reason an object oriented approach is used is so one can be ignorant
of the implementation details for each widget.  Which means that the
widget may change and someday require that some external state is
cleaned up by the Destroy callbacks.

One alternative is to modify ExitCallback() to set a global flag and
then test for that flag in a private event loop.
Or try the following code:

	#include <X11/Intrinsic.h>

	extern Widget ToplevelGet (
	#if NeedFunctionPrototypes
		Widget		gw
	#endif
	);

	extern Boolean ExitWorkProc (
	#if NeedFunctionPrototypes
		XtPointer	closure
	#endif
	);

	extern void ExitCallback (
	#if NeedFunctionPrototypes
		Widget		gw,
		XtPointer	closure,
		XtPointer	call_data
	#endif
	);

	Widget
	ToplevelGet (gw)
	Widget		gw;		/* widget to find toplevel */
	{
		Widget		top;

		for (top = gw; XtParent (top); top = XtParent (top))
			/* empty */;
		return (top);
	}


	void
	ExitCallback (gw, closure, call_data)
	Widget		gw;		/* widget */
	XtPointer	closure;	/* data the app specified */
	XtPointer	call_data;	/* widget specific data */
	{
		Widget		toplevel;

		toplevel = ToplevelGet (gw);
		XtUnmapWidget (toplevel);	/* make it disappear quickly */
		XtDestroyWidget (toplevel);
		XtAppAddWorkProc (XtWidgetToApplicationContext (gw),
				  ExitWorkProc, (XtPointer) NULL);
	}

	Boolean
	ExitWorkProc (closure)
		XtPointer	closure;
	{
		exit (0);
		/*NOTREACHED*/
	}


ExitCallback() adds a work procedure that will get called when the
application is next idle -- which happens after all the events are
processed and the destroy callbacks are executed.

User Contributions:

Comment about this article, ask questions, or add new information about this topic: