[comp.windows.x.motif] XmUpdateDisplay fails

alice@athena.mit.edu (Timothy R Wall) (04/05/91)

I use XmUpdateDisplay to refresh my application before starting a long
load from disk and subsequent calculation.  Immediately after
XmUpdateDisplay I call a routine to change the cursor, which calls
XFlush; I see the cursor change, but no screen update.  What's wrong?

thanks
trw

dbrooks@osf.org (David Brooks) (04/06/91)

alice@athena.mit.edu (Timothy R Wall) writes:
|> I use XmUpdateDisplay to refresh my application before starting a long
|> load from disk and subsequent calculation.  Immediately after
|> XmUpdateDisplay I call a routine to change the cursor, which calls
|> XFlush; I see the cursor change, but no screen update.  What's wrong?

The cursor change is done by the server, and happens as soon as it gets the
request.  No mystery there.

XmUpdateDisplay performs a XSync(), and then processes all outstanding
events.  What it must not do is block.  The theory is that after the Sync,
all the Expose events resulting from mapping the dialog windows (the
commonest use of this) are in the Xlib queue and can be processed before
continuing.

This turns out not to be the case.  The server may have delivered the
events, but the client hasn't received them yet.  There's a timing issue,
which may (or not) involve the window manager, and some of us are looking
into a better solution.  For now, you can try:

	XSync(XtDisplay(toplevel), 0);
	usleep(<some-number-found-empirically>);
	XmUpdateDisplay(toplevel);

where <some-number-found-empirically> on my workstation is 60000.
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
Experience is what lets us recognize a mistake the second time we make it.

cliu@osf.org ("Chauncy Liu") (04/08/91)

  >  I use XmUpdateDisplay to refresh my application before starting a long
  >  load from disk and subsequent calculation.  Immediately after
  >  XmUpdateDisplay I call a routine to change the cursor, which calls
  >  XFlush; I see the cursor change, but no screen update.  What's wrong?
  >  
     I think you already received mail form David Brooks, he gave some idea how
this is happening. In the workaround, if the time to sleep is short, and the process
is huge, this will not guarantee you for a total display update before your process
begin (you have to wait till your process end then your display will be
updated totally
afterward).

  My suggestion is make a routine to update your display which guarantee display is
updated before further process

void My_Update_Display_Routine(w)
Widget w;
{
  XtAppContext app;
  Boolean BREAK = False;

  app = XtDisplayToApplicationContext(XtDisplay(w));
  XmUpdateDisplay(w);
  XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True);
  for(;!BREAK;)
  {
    XEvent event;
    XtAppNextEvent(app, &event);
    switch(event.type)
    {
      /* Dump all the user generated events at the time of displaying */
      case KeyPress :
      case KeyRelease :
      case ButtonPress :
      case ButtonRelease :
      case MotionNotify :
        break;
      case Expose :
        if (event.xexpose.window == XtWindow(w)) BREAK = True;
      default :
        XtDispatchEvent(&event);
        break;
    }
  }
  XmUpdateDisplay(w);
  XFlush(XtDisplay(w));
}

Hope this helps
Chauncy Liu / OSF System Engineer

daniel@cs.UAlberta.CA (Daniel Lanovaz) (04/08/91)

In article <20738@paperboy.OSF.ORG> dbrooks@osf.org (David Brooks) writes:
>alice@athena.mit.edu (Timothy R Wall) writes:
>|> I use XmUpdateDisplay to refresh my application before starting a long
>|> load from disk and subsequent calculation.  Immediately after
>|> XmUpdateDisplay I call a routine to change the cursor, which calls
>|> XFlush; I see the cursor change, but no screen update.  What's wrong?
>
>This turns out not to be the case.  The server may have delivered the
>events, but the client hasn't received them yet.  There's a timing issue,
>which may (or not) involve the window manager, and some of us are looking
>into a better solution.  For now, you can try:
>
>	XSync(XtDisplay(toplevel), 0);
>	usleep(<some-number-found-empirically>);
>	XmUpdateDisplay(toplevel);
>
>where <some-number-found-empirically> on my workstation is 60000.

Is it possible to process events sent from the server while in a compute-
bound system module by having the events interrupt your process while it is
computing?  I have experimented with something like the following.  It seems
to work with the programs I use it in, but there may be problems I don't
see (for instance, what to do if the SIGIO interrupt was not generated by
the ConnectionNumber(Display) socket)?

    InstallEventHandler(topLevel);
    DoSomeVeryLongCalculation();
    RemoveEventHandler(topLevel);

    XEventHandler(/* Some parameters here */)
    {
        XEvent anEvent;

        while(XtPending()) {
            XtNextEvent(&anEvent);
            XtDispatchEvent(&anEvent);
        }
    }

    InstallEventHandler(Widget topLevel)
    {
        Display *theDisplay = XtDisplay(topLevel);
        int connectNumber   = ConnectionNumber(theDisplay);

        signal(SIGIO, XEventHandler);

        if (fcntl(connectionNumber, F_SETFL, FASYNC) < 0) {
            perror("Some error message");
            return ERROR_OF_SOME_SORT;
        }

        if (fcntl(connectionNumber, F_SETOWN, getpid()) < 0) {
            perror("Some error message");
            return ERROR_OF_SOME_SORT;
        }

        XFlush(theDisplay);

        return EVERTHING_WENT_OK;
    }

Daniel
daniel@cs.ualberta.ca