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