[comp.windows.x] Browsing Event Queue

Jean-Christophe.Dhellemmes@MAPS.CS.CMU.EDU (09/13/90)

Hello out there,

I use X11R4 and the Xt toolkit.

In one of my applications, a refresh procedure takes a long time to execute
(drawing thousands of segments in a window). While it is going on, it is
possible to resize, or reexpose the window in which it is drawing, thus
making the current state out of date. The problem is I still have to wait a
long time before the refresh procedure stops and starts again with the new
parameters.

I would like to be able to browse through the entire event queue in my
refresh loop and interrupt the refresh loop if an expose or resize event is
in the queue. I know how to get the first event in the queue without
removing it (XtAppPeekEvent()) but as an XEvent structure does not include a
pointer to the next event, I don't know how to go through the entire queue.

I think that XtAppPeekEvent copies the data to the user's XEvent structure,
so casting the returned event in a _XQEvent structure will not work (it is a
hack, anyway).

- Is there an official way to do what I need (like getting a pointer to the
event queue) ? 

- Is there another method ?

Any info will be highly appreciated. Thanks.

							* ][]

---------------------------------------------------------------------------
  Jean-Christophe DHELLEMMES. e-mail (jcd@maps.cs.cmu.edu) (412-268-8801)
        Carnegie Mellon University - School of Computer Science.
               5000 Forbes avenue Pittsburgh PA 15213.
---------------------------------------------------------------------------

mouse@LARRY.MCRCIM.MCGILL.EDU (09/13/90)

> In one of my applications, a refresh procedure takes a long time to
> execute (drawing thousands of segments in a window).  While it is
> going on, it is possible to resize, or reexpose the window in which
> it is drawing, thus making the current state out of date.  The
> problem is I still have to wait a long time before the refresh
> procedure stops and starts again with the new parameters.

> I would like to be able to browse through the entire event queue in
> my refresh loop and interrupt the refresh loop if an expose or resize
> event is in the queue.

> - Is there an official way to do what I need (like getting a pointer
>   to the event queue) ?

Have a look at the Xlib functions XCheckMaskEvent, XCheckTypedEvent,
XCheckTypedWindowEvent, or XCheckWindowEvent.  One or more of those can
probably do what you want.  If not, there's XCheckIfEvent, which seems
like a bit of a sledgehammer but which surely can do it.

However, there's another problem: once you have the event, what do you
do with it?  As far as I can tell there is no way to look for a certain
type of event without blocking or removing it from the queue.  There
are functions to look for events without blocking, and functions to
look for events without dequeueing them, but as far as I can see none
that do both.  This means that since you don't want to block, you're
forced to dequeue the event.  But then you are stuck with an event that
you don't want to process out of sequence, but you can't just drop.

Another possibility would be to write your own event dispatch loop (I
gather this is fairly straightforward) and then manage your own event
queue.  It's a bit ugly but it seems to be the cleanest solution
available, until/unless Xlib provides some function combining the
non-blocking property of the XCheck* calls with the non-dequeueing
property of the XPeek* calls.  It might be possible to kludge something
together with XPutBackEvent, but it would, I fear, be just that:
kludged together.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

jcb@frisbee.Sun.COM (Jim Becker) (09/14/90)

Jean-Christophe.Dhellemmes@MAPS.CS.CMU.EDU writes:


   I would like to be able to browse through the entire event queue in my
   refresh loop and interrupt the refresh loop if an expose or resize event is
   in the queue.

   - Is there an official way to do what I need (like getting a pointer to the
   event queue) ? 

I've  had  need  to  do  the same sort of thing. Wanted to avoid doing
exposure  processing if there are more exposure events in the incoming
queue. Didn't  find  anything  efficient  and  suitable  in  the  Xlib
grabbag.

   - Is there another method ?

Yes,  look  at  the  events that hang off the display event list. Note
that  this isn't really legal, but I haven't yet had problems with it.
The same sort of code within the Xlib itself does calls  to  lock  and
unlock the display, but on Suns (last time I checked) they were noops.

Here is some code that can be used to scan the list:

/*
 *	poke down the queue to see if there are more expose events 
 * 	this looks down the display event queue to see if there is 
 *	another event that is of the exposure type. the content of
 *	the queue is not disturbed. somewhat questionable, but there
 *	is no mechanism that doesn't disturb the queue in Xlib.
 */
no_more_expose( display, window )
Display		*display;
Window		window;
{
struct	_XSQEvent	*qevent;
        Window		ewin;
        int		etype;
	short		found	= FALSE;

        for( qevent  = display->head;
	     qevent != NULL && !found;
	     qevent  = qevent->next ) {

		etype	= qevent->event.xany.type;
		ewin	= qevent->event.xany.window;

		found	= ((etype == Expose) ||
			   (etype == GraphicsExpose)) &&
			   (ewin  == window);
	}

        return !found;
}


in the event processing I do this sort of logic:

	switch( xevent.type ) {

	...

	case Expose:
		/* only do the last one in the queue */
		if( no_more_expose( display, xevent.xany.window ) )
			repaint_window( args );
		break;

	...

	}


It's not directly legal, but filled a void I found in  my  needs.  One
can  get  more  exotic  additionally, in that flushing and event queue
reading  can  be  added  to  the  scan  logic.  (This is used for best
assurance  that  there  is  nothing  pending on the wire.) The example
posted is the simple case.

-Jim
--    
	 Jim Becker / jcb%frisbee@sun.com  / Sun Microsystems

argv@turnpike.Eng.Sun.COM (Dan Heller) (09/14/90)

In article <142429@sun.Eng.Sun.COM> jcb@frisbee.Sun.COM (Jim Becker) writes:
> Jean-Christophe.Dhellemmes@MAPS.CS.CMU.EDU writes:
>    I would like to be able to browse through the entire event queue in my
>    refresh loop and interrupt the refresh loop if an expose or resize event is
>    in the queue.
> Yes,  look  at  the  events that hang off the display event list. Note
> that  this isn't really legal, but I haven't yet had problems with it.

Can someone followup with this?  Why isn't this legal?  The code looks
legit to me.  If so, this seems like a pretty useful trick.  so, what';s
the scoop?

--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (09/14/90)

This seems like another of those frequently asked questions.  All it
takes is a little imagination.

    As far as I can tell there is no way to look for a certain
    type of event without blocking or removing it from the queue.

Use XCheckIfEvent.  Have your predicate *always* return False.  Maintain
the *real* boolean result (or whatever other result you want) in the
private data argument that you pass in.  If you're sensible, write a
nice wrapper function that hides this trick, so that the wrapper function
has a reasonable interface.  Call the function Xmu<something-or-other>,
and send it back to us. :-)

Call it ugly, call it a kludge, but it works and it's portable.  Yes,
it means you always walk all the way through the event queue, but the
queue shouldn't normally be that long, and quick return from your
predicate once you've found an event of interest shouldn't cost very
much.

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (09/14/90)

    Why isn't this legal?

Because the Display structure is supposed to be opaque, its internal
structure is not defined by the Xlib specification, and a vendor is
free to reimplement things like the event queue as they see fit.

jcb@eng.sun.COM (Jim Becker) (09/14/90)

  Bob Scheifler writes:

      > As far as I can tell there is no way to look for a certain
      > type of event without blocking or removing it from the queue.

   Use XCheckIfEvent.  Have your predicate *always* return False. 

   Call it ugly, call it a kludge, but it works and it's portable.  Yes,
   it means you always walk all the way through the event queue .... 


Sorry,  should  have  mentioned this as an option. The disadvantage is
walking the entire list each time, something I didn't want to do.


-Jim
--    
	 Jim Becker / jcb%frisbee@sun.com  / Sun Microsystems