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




Raph Levien <raph@acm.org> writes
>
> On Sun, 14 Dec 1997, Owen Taylor wrote:
> 
> [excellent explanation of GraphicsExpose elided]
> > 
> > As far as I know, only two pieces of code use gdk_draw_pixmap 
> > window-to-window copying for scrolling - the text widget and
> > scrolling in the GIMP. The code in the GIMP doesn't work properly
> > (probably because of the above mentioned timing issues) - try
> > scrolling a window with button-two that is partially obscured.
> > The Text widget doesn't seem to show this problem, but possibly
> > only because it is faster at doing the redrawing.
> 
> The text widget is careful not to copy from any region offscreen. If you 
> look at scroll_up (for example) in gtktext.c, you'll see that scrolling 
> is accomplished by both a call to gdk_draw_pixmap (which wraps XCopyArea 
> in this case) and expose_text, which draws the text in the uncovered area.
> 
> Nonetheless, the gtk_text widget does deal with GraphicsExpose events 
> when scrolling a partially obscured window. Apparently, the 
> GraphicsExpose events are translated into plain Gdk expose events, and 
> the handling is correct.
> 
> I've also noticed the Gimp image area scrolling bug - it's especially a 
> problem in conjunction with fvwm95's task bar at the bottom of the 
> screen. I haven't looked into it at all, though.

I think what happens is:

After the XCopyArea call, X thinks that the entire window now contains
valid information (for the purpose of calculating GraphicsExpose
events). But actually, that isn't true until the GraphicsExpose events
filter through the queue. Before then, X has blanked out the improper
areas to the background color (*) If another motion event occurs
before then, X will copy the blanked out areas, but not produce
graphics expose events for them, thus leading to the observed gray
bars. 

(*) (It should be possible to gain a bit of performance by specifying
a background pixmap of None, though that can produce some strange
visual artifacts - Adobe's Acroread does this.)

I'm thinking of adding a specialized function to gdk to handle this:

  gdk_get_next_graphics_expose_event (GdkWindow *window, GdkEvent
                                      *event, gint status);

or something. So you could do:

 gdk_draw_pixmap (widget->window, gc, widget->window, ...);

 do
   {
     if (gdk_get_next_graphics_expose_event (widget->window, &event, &status))
       gtk_widget_event (widget, &event)
   }
  while (status);

to make sure that all the GraphicsExpose events are properly handled.
status would become FALSE when a NoExpose event or GraphicsExpose
event with a count of zero was received, or no suitable events were in
the queue. The GIMP tries to to do this using gdk_next_event () with a
predicate, but as I mentioned, that seems completely broken, and I
don't know how to fix it without tons of overhead. (And changing a lot
of assumptions in the event handling code)

> > So, for starters, I would like to make no graphics expose events
> > the default for GDK created GC's. 
    ^^^^^^^^^^^

> I'm not quite sure I understand the proposal. How are you going to detect 
> the case when XCopyArea is used to scroll inside a partially obscured 
> window? Unless I totally misunderstand, enabling graphics expose is the 
> only way to do this.

People who knew what they were doing could still specify that they
wanted GraphicsExpose events. But it would remove a trap for
beginners, and cut down on the number of NoExpose events GTK handles.

> > I'm not sure what to do about the translation of GraphicsExpose =>
> > Expose. I'll probably have to fix the code in the GIMP to figure
> > out what the right course is.
> > 
> > Comments? Objections? 
> 
> Currently, Gzw (and thus Gzilla) handles scrolling by moving the 
> underlying X window, pretty much the same as gtk_scrolled_window, except 
> with some stuff to handle >32kpixel scrollable regions. Thus, the stuff 
> scrolled in is handled by a vanilla expose event. This works ok, but you 
> do get the round-trip latency of waiting for the expose event, which is 
> visually noticeable. It's especially noticeable when scrolling very 
> quickly and/or on a highly loaded machine. I'd like to add an alternate 
> mode that works the same as gtk_text. On the other hand, the gtk_text 
> method works very poorly when there are embedded non-NO_WINDOW widgets. 
> In any case, I'm certainly interested to find out how this is resolved.

The same latency should be present in any case, right? X should
optimize scrolling the window like using XCopyArea, and the
GraphicsExpose events also have to go round-trip. 

I was thinking some more about how to avoid the lagging-widget effect,
and came only came up with a rather wild and impractical idea -
make the embedded widget's have InputOnly windows, and redirect
the drawing calls onto the scrolled window's pixmap. It would require
some changes to GdkWindow handling, and you'd have to handle exposures
pretty much by hand...

Another way to get the display right - with horrible performance and
complexity. Set the background pixmap of the parent window to None. Do
an XCopyArea with SubwindowMode set to IncludeInferiors, unmap the
child windows, ignore the resulting expose events on the parent
window. Set the background pixmap of all the child windows and their
descendants to None, remap them in the new position, ignore the
resulting expose events on the child windows, then restore the
backgrounds.

But pretty much, I don't think it is possible to do better than what
you do in Gzilla now.

Regards,
                                        Owen






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