[comp.windows.x] Proper modal dialogs using Xt -- can it be done?

giguere@csg.UWaterloo.CA (Eric Giguere) (07/17/90)

This question was originally posted in the Motif newsgroup but no one's been
able to answer it for me so:

I want to create and display a modal dialog created as a widget under Motif.
That is, after I add callback routines, manage & display the widget, I want
my main program to wait (without busy-waiting!) until the widget is 
destroyed and not accept input into its main window while the dialog widget
is being displayed.  All the dialog examples I've seen so far that use the
Xt or Motif widget sets use modeless dialogs.

So, can I do this portably using X or do I have to resort to using system
calls such as the Unix signalling facility?

--
Eric Giguere                                       giguere@csg.UWaterloo.CA

scott@graft.Berkeley.EDU (Scott Silvey) (07/17/90)

giguere@csg.UWaterloo.CA (Eric Giguere) writes:
|> This question was originally posted in the Motif newsgroup but no one's been
|> able to answer it for me so:
|> 
|> I want to create and display a modal dialog created as a widget under Motif.
|> That is, after I add callback routines, manage & display the widget, I want
|> my main program to wait (without busy-waiting!) until the widget is 
|> destroyed and not accept input into its main window while the dialog widget
|> is being displayed.  All the dialog examples I've seen so far that use the
|> Xt or Motif widget sets use modeless dialogs.
|> 
|> So, can I do this portably using X or do I have to resort to using system
|> calls such as the Unix signalling facility?
|> 
|> --
|> Eric Giguere                                       giguere@csg.UWaterloo.CA

You need to go through an event processing loop while the dialog is up.

This was far from obvious for me too, perhaps R5 could have a "convenience" 
  routine to pop up a modal dialog.

Here is the basic code needed:
------------------------------

Boolean ok=FALSE;

ok_button_cback(button, dialog_shell)
Widget button, dialog_shell
{
	extern Boolean ok;

	/* Do useful things here. */
	ok = TRUE;
	XtPopdown(dialog_shell);
}

prompt()
{
	extern Boolean ok;
	extern Widget toplevel;
	XEvent event;
	Widget dialog_shell, ok_button;

	dialog_shell = XtCreatePopupShell("Modal Dialog", transientShellWidgetClass,
	                                   toplevel, NULL, 0);
	ok_button = XtCreateManagedWidget("OK", commandWidgetClass,
dialog_shell, NULL, 0);
	XtAddCallback(ok_button, XtNcallback, ok_button_cback, dialog_shell);

	XtPopup(dialog_shell, XtGrabExclusive);

	while (!ok) {
		XtAppNextEvent(XtWidgetToApplicationContext(toplevel), &event);
		XtDispatchEvent(&event);
	}
	ok = FALSE;
}

-----------------------------

Note that this is for R4 Athena widgets.  You'll have to tailor the
details for 
  your case (probably R3 Motif?).  Also, I just typed this in from memory, so
  I'm not guaranteeing that I didn't forget something here, but the basic idea
  is demonstrated.  I also don't know if perhaps there are other/better ways to
  approach this problem either, I just know it works for me.

Hope this helps.

Scott

schoeller@clt.enet.dec.com (Dick Schoeller) (07/17/90)

> |> This question was originally posted in the Motif newsgroup but no one's
been
> |> 
> |> I want to create and display a modal dialog created as a widget under
Motif.
> |> That is, after I add callback routines, manage & display the widget, I
want
> |> my main program to wait (without busy-waiting!) until the widget is 
> |> destroyed and not accept input into its main window while the dialog
widget
> |> is being displayed.  All the dialog examples I've seen so far that use the
> |> Xt or Motif widget sets use modeless dialogs.
> |> 
> |> So, can I do this portably using X or do I have to resort to using system
> |> calls such as the Unix signalling facility?
> |> 
> |> --
> |> Eric Giguere                                      
giguere@csg.UWaterloo.CA
> 
> You need to go through an event processing loop while the dialog is up.

This is not entirely true.  If you are simply waiting for a required input,
you can deal with it as a callback and not use a special "main loop".  The
XtAddGrab done by the modal dialog box will prevent input going to other
widgets than the modal box.  This would break the functionality into a
"display" procedure and a callback.

If, however, you desire a function which displays the box and does not return
until the box has been dismissed then Scott Silvey's approach is needed.

If you have displayed a modal box while performing a lengthy operation, you
can either use your own mini-"main loop" to check the box (if the box has
a cancel button) and handle exposures.  This would be called occasionally
during the lengthy procedure.  The result of a "cancel" would indicate that
you should clean up and terminate the lengthy operation.

If you don't want to allow cancel and are simply using the box as an indicator,
you can just call XmUpdateDisplay. This will only process expose events.

Dick Schoeller                  | schoeller@clt.enet.dec.com
Digital Equipment Corporation   | 603-881-2965
110 Spit Brook Rd., ZKO2-3/R56  | "Either Judaism has something to say to the
Nashua, NH 03062-2642           | world or it has nothing to say to Jews."
                                |                             - Dennis Prager

lockheed@Hudson.Stanford.EDU (Lockheed) (07/17/90)

>> This question was originally posted in the Motif newsgroup but no one's been
>> able to answer it for me so:
>>
>> I want to create and display a modal dialog created as a widget under Motif.
>> That is, after I add callback routines, manage & display the widget, I want
>> my main program to wait (without busy-waiting!) until the widget is
>> destroyed and not accept input into its main window while the dialog widget
>> is being displayed.  All the dialog examples I've seen so far that use the
>> Xt or Motif widget sets use modeless dialogs.
>>
>> So, can I do this portably using X or do I have to resort to using system
>> calls such as the Unix signalling facility?
>>
>> --
>> Eric Giguere                                       giguere@csg.UWaterloo.CA
>>

I previously e-mailed a solution to another person who raised the same
question, but I guess I'll post it this time. I'm using HP widgets,
but the following piece of code is pure "Xt" and may work for Motif.
(Actually the person told me it did work for Motif.)

Ik

/*****************************************************************************/

static int exit_flag, exit_value;

/* dialog_shell should be a popup shell widget */
int modal_dialog(dialog_shell)
     Widget dialog_shell;
{
  XEvent event;
  XtAppContext context;

  context = XtWidgetToApplicationContext(dialog_shell);
  exit_flag = FALSE;

  XtPopup(dialog_shell, XtGrabNonexclusive);

  while (! exit_flag) {

    XtAppNextEvent(context, &event);
    XtDispatchEvent(&event);
  }

  XtPopdown(dialog_shell);

  return(exit_value);
}

/* callback function for the "yes" button */
static void yes_button_action(w, client_data, call_data)
     Widget w;
     caddr_t client_data, call_data;
{
  exit_value = TRUE;
}

/* callback function for the "no" button */
static void no_button_action(w, client_data, call_data)
     Widget w;
     caddr_t client_data, call_data;
{
  exit_value = FALSE;
}

/*****************************************************************************/

   -------------------------------------------------------------------------
 /                                    |                                      \
|      Ik Su Yoo                      |                                       |
|      Lockheed AI Center             |   Office: (415) 354-5584              |
|      Orgn. 96-20, Bldg. 259         |   Fax:    (415) 354-5235              |
|      3251 Hanover St.               |   E-mail: ik@laic.lockheed.com        |
|      Palo Alto, CA  94304-1191      |                                       |
 \                                    |                                      /
   -------------------------------------------------------------------------