[comp.windows.x.motif] Nested PopupShells and XtDestroyWidget

roger@zuken.co.jp (Roger Meunier) (04/30/91)

I've included a test program which illustrates a problem I am having
managing nested PopupShells.  The main window ("mainw") is of class
topLevelShellWidgetClass.  From here, I popup another topLevelShellWidgetClass
window ("secondary") which has a xmDialogShellWidgetClass child ("panel").

Pressing mainw's "Start" button creates and displays secondary and panel.
If I press panel's "Quit" button and then secondary's "Quit2" button,
both of these PopupShells are cleanly destroyed, and I can repeat this
sequence of operation (start, quit, quit2) until the cows come home.

But if I press secondary's "Quit'" button instead of panel's "Quit",
I internally call XtDestroyWidget() for panel AND secondary, then
return to the event loop.  The next time I try this sequence of
operation (start, quit'), I get:

	X Protocol error detected by server:  BadGC, invalid GC parameter
	  Failed request major op code 70 (X_PolyFillRectangle)
	  Failed request minor op code 0 (if applicable)
	  ResourceID 0x1300002 in failed request (if applicable)
	  Serial number of failed request 238
	  Current serial number in output stream 240

For some reason, it doesn't like me to destroy both popups without
an intervening pass through the event loop.  Any reason why this should
be?

I'm using Motif 1.0 with X11R3 under HP-UX 7.03.


----------------------- Cut Here -----------------------------------------
#include <Xm/Xm.h>
#include <X11/Shell.h>
#include <Xm/DialogS.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/CascadeB.h>
#include <Xm/PushB.h>

XrmOptionDescRec	options[] = {
{"-fl",         "*fontList",    XrmoptionSepArg,        (caddr_t)"variable"},
};

Display*	display;

typedef	struct {
	Widget	main;
	Widget	panel;
} widgets;

void	DoQuit(w, flag, call_data)
Widget	w;
int	*flag;
XmAnyCallbackStruct	*call_data;
{
	exit(0);
}

void	DoQuit2(w, me, call_data)
Widget	w;
Widget	me;
XmAnyCallbackStruct	*call_data;
{
	XtDestroyWidget(me);
}

void	DoQuitP(w, data, call_data)
Widget	w;
widgets*	data;
XmAnyCallbackStruct	*call_data;
{
	/**  THIS IS WHERE THE ACTION IS!!!!!!!!  **/
	XtDestroyWidget(data->panel);
	XtDestroyWidget(data->main);
	free(data);
}

void	DoStart(w, parent, call_data)
Widget	w;
Widget	parent;
XmAnyCallbackStruct	*call_data;
{
	Widget	main_w,form_w,menu_bar,quit_b,quitp_b;
	Widget	panel;
	Arg	args[10];
	short	cnt;
	widgets*	data;

	XUngrabPointer(display,CurrentTime);
	XUngrabKeyboard(display,CurrentTime);
	XFlush(display);

	cnt = 0;
	XtSetArg(args[cnt],XmNwidth,200); cnt++;
	XtSetArg(args[cnt],XmNheight,200); cnt++;
	main_w = XtCreatePopupShell("secondary",topLevelShellWidgetClass,
			parent,args,cnt);
	XtManageChild(main_w);
	form_w = XmCreateForm(main_w,"form", args, cnt);
	XtManageChild(form_w);

/** shouldn't need to set args, but geometry management is buggy!!!!  **/
	cnt = 0;
	XtSetArg(args[cnt],XmNwidth,200); cnt++;
	XtSetArg(args[cnt],XmNheight,30); cnt++;
	menu_bar = XmCreateMenuBar(form_w,"menu",args, cnt);
	XtManageChild(menu_bar);
	quit_b = XtCreateManagedWidget("Quit2",xmCascadeButtonWidgetClass,
			menu_bar,NULL,0);
	XtAddCallback(quit_b,XmNactivateCallback,DoQuit2,main_w);
	quitp_b = XtCreateManagedWidget("Quit'",xmCascadeButtonWidgetClass,
			menu_bar,NULL,0);
	data = (widgets*)malloc(sizeof(widgets));
	data->main = main_w;
	XtAddCallback(quitp_b,XmNactivateCallback,DoQuitP,data);

	XtRealizeWidget(main_w);
	XtPopup(main_w,XtGrabNone);

	/*** attach popup panel ***/
	cnt = 0;
	XtSetArg(args[cnt],XmNwidth,100); cnt++;
	XtSetArg(args[cnt],XmNheight,100); cnt++;
	panel = XtCreatePopupShell("panel",xmDialogShellWidgetClass,
			form_w,args,cnt);
	data->panel = panel;
	form_w = XmCreateForm(panel,"Form", args, cnt);

	quit_b = XtCreateManagedWidget("Quit",xmPushButtonWidgetClass,
			form_w,NULL,0);
	XtAddCallback(quit_b,XmNactivateCallback,DoQuit2,panel);
	XtManageChild(form_w);
}

main(argc, argv)
int     argc;
char    *argv[];
{
	Widget	toplevel;
	Widget	main_w,form_w,menu_bar,quit_b,start_b;
	Arg	args[10];
	short	cnt;

	XtToolkitInitialize();
	display = XtOpenDisplay(NULL,NULL,"xytest","xytest", options, 0, &argc, argv);
	if (!display) {
		printf("Cannot open display!\n");
		exit(-1);
	}
	cnt = 0;
	XtSetArg(args[cnt],XmNwidth,300); cnt++;
	XtSetArg(args[cnt],XmNheight,300); cnt++;
	toplevel = XtAppCreateShell("xytest","xytest",
		applicationShellWidgetClass,display,args,cnt);

	main_w = XtCreatePopupShell("mainw",topLevelShellWidgetClass,
			toplevel,args,cnt);
	XtManageChild(main_w);
	form_w = XmCreateForm(main_w,"Form", args, cnt);
	XtManageChild(form_w);

	menu_bar = XmCreateMenuBar(form_w,"Menu",NULL,0);
	XtManageChild(menu_bar);
	quit_b = XtCreateManagedWidget("Quit",xmCascadeButtonWidgetClass,
			menu_bar,NULL,0);
	XtAddCallback(quit_b,XmNactivateCallback,DoQuit,NULL);
	start_b = XtCreateManagedWidget("Start",xmCascadeButtonWidgetClass,
			menu_bar,NULL,0);
	XtAddCallback(start_b,XmNactivateCallback,DoStart,form_w);

	XtRealizeWidget(main_w);
	XtPopup(main_w,XtGrabNone);

	XtMainLoop();
}

----------------------- Cut Here -----------------------------------------
--
Roger Meunier @ Zuken, Inc.  Yokohama, Japan	(roger@zuken.co.jp)