[comp.windows.x] Handling expose events.

karl@mote.umb.EDU ("Karl Berry.") (08/22/89)

Two programs I've worked on recently (Metafont and Ghostscript) are
designed to work with many devices; to them, X is just another device. 
(Well, there are some differences between MF and Ghostscript as far as
the way X is used goes, but they aren't relevant for my purposes here.)

The interface between any device and the program is a set of small
procedures.  The program does all the real graphics work.

For both these programs, it is quite straightforward to implement the
interface procedures in Xlib; from what little I have read of the Xt
manual, Xlib seems far more appropriate.  It seems like overkill to
me to have a widget for these windows, when the only thing that is ever
done is drawing rectangles and lines (say).  Perhaps I'm wrong about
this; that's one of the things I'd like to know.

But there is a problem with using Xlib: handling expose events.  In
neither case does the program keep track of a bitmap representing the
current state of the window; it just makes marks as it goes along.  And
although I could write all the drawing routines to update a bitmap, that
is probably an unacceptable memory overhead, and it is certainly not
very clean.

What I would like to do is get X to tell me when part of the window is
obscured; that seems like the VisibilityNotify event.  But I also want
to get the image that was on the screen with XGetImage (or whatever; the
point is to get it from X), and thus I need the coordinates of what was
obscured.  It looked like (a) those coordinates are not available to me (I
suspect I'm wrong about this), and (b) XGetImage is not guaranteed to
work on obscured parts of windows, and I only get the event after the
window is obscured, so I'm up the creek...

The general question is: what is the best approach to this?  For
example, is it somehow possible to use Xt to handle the Expose events,
but deal with the drawing myself?

The specific question is: is it possible to handle expose events using
Xlib if a bitmap of the window's contents is not kept by the program?

Thanks for any help.

karl@umb.edu   ...!harvard!umb!karl

rws@EXPO.LCS.MIT.EDU (08/22/89)

    What I would like to do is get X to tell me when part of the window is
    obscured; that seems like the VisibilityNotify event.

Only sort-of.  It tells you when you've become obscured, but it doesn't tell
you each time a new piece becomes obscured.

    It looked like (a) those coordinates are not available to me (I
    suspect I'm wrong about this),

No, you are correct.

    and (b) XGetImage is not guaranteed to
    work on obscured parts of windows, and I only get the event after the
    window is obscured, so I'm up the creek...

Right.

    For example, is it somehow possible to use Xt to handle the Expose events,
    but deal with the drawing myself?

Nope, Xt won't solve this problem for you.

    is it possible to handle expose events using
    Xlib if a bitmap of the window's contents is not kept by the program?

Not in the way you apparently want.  The application is ultimately
responsible for window contents, and must be able to regenerate them.
Your application is (somehow) generating the contents to begin with,
it should be a SMOP to use that code to refresh after exposures.
You can turn on backing-store for the window if you think it's very
expensive to generate the contents, but this is only a hint to the
server, and you can't rely on backing-store staying around.

MAP@LCS.MIT.EDU (Michael A. Patton) (08/23/89)

I, too, have a program that draws on many different devices (although
in my case X is the focus and therefore the structure is somewhat
biased).  My tool is also based on Xlib rather than a Toolkit (for
historical reasons, I'm not sure which way I'd do it if I was starting
over).  I use a simple technique to achieve the goal you describe.
I'll relate it here with a bit of the history of how it came about
since that may aid you in understanding how to do it to your programs.

At first (and I assume this is really the stage you're at now) I just
redrew everything on any expose event.  This initially didn't seem
like a real problem since it only took a second or so, but if the user
iconifies lots of other windows, each of which overlaps my application
just a little bit, it redraws, and redraws, and ...  I did put in some
code so that if it gets behind, it doesn't redraw over and over, it
gets all the events out of the queue before actually doing the redraw.
But that still often meant three or so times which was a bit much.
Since I assume you're really looking at much longer redraw times, you
probably need the next inprovement that I mostly put in for a better
"feel".

The redraw algorithm already had a linked list of "things" to draw and
it just iterated down it drawing them.  Then as I started making the
"things" on the screen mouse sensitive, I was keeping an extent
independantly for each type that was.  I moved this up into the
"common" part of the structure and set it for all "things", if they
weren't supposed to be active, I still knew what the user was pointing
at and could produce better (sometimes) error reports.  From here it
was just a short step to having the handler for expose events iterate
down the list and set a flag in any "things" that overlapped the
region.  Then the redraw routine looks at the flag to determine what
really needs to be drawn.  I also have a "force" argument to make it
draw everything whether it needs it or not, for the initial draw and
when (at user request) I wipe the screen and do a full redraw.

I realize that this method as described does not specifically map to
your application, but I hope it helps give you (and any others
listening in) some ideas on how you might handle this problem in a
reasonably efficient way without undue impact on the structure of the
rest of your program.  If you want to discuss any details of how you
might apply this technique to your code, feel free to send me a note
with more details and I'll see what I can do.  I'm very familiar with
how my system works, but not knowing how your programs are structured
I can't really make any concrete suggestions.

	    __
  /|  /|  /|  \		Michael A. Patton, Network Manager
 / | / | /_|__/		Laboratory for Computer Science
/  |/  |/  |atton	Massachusetts Institute of Technology

Disclaimer: The opinions expressed above are a figment of the phosphor
on your screen and do not represent the views of MIT, LCS, or MAP. :-)

raveling@venera.isi.edu (Paul Raveling) (08/24/89)

	[original message not forwarded -- appears to be a response
	to a message I missed about finding a good technique to handle
	redrawing in response to an expose event]


	An easy technique with X11 (other than backing store) is
	to draw into a pixmap instead of the window, drawing only
	when necessary, and do an XCopyArea from pixmap to window.
	The XCopyArea is quite fast on our systems -- virtually
	instantantaneous on our HP 9000/370's.

	Code to respond to an Expose event is then quite simple.
	Here's a fragment from the X11 interface in our imglib source:


expose = (XExposeEvent *) &sir -> event;	/*  Point to event data	  */
	...

	switch ( (sir->event).type )
	    {
	    case Expose:	/*  Expose:  Copy area from pixmap	*/

		XCopyArea ( X11_env->display, sir->pix, sir->win, X11_env->gc,
			expose->x, expose->y, expose->width, expose->height,
			expose->x, expose->y );
		break;

	    case NoExpose:	/*  A couple noise events...		*/
	    case GraphicsExpose:
		...



----------------
Paul Raveling
Raveling@isi.edu

janssen@holmes (Bill Janssen) (08/24/89)

In article <8908220058.AA08564@mote.umb.edu>, karl@mote ("Karl Berry.") writes:
>The specific question is: is it possible to handle expose events using
>Xlib if a bitmap of the window's contents is not kept by the program?

My impression is that the only canonical solution to this problem is to
have the client draw on a Pixmap, not a Window, and to copy appropriately
from the Pixmap to the Window in response to expose events on the Window.
This has some advantages (such as separating the canvas from the viewer)
that might be exploited, but it does require twice (?) as much memory in
the server.

Anyone have a better solution?

Bill

--
 Bill Janssen        janssen.pa@xerox.com      (415) 494-4763
 Xerox Palo Alto Research Center
 3333 Coyote Hill Road, Palo Alto, California   94304

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (08/24/89)

    My impression is that the only canonical solution to this problem is to
    have the client draw on a Pixmap, not a Window, and to copy appropriately
    from the Pixmap to the Window in response to expose events on the Window.

I would hardly call this canonical.  It is one way to do it.  Whether or
not it is the best way depends a lot on your server and on the structure
of your application and the data it is trying to display.  If your application
is retaining all of the necessary data on the client side in some structured
(and hopefully higher-level) form, then regenerating the image from that data
is often a much better solution.

janssen@holmes (Bill Janssen) (08/25/89)

In article <8908241149.AA02743@expire.lcs.mit.edu>, rws@EXPO (Bob Scheifler) writes:
>...  If your application
>is retaining all of the necessary data on the client side in some structured
>(and hopefully higher-level) form, then regenerating the image from that data
>is often a much better solution.

I believe the statement of the problem specified that the data was not
kept by the client, but was written in sporadic bursts to the window
system...  Though the possibility of modifying the client to keep a
display list should not be discarded out of hand.

Bill

--
 Bill Janssen        janssen.pa@xerox.com      (415) 494-4763
 Xerox Palo Alto Research Center
 3333 Coyote Hill Road, Palo Alto, California   94304