jim@athsys.uucp (Jim Becker) (08/31/88)
In managing window interactions and refresh there I have a nagging problem that has recently compunded. I am looking for enlightenment! When managing window events, I currently process exposure events as full window re-renders. I would like to minimize the rendering as much as possible, by way of only rendering the *last* time there is an exposure event for the target window in the current event queue. Hence, I would like to skip the re-rendering in the situation where there are more xexpose events further down the queue. The "count" field seems to only apply with chained xexpose events on regions of the window, but is not global in nature to the entire event stream. All the XCheck*() calls are very nice, and would perform the needed checking logic, but they remove the matched event from the input queue. I would like to process all the events in order, as I would think that processing out-of-synch with other events would cause problems (although I have not tested this theory). Is there some method to determine globally if an exposure event (or any given event/window combination) is the last such event, with only scanning of the event queue taking place ?? This would also be helpful for other purposes, such as building damage lists of graphics redraw regions (that are complete for the entire queue) before re-rendering from a database or datastructure resource. If this functionality does not exist, maybe it could be created simply for R3 by passing NULL XEvent pointers to the XCheck*() routines. They would detect and return status, yet keep the event queue intact. -Jim Becker
josh@mit-vax.LCS.MIT.EDU (Joshua Marantz) (08/31/88)
This article brings up a good point. The existing Xlib procedures for manipulating the event queue need to be augmented. Another way to solve the redundant exposure problem would be to provide two Pending routines that do not block, and do not remove matched events from the queue. These would complement the functionality of XCheckIfEvent and XCheckMaskEvent. They might be called: XIfPending (display, event_return, predicate, arg); XMaskPending (display, event_return, event_mask, arg); Currently, I have to emulate that functionality with an XCheckIfEvent followed by an XPutBackEvent, which has the annoying side effect of rearranging the event queue. The only solution I can think of that does not require a change to Xlib is to create your own event queue and move all of X's events into it whenever there are X events pending. This permits you to define your own methods of access to the event queue. Another advantage of defining your own event queue is that you can efficiently filter out uninteresting events, check for user interrupts (like Control-C), and so on. This is more efficient than using the Xlib event manipulation functions (even with the addition of XIfPending and XMaskPending) because each event will be examined once by a filter that may flag it as either very interesting (such as an interrupt character), or very uninteresting (a redundant expose or pointer-motion event). If you leave the events in X's event queue, you must rescan the entire event queue each time you want to check for an interrupt. Note that the auxiliary event queue can utilize X's event structures, which simplifies the implementation and elliminates extraneous data copying. -Joshua Marnatz Viewlogic Systems, Inc.
RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (08/31/88)
Date: 30 Aug 88 17:54:08 GMT From: vsi1!daver!athsys!jim@AMES.ARC.NASA.GOV (Jim Becker) Is there some method to determine globally if an exposure event (or any given event/window combination) is the last such event, with only scanning of the event queue taking place ?? Yes, just think a little creatively. XCheckIfEvent takes a predicate and a "char *arg". Rather than using the Bool return from XCheckIfEvent to indicate if you have a matching event, store the outcome in the arg instead, and always return False from the predicate (so that XCheckIfEvent doesn't remove any events). To get the effect of "stopping early", your predicate will need to check the stored outcome in the arg and do nothing when it is already True (or whatever status you are looking for). Yes, this means you execute a bit more code, but somehow I doubt your event queues should be long enough for that to really matter.
RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (08/31/88)
Date: 31 Aug 88 01:30:19 GMT From: mit-vax!josh@bloom-beacon.mit.edu (Joshua Marantz) XIfPending (display, event_return, predicate, arg); XMaskPending (display, event_return, event_mask, arg); Currently, I have to emulate that functionality with an XCheckIfEvent followed by an XPutBackEvent, which has the annoying side effect of rearranging the event queue. As I pointed out in a previous posting, by using the arg value you can avoid having to pull anything out of the queue. In general, Xlib functionality is rather unlikely to change if there are reasonable ways to build "convenience" routines on top of existing functionality. That isn't to say that additional convenience routines aren't useful, just that they probably won't go into Xlib. If people feel strongly that additional routines ought to be provided in some sort of utility library on the MIT release, we're willing to listen (and take code that comes with documentation). Another advantage of defining your own event queue is that you can efficiently filter out uninteresting events, check for user interrupts (like Control-C), and so on. If you want efficient handling of "out of band" events, you can install your own wrapper routine for the WireToEvent conversion, and trap it before it ever even enters the queue. See Appendix C of the Xlib manual.
sandra@utah-cs.UUCP (Sandra J Loosemore) (09/01/88)
Any clues on how to do this in CLX? I just tried some experiments with using an EVENT-CASE with :timeout 0 and :discard-p t to scan through the event queue, discarding all but the first expose event on a window. But returning T from the clause to indicate that the event should be kept would also exit from the EVENT-CASE, so you'd never see whether there are more expose events in the queue or not. I tried doing a recursive call to EVENT-CASE to look at the remaining events, but that seemed to end up throwing out events it shouldn't have. I'd appreciate seeing a bit of code that actually works. -Sandra Loosemore (sandra@cs.utah.edu)
Oren@home.csc.ti.COM (LaMott Oren) (09/01/88)
Date: 31 Aug 88 18:44:11 GMT From: sandra@cs.utah.edu (Sandra J Loosemore) Subject: Re: Detecting/Compressing Multiple Exposure Events - how ? Any clues on how to do this in CLX? I just tried some experiments with using an EVENT-CASE with :timeout 0 and :discard-p t to scan through the event queue, discarding all but the first expose event on a window. But returning T from the clause to indicate that the event should be kept would also exit from the EVENT-CASE, so you'd never see whether there are more expose events in the queue or not. I tried doing a recursive call to EVENT-CASE to look at the remaining events, but that seemed to end up throwing out events it shouldn't have. I'd appreciate seeing a bit of code that actually works. -Sandra Loosemore Instead of discarding all but the first, discard all but the last. That is, when you receive an :exposure event, ignore it if there's another in the queue using: (event-case (display :discard-p t :force-output-p t) (exposure (window count) (unless ;; Ignore all but the last exposure event (event-case (window :discard-p nil :peek-p t :timeout 0) (exposure ((window event-window)) (window-equal window event-window))) (refresh window))) ;; handle other events... ) This technique works well for :motion-notify and enter/leave-notify event compression. If you really want to discard all but the first exposure event, the release 3 version of CLX contains a new form, EVENT-COND, which will give you the control you want. An easy way to compress exposure events is to ignore all events with a non-zero count: (event-case (display :discard-p t :force-output-p t) (exposure (window count) (when (zerop count) ;; Ignore all but the last exposure event (refresh window))) ;; handle other events... )
jim@athsys.uucp (Jim Becker) (09/02/88)
From article <19880831130506.7.RWS@KILLINGTON.LCS.MIT.EDU>, by RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler): > From: mit-vax!josh@bloom-beacon.mit.edu (Joshua Marantz) > > Currently, I have to emulate that functionality with an XCheckIfEvent followed > by an XPutBackEvent, which has the annoying side effect of rearranging the > event queue. > > As I pointed out in a previous posting, by using the arg value you can > avoid having to pull anything out of the queue. In general, Xlib > functionality is rather unlikely to change if there are reasonable ways > to build "convenience" routines on top of existing functionality. That > isn't to say that additional convenience routines aren't useful, just > that they probably won't go into Xlib. If people feel strongly that > additional routines ought to be provided in some sort of utility library > on the MIT release, we're willing to listen (and take code that comes > with documentation). Here are my strong feelings, please listen !! There is a fairly simple modification that can be done to correct this problem, which results in the additional functionality being added without increasing the already large number of Xlib calls. The XCheck*() calls all take an XEvent pointer, which is used to return the event to the application. In doing so, they take the event out of the queue. A modification to this logic could check for a NULL XEvent pointer being passed to the XCheck*() calls. This would serve as a signal that the user does NOT want the event, merely to know that one or more exist. Result being: The correct return status would be returned and the queue would remain intact. The code modifications involved simply add an additional if{} statement to the XCheck*() routines, which are pretty simple as stands. The other alternative is to let users get at the queue itself, which I consider to be potentially dangerous. Let me explain why this is such a big issue. In the current UI paradigm that my company is using there can be hundreds of nested windows within the layout of a single big window (which is the child of the root). When the single big window is mapped, deiconified or otherwise exposed all these little guys get exposure events. If there are multiple sets of exposes there is a lot of redundant processing. (I believe that this is a common problem with some of the current toolkits). Our problem is additionally compounded by the graphics editors having to access the database (with possible disk access) when refreshing themselves. Hence we have the need to contain the exposure processing for better application throughput and responsiveness. The proposed solution of using XCheckIfEvent(), with continual negative return status for each event in the queue, causes the entire queue to be scanned for each curious query (each window!). It also returns it's real status by "side effect", something I group with "goto"s as far as cleanliness. If there are two hundred windows, with a few sets of exposure events, you are doing a lot of work to look at the entire queue for each window. Possibly, in this case, it is faster not to try to compress the events!! (Our application currently STILL has over SIX hundred windows to contend with..uggh!). I believe that this would only cause minor mods in the five XCheck*() routines, and the additional logic is trivial. I understand that you guys have a lot to do to get R3 frozen, but this may be a worthwhile change. If there are no other changes in these routines since R2, I can make the changes and post them to xbugs. Ten minutes of fixes! One way or another, this will be a _very_ useful addition down the road. Once people get more advanced in their use of X they will want to "Check", as opposed to "Check & Get", the event queue. Enough leaning on on you busy guys -- thanks one way or the other!! -Jim Becker
RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (09/02/88)
Date: 1 Sep 88 21:36:01 GMT From: vsi1!daver!athsys!jim@AMES.ARC.NASA.GOV (Jim Becker) I believe that this would only cause minor mods in the five XCheck*() routines, and the additional logic is trivial. I understand that you guys have a lot to do to get R3 frozen, but this may be a worthwhile change. If there are no other changes in these routines since R2, I can make the changes and post them to xbugs. Ten minutes of fixes! People need to understand that the number of minutes it takes to fix the code is somewhat irrelevant. What matters is that there is a standard definition of the Xlib interface, and it doesn't willy nilly get changed. There is a process that has to get followed. And, at this particular point, stability of interfaces is rather important, to vendors and to developers. There are many products in-progress out there, being built to comply with current interfaces. Those products are on varying schedules, none under the control of MIT. Many are close to being "out", and a number of companies already have products out. You can't just change an interface and expect that all vendors will be able to instantly make the change. For some, it make a year to fold it into their release cycle. Those are realities that we have to live with. This isn't to say we'll ignore your suggestion, just that expecting it as part of Xlib in R3 is not realistic.
josh@mit-vax.LCS.MIT.EDU (Joshua Marantz) (09/07/88)
JDM> Currently, I have to emulate that functionality with an XCheckIfEvent JDM> followed by an XPutBackEvent, which has the annoying side effect of JDM> rearranging the event queue. RWS> As I pointed out in a previous posting, by using the arg value you can RWS> avoid having to pull anything out of the queue... RWS> ... If people feel strongly that RWS> additional routines ought to be provided in some sort of utility library RWS> on the MIT release, we're willing to listen (and take code that comes RWS> with documentation). JB> [Paraphrased] JB> By modifying the XCheck*() routines to accept a NULL event pointer and JB> take it to mean that the event should not be removed from the queue, my JB> problems can be solved efficiently without breaking anyone else's code JB> and with minimal coding work from the X Consortium. The arg modification JB> proposed by RWS is functional but potentially inefficient and arguably JB> unaesthetic. If Jim Becker's change were implemented for R3, it might present a backwards compatibility problem: if I write my code for an Xlib that accepts NULL events in XCheckIfEvent, then my code won't work correctly on a vendor's library, since they typically lag the MIT version by a few months. This may not be so important to some people, but it would be to others. I like RWS's other suggestion -- using a custom WireToEvent routine. As described on page 243 of the MIT, Xlib manual, in the extensions section, the routine XESetWireToEvent will allow you to define a routine to intercept events before they are placed on the queue. This routine could update your own data structure saying which events are pending. It could then call the default WireToEvent routine, which is returned by XESetWireToEvent. This is a nice little design, since several independent modules can intercept events, process them, and then call the previous handler. My only problem with it is that the manual says: XLib> You can replace a core event conversion routine with one of your own, XLib> though this is not encouraged. It would, however, allow you to XLib> intercept a core event and modify it before being enqueued or XLib> otherwise extended. Should I take this to mean that I am treading on thin ice in terms of portability by using this routine? Or am I OK so long as I call the default handler and return its status after doing my own filtering? Also, the documentation is confusing as to whether my routine is supposed to return an "int" or a "Status", since XESetWireToEvent returns an integer procedure pointer. I suppose they are ultimately the same thing, but I haven't checked yet. -Joshua Marantz Viewlogic Systems, Inc.
jg@jumbo.dec.com (Jim Gettys) (09/07/88)
Event conversion routines, as in all X protocol extensions, must be carefully written if they are to be portable, particularly to machines like a Cray. This is why there is a warning in the Xlib manual. - Jim