Re: [gtk-list] Re: GraphicsExpose (was Re: About the About Box)





On Tue, 16 Dec 1997, Owen Taylor wrote:

> I think XCheckIfEvent will check for events waiting on the socket in
> a non-blocking fashion. The problem would be if the XCopyArea
> event was still being processed by the server and it hadn't written
> it to the socket yet - or it was still in network transit. 
> 
> Anyways, a _literal_ XSync isn't necessary. An XSync does something like
> sending a message with a unique serial # to the server and waiting
> until the server echo's it back.
> 
> But we already have something in the queue that the server will echo
> back -- The XCopyArea is guaranteed generate either a sequence
> of GraphicsExpose events (the last one identified by count == 0),
> or a NoExpose event. If we wait until we get one or the other after
> a XCopyArea, we should be OK.
> 
> Additionally, this should work OK even if the server is generating
> graphics expose events asynchronously to the processesing of the
> event queue.

Aha, the light dawns now. Finally it becomes clear to me why the NoExpose 
is generated in the first place. It now seems to be that the right way to 
handle GraphicsExpose does involve keeping track of the queue in this wauy.

> The example I posted a reference to earlier does this by calling
> XIfEvent - I may have implied that it was using XCheckIfEvent,
> which would be incorrect, as you point out. (Another reason why
> using the current gdk_event_get() doesn't work)
> 
> > If I'm right about this, then it seems that there's just no way to scroll 
> > without at least one roundtrip to the server :(
> 
> Pretty much. One could keep a flag when waiting for an GraphicsExpose
> /NoExpose event, batch up events that cause further scrolling, and then
> execute them when the GraphicsExpose event is received. Not much
> fun to implement though.

Another idea occurred to me today. Instead of trying to make the 
GraphicsExpose events effectively synchronous with the XCopyArea call 
(which is essentially what's been discussed), why not glory in the 
asynchronity of it all? Basically, here's what I'm proposing:

1. Every time you do an XCopyArea call, add the parameters to a queue. I 
think the rectangle and the offset should be sufficient.

2. Every time you get a GraphicsExpose event with a count of zero, or a 
NoExpose event, you remove one entry from the queue.

3. Translation of GraphicsExpose events filters through the queue. I.e. 
if you get a GraphicsExpose event in a region that's been moved by a later
XCopyArea, then just offset the corresponding Expose event that's pushed
through Gdk. 

It shouldn't bee too hard to see that this solution is correct, 
reasonably efficient (no XSync's ever), and doesn't require significant 
modification to Gtk's event handling code. Further, I don't think it's 
that complex to implement.

My description of step 3 above was a bit vague. Here's more precise 
pseudocode. You have a recursive procedure called "filter" that takes a 
rectangle and a position in the queue. The initial position is the 
first of the XCopyArea entries.

If the position points to the last entry in the queue, then "filter" just
generates an Expose event with the rectangle. Thus, in the case where
there is only one XCopyArea in the queue (i.e. all GraphicsExpose events
handled before the next XCopyArea call), the filter is effectively a
no-op

If the position is not at the last entry, then "filter" intersect its
argument rectangle with the XCopyArea rectangle. If non-empty, then it
adds the XCopyArea offset and recursively calls "filter" with the
resulting rectangle and a position one later in the queue.  Additionally,
if the rectangle intersects with the region outside the XCopyArea
rectangle, then that area is subdivided into rectangles and passed
recursively to "filter" without any offset. It's the plane with a hole 
in it, so it can easily be subdivided into four rectangles.

To see that this is correct, assume that the GraphicsExpose event 
rectangles are initially colored purple when the XCopyArea is called. 
Then, trace through the effect of subsequent XCopyArea calls - they move 
the purple around. The resulting rectangles may not be minimal, because 
it's always possible that an XCopyArea will cover over a purple area 
with non-purple, but optimizing for that is almost certainly more trouble 
than it's worth. In the common case, there usually won't be a 
GraphicsExpose event outside the XCopyArea rectantlngle, so the 
subdivision has a branching factor of one, and the resulting rectangle is 
exactly the area left uncovered in the Gimp now.

What say the Gtk gods?

Raph



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]