gtk_widget_draw()



Hi,

Here's an email detailing my thought process for what I want to do
with rendering in the master branch following the rendering-cleanup
merge. It's mostly a brain dump, so treat it as such.

I'll start with the end goal: gtk_widget_draw(GtkWidget *widget, cairo_t *cr);
That function will draw the given widget to the given cairo_t, no
matter what kind of cairo_t you hand it, no matter wether it's an
actual X window and the drawing is due to an expose event or if it's
an image surface for a screenshot or even if it's a PDF for printing.
The widget will then draw itself to the cairo_t at (0,0) and take
width x height pixels. It will of course respect the currently set
matrix, so you can draw widgets transformed in any way you like. Of
course, it's the only way to do rendering of widgets, so expose events
will use this function.
What does this buy us and why am I so excited about it? Well,
immediately it doesn't buy us a lot, but I expect during GTK 3 people
will take advantage of it. Things this enables:
1) Snapshots. So we can get rid of the buggy gtk_widget_get_snapshot()
function and use this one instead.
2) Snapshots. We can actually create a testsuite that compares
renderings of widgets without even requiring an X server.
3) Resolution independence. A cairo_scale (cr, 2, 2) before calling
gtk_widget_draw() smoothly scales widgets to twice the size. Of
course, event translation and all that fun is needed, too, but the
rendering part is there.
4) New backends. It's easy to render to anything that we can create a
cairo surface for. So integration with Clutter or other GL
applications becomes a lot easier.
5) Performance. We suddenly use the same API that current
performance-relevant rendering APIs like web browsers use.
6) Features. We can do all the things with a widget now that you could
do in Cairo, like fade-in/out, cover-flow, etc. And all of that
without hacks like offscreen windows.

So how do I get there:
1) Drop the whole implicit paint and gtk_widget_snapshot() machinery.
It simplifies internal code and it'll come back later with gtk_widget_draw().

2) Get rid of GdkPixmap
cairo_surface_t via cairo_surface_create_similar() does the same
thing. Only it supports transparency and all these crazy features. Or
if you need native surfaces, cairo_xlib_surface_create_for_drawable()
is for you. This includes getting rid of the APIs that require a
GdkBitmap and hide that implementation detail somewhere. Make all
these APIs accept any cairo_surface_t instead.

3) Fold GdkDrawable into GdkWindow
There's no reason left why GdkDrawable should still exist when pixmaps are gone.

4) Make the window's surface gettable
You might want to use a window as a source in drawing operations or do
other stuff with it (like calling cairo_surface_create_similar() for
the pixmap replacement) so this needs to be available. Arguably,
surfaces should not be created on demand, but be always available. And
GDK_WINDOW_XID() should probably call
cairo_xlib_surface_get_drawable(). (FIXME: Does this work fine with
the OS X semantics where we need to recreate the surface when
resizing?)

5) Get rif of the impl/wrapper mess
Currently every window is in fact 2 windows: A wrapper window and an
implementation window. So you have to cast between window->impl and
window->wrapper all the time. That was necessary due to the
window/pixmap split, but is not anymore. the native types can directly
derive from GdkWindow now.

6) Reorganize the window class hierarchy
With the drawables and impl/wrapper mess gone, we can reorganize the
window class hierarchy. First, we probably wanna pull
GdkWIndowImplIface into GdkWindowClass and then reorganize the class
hierarchy into something like this:
GdkWindow
-> GdkNativeWindow
   -> GdkNativeWindowX11
   -> GdkNativeWindowQuartz
   -> GdkNativeWindowWin32
-> GdkOffscreenWindow
-> GdkSubWindow
And we probably want some interfaces, like GtkToplevel, for stuff
that's only relevant for toplevels, like setting application icons.

We should also think about wether we want to make GdkWindow
subclassable by applications. Then you could code up your own
GdkWindow subclass (like ClutterGdkWindow) where it's your job to send
events, handle resizes and all that magic. And as a thank you, you can
do whatever you want with the GtkWidgets that use these. But we can
think about this after 3.0.

7) Improve repaint semantics
Something like disallowing multiple being_paint_region() calls and
disallowing the use of windows as a source while a repaint is
happening sound very desirable to me. The code that circumvents these
issues is quite extensive and buggy and noone uses these features
anyway. Also, the Paintable interface should probably be folded back
into GdkWindow, too.

8) Get rid of gdk_window_set_user_data()
Yes, user data currently must be a GtkWidget or stuff will explode. We
should probably just add an "event" signal to GdkWindow and connect to
it from the GtkWidgets.

9) Redo styling
This probably just involves merging Carlos' new themeing API, but we
want the theme drawing to happen using Cairo. The current style API
passes GdkWindows, and we don't have a GdkWindow if we draw to PDF.

10) Add gtk_widget_draw()
Now that all drawing is done with Cairo, we can add a new draw signal,
and call it from the default expose_event function. Then we can get
busy porting all the widgets' expose events to this signal. This
should be rather easy now, as it should just removing the
gdk_cairo_create() at the beginning and cairo_destroy() at the end of
the expose function.

11) Remove the expose_event from GtkWidget
Now that the whole repaint handling is done in the draw signal,
there's no more need for expose events. The semantics are somewhat
different, as draw signals don't correspond 1:1 to expose events. But
I think that change shouldn't matter for all practical purposes. And
if you need it, you can just connect to the "event" signal of the
GdkWindow.

So, that's a rough list of ideas I have currently. I have no idea if I
get all of this done for 3.0 and in what order I'm going to tackle
these problems, but it's what I'd like to see happen.
Comments, suggestions, possible improvements I've missed, offers for help?

Benjamin


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