Re: Problems with expose_event->region patch



Alexander Larsson <alla lysator liu se> writes:

> On 7 Mar 2001, Owen Taylor wrote:
> 
> > 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?)
> 
> No, i must have missed this. I'm not very good at the backing store stuff,
> and i don't think many are. Have you written any docs on that?

While I could dredge up my design document for it, 

 http://developer.gnome.org/doc/API/2.0/gdk/gdk-windows.html#GDK-WINDOW-BEGIN-PAINT-REGION

is better. Thanks, Havoc!
 
> Here is the core of the patch in the final form. Then i changed all the
> widgets to chain to the expose handler or propagate exposes correctly.
> That part is pretty much like the previously send patch, although i found
> some additional gtk_widget_event()s.
> 
> Is this ok to check in?

This looks very good, and ready to check in. A few comments:

> +
> +- The GdkExposeEvent has a new region field. This can be used instead
> +  of the area field if you want a more exact representation of the
> +  area to update. If your code sends any synthetic expose events, make
> +  sure you initialize the region field, by using something like:
> +   event.region = gdk_region_rectangle (event.area);
> +  Note that sending synthetic expose events isn't really a good way to

> +  expose (parts of) a window anymore, you should use
> +  gdk_window_invalidate_rect() or gdk_window_invalidate_region() instead.

I think this needs to be more detailed in describing exactly how
you need to fix a container implementation, and mention explicitely
that gtk_widget_event() can no longer be used to send EXPOSE
events.

> + * gtk_container_propagate_expose:
> + * @container: a #GtkContainer
> + * @child: a child of @container
> + * @event: a expose event sent to container
> + *
> + * Some windows (those without GdkWindows) need to get synthetic expose
> + * events, since they don't get expose events otherwise. This function
> + * should be used by all containers to propagate expose events. It handles
> + * correct intersecting and coordinate translation of the event.

Here's my attempt at a bit better explanation.

 When a container receives an expose event, it must send synthetic
 expose events to all children that don't have their own GdkWindows.
 This function provides a convenient way of doing this. A container,
 when it receives an expose event, gtk_container_propagate_expose() 
 once for each child, passing in the event the container received.

 gtk_container_propagate expose() takes care of deciding whether
 an expose event needs to be sent to the child, intersecting
 the event's area with the child area, and sending the event.

 In most cases, a container can simply either simply inherit the
 ::expose implementation from GtkContainer, or, do some drawing 
 and then chain to the ::expose implementation from GtkContainer.

> + **/
> +void
> +gtk_container_propagate_expose (GtkContainer   *container,
> +				GtkWidget      *child,
> +				GdkEventExpose *event)
> +{
> +  GdkEventExpose child_event;
> +
> +  g_return_if_fail (GTK_IS_CONTAINER (container));
> +  g_return_if_fail (GTK_IS_WIDGET (child));
> +  g_return_if_fail (event != NULL);
> +
> +  g_assert (child->parent == GTK_WIDGET (container));
>
> +  if (GTK_WIDGET_DRAWABLE (child) &&
> +      GTK_WIDGET_NO_WINDOW (child))

To handle containers with multiple windows, you should check to
see if event->window == widget->window.

> +/**
> + * gtk_widget_send_expose:
> + * @widget: a #GtkWidget
> + * @event: a expose #GdkEvent
> + *
> + * Very rarely-used function. This function is used to emit
> + * an expose event signals on a widget. This function is not
> + * normally used directly. The only time it is used is when
> + * propagating an expose event to a child NO_WINDOW widget, and
> + * that is normally done using gtk_container_propagate_expose.
> + *
> + * If you just want to synthesize an expose event, use
> + * gdk_window_invalidate_rect() to invalidate a region of the
> + * window.

 If you want to force an area of a window to be redrawn, 
 use gdk_window_invalidate_rect() or gdk_window_invalidate_region().
 To cause the redraw to be done immediately, follow that call
 with a call to gdk_window_procss_updates().

> +/* This internal function is called from gtkmain.c
> + * to allow it to pass expose events. */
> +static gint

Stale comment?

> +/**
> + * gtk_widget_region_intersect:

Need to describe the coordinate systems, as ugly as that will
make the description sound.

> + * @widget: a #GtkWidget
> + * @region: a #GdkRegion, 
                             in the same coordinate system as 
      widget->allocation. That is, relative to widget->window
      for NO_WINDOW widgets; relative to the parent window
      of widget->window for widgets with their own widget.
                               

> + * @returns: the intersection of @widget and @region

  A newly allocated region holding the intersection of @widget
  and @region. The coordinates of the return value are
  relative to widget->window for NO_WINDOW widgets, and
  relative to the widget's allocation for widgets with their
  own window.

Actually, the funky coordinate system for the return value is that way
because gtk_widget_intersect() was used for ::draw propagation and
that was the coordinate system that was used for the argument to
::draw.

Now that ::draw is gone, I think we should simply make
gtk_widget_region_intersect() return coordinates relative to
widget->window. The question then is - should gtk_widget_intersect()
be changed to match?

It's strange having them be different, and I the number of people who
actually understand the way the coordinate systems used to work is
tiny, but then again, there will be one person, somewhere, who will
have a _HARD_ bug to track down if we change it.

(Regards,
                                        Owen


  





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