Re: Problems with expose_event->region patch



Alexander Larsson <alla lysator liu se> writes:

> I have an almost working patch for getting the full region in expose
> events. Unfortunately the small problems left may be showstoppers...
> 
> The core problem is that mixing event->area and event->region in expose
> handlers just doesn't work when handling NO_WINDOW children.
> 
> Here is an example that shows the problem.
> 
> Consider a window with a vbox, two frames, and labels in the frames:
> 
>  +-frame1---+
>  | Label1   |
>  +----------+
> 
>  +-frame2---+
>  | Label2   |
>  +----------+
> 
> Note that all widgets (exept the GtkWindow) are NO_WINDOW, so there is
> only one X window.
> 
> Now i change the widgets:
>   gtk_widget_queue_draw (label1);
>   gtk_widget_queue_draw (label2);
> 
> This invalidates the area of the labels, and this invalidation will be
> compressed into one expose (event->region being two rectangles). The
> expose event will be sent to the GtkWindow.
> 
> GtkWindow starts by clearing the exposed *area*, then propagating the
> expose to the frames. This means that label1, label2, and the rectangle
> between them, containing part of the frames are cleared.
> 
> But when propagating the expose to frame1 the intersection of the
> event *region* and the frame1 rect is just the label1 rect, so frame1
> doesn't repaint the lower part of the frame which was previously cleared.
> Even though both GtkWindow and GtkFrame just uses event->area.
> 
> The problem here is that the exposed area changes with event->region
> support, since:
> intersect (rect(expose_region), window_rect) != rect (intersect (expose_region, window_rect))
> 
> So, "clear area, propagate to NO_WIN child, render area" doesn't work.
> 
> "clear region, propagate to NO_WIN child, render area" doesn't work
> either, since the NO_WIN child depends on having the area it paints being
> cleared.

At least with backing store, I don't follow this. Only the region
is copied from the back buffer to the screen, so painting outside 
the region doesn't matter. There is an implicit clip to the region
passed to gtk_window_begin_paint().

(Have you changed gtk_main_do_event to call gtk_window_begin_paint_region?
Now that you have the region in the expose?)

For the non-backing-store case we could even add a
gdk_drawable_set_clip_region() call and emulate it by changing the
GC's clips, though that could be rather inefficient without a
lot of complexity.

But I would really consider that unless you have a widget in which
you are doing all your own painting, you really are supposed
to leave backing store on. 

[ That is, calling gtk_widget_set_double_buffered (gtkwindow, FALSE)
  is bogus ]

> So, for this to work we need to do "clear region, propagate to NO_WIN
> child, render region". This is probably not an optimization though, since
> we will need to use a lot of complex clip regions all the time (not to
> mention all the gtk_paint_xxx need to take regions instead of rects, and
> breaking all expose handlers in existance).
> 
> In practice we may be able to get most of the benefits of expose regions
> by doing "clear area, propagate to NO_WINDOW childer the old way, render
> area or region (they are equal now)". Then non-container !NO_WINDOW
> widgets can use use expose region to optimize their redraw.

Well, your example shows that we do get a fairly big win from the
the region propagation - if two labels are updating in opposite
corners of a big window, right now, we are clearing the whole
window.

Regards,
                                        Owen




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