Path: utzoo!utgpu!watmath!att!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!odi!mlm From: mlm@odi.com (Mitchell Model) Newsgroups: comp.windows.x Subject: Re: help Message-ID: <1989Aug15.213710.3103@odi.com> Date: 15 Aug 89 21:37:10 GMT References: <3982@ncar.ucar.edu> Organization: Object Design, Inc. Lines: 306 In-reply-to: clyne@redcloud.ucar.edu's message of 14 Aug 89 23:10:24 GMT In article <3982@ncar.ucar.edu> clyne@redcloud.ucar.edu (John Clyne) writes: This should not be too hard to do but I haven't been able to figure out a simple solution: I want to have a generic warning routine, call it display_warning(), that when invoked will popup and display a warning message (under the Xt instrinics) and require the user to select a proceed or cancel button. The problem is that I want display_warning() to return a value depending on the user's selection. How do I get display_warning() to wait until a selection has been made before returning?. display_warning() also needs to know which selection has been made and indicate this in the return. Is there a simple way to due this? One way is to do the following after XtPopup(shell, XtGrabExclusive): flag = True; while (flag) ProcessOneEvent(XtDisplay(shell)); return result; with: void ProcessOneEvent(display) Display *display; { static XEvent event; XNextEvent(display, &event); XtDispatchEvent(&event); } There's a further trick, though: your callback functions have to set result, popdown shell, and set flag to false. There are various ways to do this, all awkward, including global variables and packaging up stuff like this into a record that you provide as the client_data for the callback. Here's the complete code for a Yes/No confirmation widget. I originally took this code from contrib/hacks/xpostit/confirm.c then hacked it up to wait for user response as well as add some other features my application needed (in particular warping the cursor back to where it was before the confirmation popped up). Thanks to David Curry, xpostit author, for xpostit: a really useful utility and a source of well-structured, commented, and X-instructive code. Mitchell L Model Director, HeadStart Program Object-Design, Inc. One New England Park Burlington MA 01803 (617) 270-9797 mlm@odi.com ============================================================================== /* confirm -- copied from $x/contrib/hacks/xpostit/confirm.c and xpostit.h then modified to be simpler -- not use callbacks, just return true or false */ /* mlm: 5-17-89 added wait loop 3-17-89 changed to just return Bool 3-16-89 added toplevel to ConfirmIt arg list, to make this completely independent */ #include/* for Bool, etc. */ #include #include #include #include #include #include #include #include "confirm.h" #include "xutil.h" /* from xpostit.h */ #define SetArg(which, val) XtSetArg(args[nargs], (which),\ (XtArgVal) (val)); nargs++ typedef struct _result { Bool *popflg, *var; int root_x, root_y; Window root; Widget shell; } *Result; static Result MakeResult(shell, popflg, resultvar, root, root_x, root_y) Bool *popflg, *resultvar; Window root; int root_x, root_y; Widget shell; { Result rec = (Result) malloc(sizeof(struct _result)); rec->popflg = popflg; rec->var = resultvar; rec->root = root; rec->root_x = root_x; rec->root_y = root_y; rec->shell = shell; return rec; } /* ARGSUSED */ /* * ClearConfirm - get rid of the confirmation box. */ /* ARGSUSED */ void ClearConfirm(w, val, result) Widget w; Bool val; Result result; { Display *display = XtDisplay(w); XtPopdown(result->shell); XtDestroyWidget(result->shell); *result->popflg = False; *result->var = val; XWarpPointer(display, None, result->root, 0, 0, 0, 0, result->root_x, result->root_y); } /* ARGSUSED */ static void Yes(w, result, call_data) Widget w; Result result; caddr_t call_data; /* unused */ { ClearConfirm(w, True, result); } /* ARGSUSED */ static void No(w, result, call_data) Widget w; /* unused */ Result result; caddr_t call_data; { ClearConfirm(w, False, result); } #define btnsepr 8 static void adjust(label, yes, no) Widget label, yes, no; { Arg args[2]; int nargs; int labelwidth, yeswidth, btnborder, btnwidth; if (!label) labelwidth = 0; else { nargs = 0; SetArg(XtNwidth, NULL); XtGetValues(label, args, 1); labelwidth = args[0].value; } nargs = 0; SetArg(XtNwidth, NULL); SetArg(XtNborder, NULL); XtGetValues(yes, args, 2); yeswidth = args[0].value; btnborder = args[1].value; btnwidth = (labelwidth-btnsepr-4*btnborder)/2; if (btnwidth < yeswidth) btnwidth = yeswidth; nargs = 0; SetArg(XtNwidth, btnwidth); XtSetValues(yes, args, 1); XtSetValues(no, args, 1); } /* * Confirm - put up a window asking for confirmation. */ Bool Confirm(toplevel, prompt) Widget toplevel; char* prompt; { static Arg args[4]; register int nargs; static Bool inited = False; Bool poppedup=False, result=False; static Widget shell, form, label, yes, no; static int root_x, root_y, child_x, child_y, buttons; static Window root, child; static Result resultrec; inited = False; /* recreate each time for now */ /* * Find out where the mouse is, so we can put the confirmation * box right there. */ XQueryPointer(XtDisplay(toplevel), XtWindow(toplevel), &root, &child, &root_x, &root_y, &child_x, &child_y, &buttons); /* * If we need to construct the confirmation box do that, * otherwise just reset the position and callbacks and * put it up again. */ if (!inited) { nargs = 0; SetArg(XtNx, root_x); SetArg(XtNy, root_y); SetArg(XtNinput, True); shell = XtCreatePopupShell("Confirm", transientShellWidgetClass, toplevel, args, nargs); nargs = 0; form = XtCreateManagedWidget("form", formWidgetClass, shell, args, nargs); if (!prompt) label = NULL; else { nargs = 0; SetArg(XtNlabel, prompt); SetArg(XtNborderWidth, 0); label = XtCreateManagedWidget("prompt", labelWidgetClass, form, args, nargs); } nargs = 0; if (prompt) { SetArg(XtNfromVert, label); SetArg(XtNvertDistance, 12); } yes = XtCreateManagedWidget("yes", commandWidgetClass, form, args, nargs); nargs = 0; SetArg(XtNfromHoriz, yes); SetArg(XtNhorizDistance, btnsepr); if (prompt) { SetArg(XtNfromVert, label); SetArg(XtNvertDistance, 12); } no = XtCreateManagedWidget("no", commandWidgetClass, form, args, nargs); adjust(label, yes, no); XtRealizeWidget(shell); inited = True; } else { /* * Reset the confirmation box position. */ nargs = 0; SetArg(XtNx, root_x); SetArg(XtNy, root_y); XtSetValues(shell, args, nargs); } resultrec = MakeResult(shell, &poppedup, &result, root, root_x, root_y); XtAddCallback(yes, XtNcallback, Yes, resultrec); XtAddCallback(no, XtNcallback, No, resultrec); XtPopup(shell, XtGrabExclusive); poppedup = True; while(poppedup) ProcessOneEvent(XtDisplay(shell)); return result; } #undef btnsepr -- Mitchell L Model Director, HeadStart Program Object-Design, Inc.