[comp.windows.x] Motif and "work-in-progress"

vania@osf.ORG (Vania Joloboff) (02/06/90)

"mike%snowhite.cis.uoguelph.ca@mitvma.mit.edu" submitted a while ago a
problem with OSF/Motif "work-in-progress" widget.  When the work in
progress takes too many cycles, the dialog box don't get the expose
necessary to tell the user there is work in progress...

Here follows a work around proposed by Bill Wilhelmi from HP,
Thanks Bill.

/******************************************************************
 ***   
 ***   Here is a solution to the popup problem.  What I had to do
 ***   was remove the processing in the callback from the function
 ***   that manages the message box.  The background routine
 ***   is now in a focus callback registered for the 
 ***   message box.  To avoid calling the callback whenever the 
 ***   pointer is moved, the focus callback removes itself.  This 
 ***   ensures that the callback is called only once whenever the
 ***   message box is popped up.  When the message box is popped 
 ***   down, an unmap callback is used to install the focus 
 ***   callback again.  
 ***
 ***   The only problem I can see with this solution, is that if you
 ***   click the pushbutton and then move the pointer fast enough,
 ***   the message box will pop up without gaining focus.  The focus
 ***   callback won't be called until the pointer is moved back into
 ***   the message box.  
 ***
 ***   I tried other solutions, including event handlers.  This seems
 ***   to be the best reasonable workaround to the problem that I have
 ***   found. 
 ***
 ***  
 ***
         Bill Wilhelmi  
 USMail: Hewlett-Packard - Interface Technology Operation
         1000 NE Circle Blvd.  Corvallis, OR 97330
 ARPA:   bw%hp-pcd@hplabs.HP.COM or  <bw@hpcvlx.cv.hp.com> 
 UUCP:   {ihnp4, cmcl2, decvax, sun, rice, tektronix}!hplabs!hp-pcd!bw


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

#include <Xm/BulletinB.h>
#include <Xm/PushB.h>
#include <Xm/MessageB.h>

void push1(wid, info, call_data)
Widget wid;
Widget info;
caddr_t call_data;
{
 XtManageChild(info);
 /* The popup won't be drawn until XtMainLoop is able to deal
  * with all the expose events for the widget.  Therefore, we
  * don't want to do any other processing here.  Rather, wait
  * until the message box gets mapped and receives the focus.
  * Add a focus callback to do the other processing.
  */
}

void push2(wid, client_data, call_data)
Widget wid;
caddr_t client_data;
caddr_t call_data;
{
 int i;
 for (i=0;i<300;i++)
    printf("hi %d\n",i);
 XtRemoveCallback(wid, XmNfocusCallback, push2, NULL);
 /* We want to do our background processing the first time the
  * message box receives focus.  Alternatively, you could 
  * unmanage the message box when processing is done.
  */
}

void push3(wid, client_data, ev)
Widget wid;
caddr_t client_data;
XEvent *ev;
{
XtAddCallback(wid, XmNfocusCallback, push2, NULL);
}


void main(argc, argv)
  unsigned int argc;
  char **argv;
{
   Widget toplevel, bboard, pbutton, info;
   Arg myArgs[10];
   int i;
     
   toplevel = XtInitialize(argv[0], "Lab02", NULL, 0, &argc, argv);

   bboard = XmCreateBulletinBoard(toplevel, "bb", myArgs, 0);
   XtManageChild(bboard);

   info = XmCreateInformationDialog(bboard, "info", myArgs, 0);

   pbutton = XmCreatePushButton(bboard, "pbutton", myArgs, 0);

   XtManageChild(pbutton);
   XtAddCallback(pbutton, XmNactivateCallback,push1, info);
   XtAddCallback(info, XmNfocusCallback, push2, NULL);
   XtAddCallback(info, XmNunmapCallback, push3, NULL);

   XtRealizeWidget(toplevel);
   XtMainLoop();
}

marbru@auto-trol.UUCP (Martin Brunecky) (02/07/90)

In article <9002052045.AA16268@osf.osf.org> vania@osf.ORG (Vania Joloboff) writes:
>
>"mike%snowhite.cis.uoguelph.ca@mitvma.mit.edu" submitted a while ago a
>problem with OSF/Motif "work-in-progress" widget.  When the work in
>progress takes too many cycles, the dialog box don't get the expose
>necessary to tell the user there is work in progress...
>
>Here follows a work around proposed by Bill Wilhelmi from HP,
>Thanks Bill.
>
	.... code deleted ....

Using a focus event is fine, especially since Motif widgets have a callback
for it - but using map event would be more generic, i.e. would work even
for widgets which do NOT take intput focus. 

I am not 100% sure what the X protocol says about expose event order, but
I tend to beleve that expose event for subwindows will FOLLOW the one for
the parent window. 
Thus, waiting for the focus (or map) and expose event on the main widget
will NOT be enough - it's children's events will still be in a queue.
This may not be visible where Gadgets are used (Gadgets are repainted
on parent's expose), but definitly will cause troubles in case of subwindows
- such as "real" widgets.

Toolkits like Motif should provide something like "XmForceDisplay" routine,
using techniques similar to Motif MenuShell (but in a generic fashion):
	- popup the shell (and PLEASE, don't replace XtPopup by XtManage...)
	- XSync or some wait for map event on the shell
	  (no wait on OverrideShell, wait for WM action on others)
	- traverse the widget tree starting with shell, 
	  calling "expose" method for each WindowObject with
	  an artificial expose event/region to force redisplay
	- remove expose events for all windows touched above
	  to avoid double repaint.

To do everything correctly requires more code and XtIntrinsic internals
knowledge than appropriate for application code - therefore it should
be a part of the toolkit.
 
-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
Martin Brunecky                   marbru@auto-trol.COM
(303) 252-2499                    {...}ncar!ico!auto-trol!marbru
Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404