Re: gtk_widget_draw()



On Tue, 2010-08-17 at 17:28 +0200, Benjamin Otte wrote:
> The biggest problem for me when reading the GdkWindow code is that I
> have no idea what a window is. So I have a hard time understanding the
> code and if what it does is sane.

One pattern we see a lot is when widgets want to paint themselves on
their parent container's background, but still receive events.  They are
NO_WINDOW widgets, which means "I want to share my parent's window", and
then they also create INPUT_ONLY windows to catch events.

This is a very useful pattern.  Such widgets are basically saying:

- "Just give me a nicely-prepared surface to draw on" (i.e. with the
parent's contents already drawn)

- "And let me catch events, too".

The funny thing is that not only "non-square" widgets like labels do
this; buttons also do this for aesthetic purposes.

I think it seems sane to move to a model where

1. The only native windows (with an XID) are toplevels, with a few
exceptions (see below),

2. All subwindows are all GDK-side abstractions.  They define a clipping
region and a coordinate system.  See below for transparency issues.

3. The exception is when you need a native window to do funky stuff
(OpenGL, plug/socket, xv, etc.).  These (sub)windows are understood to
be limited - you may not be able to transform them and such.

The interesting part is (2), or what happens with subwindows.

Non-square widgets that want to paint to their parent's background would
still benefit from having a "transparent" window to paint on - this
would give you an already-prepared surface (with whatever the parent
painted), a clipping region and a coordinate system.  That is, GtkLabel
wouldn't have to clip the text itself and add allocation->{x,y} all the
time.

Square widgets that completely cover their area are of course trivial to
implement in that model - they would just overwrite their parent's
contents with their own.  I don't know if we want to be able to avoid
painting the parent's regions that we *know* will be completely
obscured.  Think of a white text area over a gradient window background
- drawing that gradient may be expensive and so you certainly want to
paint only the areas that will *not* be the white text area... or maybe
not, if you can just ask the GPU to draw the whole gradient.

Do we need a "window->need_parent_background" flag?  I.e. the "paint the
parent first, don't clip to the subwindow" flag?

I don't think these "transparent windows" should store any contents at
all to composite them later.  GDK doesn't store window contents, and
starting to do that sounds painful.  Keep subwindows just as an
abstraction for clipping/coordinates/initial-background.

With the model above, the repaint cycle looks pretty much like the
current one - you paint recursively, and you just set the clip region
(or not) based on a subwindow's "need_parent_background" flag.

> - Does a GdkWindow describe a window hierarchy? Again, kinda. Mostly
> you can restack and reparent windows fine, but stuffing a toplevel
> into an offscreen window does not work at all.
> - What's a GdkWindowType? When I restack a TOPLEVEL into a CHILD, will
> it change type? Should it?

This is the core of Alex's argument for keeping the impls separate, I
think.  GdkWindow exposes a public API (with a few leaks such as
gimme_the_native_window_id()); the internal impls switch in and out as
you reparent things.

Who uses reparenting, anyway?

Restacking our abstracted subwindows should be trivial; you just repaint
them in order.

> - Can windows be translucent? Should they be?

See above.

> - Is a GdkWindow the only way to get enter/leave events to widgets? Do
> widget authors know these thing?

If they don't know offhand, they learn pretty fast :)  Basically, having
a window is the *only* way to get events.  Whether you do it with an
InputOutput or an InputOnly window depends on each particular widget.

> - What do we do with event masks? I learned yesterday that widgets
> without EXPOSURE_MASK don't get their background cleared. Is that
> documented? Or should that even be the case? Do we even need event
> masks?

Clearing the background or not depends on the hypothetical
"is-this-window-transparent" flag that we discussed above.

Event masks are an X-ism, I think... I really don't know if they matter
much with local connections (except maybe to save context switches);
they may definitely help in remote connections.  Something tells me that
Owen will know more about this from when he was profiling GTK+'s X
stream.

> - Shoud every widget have its own window now that we have lightweight
> client-side windows? Or should almost no widget have a window because
> we can synthethically create all the events widgets need? Do we have a
> list for widget authors somewhere for when they want to create their
> own window?

If we move to the model I described above, then it should be pretty
clear that all widgets can have windows (for convenience) and yet be
able to draw themselves as they wish.

> But there are operations that do not make sense at all on a
> non-toplevel window. Like setting the icon or the title. And I'd argue
> that it's confusing for widget implementors that they need to think
> about this stuff when creating a window for their widget.
> For offscreen windows, a lot more of the window operations don't make sense.

If you wanted to really segregate functionality based on the window
type, I guess you could have

  if (gdk_is_toplevel (some_window)) {
     GdkToplevelWindow *t = gdk_window_get_toplevel_iface (some_window);
     gdk_window_set_title (t, "hello world");
  }

I.e. force the caller to get an iface that really supports the window
functions based on the window's type.  I don't know if that is
gratuitously painful or actually cleaner :)

  Federico



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