On Mon, Aug 16, 2010 at 11:23 PM, Alexander Larsson <al...@redhat.com> wrote: > [...] > > Just doing this is a great cleanup and simplification of gdk and the > backends, which is clearly a good step towards further work. > Great. This is what I've been hacking on in the rendering-cleanup branch (yes, you cannot make it die, even by merging it) since it was merged last time. I do not inted to touch any GdkWindow internals in that branch until it's merged again. The branch right now focusses on getting rid of GdkPixmap and providing suitable replacements. More on that in a separate mail though.
> However, the next step, getting rid of the wrappers/impls and > restructuring the window class hierarchy is not really right > imho. Having impls be a separate object type is quite nice for CSW, it > models pretty well the situation where GdkWindow are the client side > things, and GdkWindowImpls are the native part that GdkWindows draw > in, etc. It also matches the dynamic status of "nativeness". I.e. a > window can get a native window when needed rather than having to do > this upfront. If nativeness was encoded in the typesystem things like > that just wouldn't work. > 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. - Does a GdkWindow mirror a window provided by the windowing system? Obviously no, because offscreen windows do not own a windowing system window and csw windows do grab onto the native parent's window. So the relationship between GdkWindows and X Windows is 1:N (where N can be 0). - Does a GdkWindow have a matching Cairo surface? Well, kinda, but csw windows share the surface with of the native window, so when drawing to it, we need to clip before we draw. - Is a GdkWindow an implementation detail or available in the public API? Again, it depends. If you have a GdkWindowImplFoo, it's private, otherwise it's public. Can I even call the same (internal or public) functions on these two types of windows? - 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? - Who's responsible for what? Who decides when to repaint a window? Is it the same for offscreen windows? Who creates damage events? - Can windows be translucent? Should they be? - Is a GdkWindow the only way to get enter/leave events to widgets? Do widget authors know these thing? - 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? - 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? Note that I don't describe the current state of things in GTK2, I can look that up in the code if I have to. I'm more interested in how things should be. > Similarly a problem is encoding things like toplevel/subwindowness in > the typesystem (i.e. GdkSubwindow or GdkToplevel). A subwindow is a > subwindow purely based on where its in the hierarchy, which is easily > changed with gdk_window_reparent. This means windows can go from > toplevels and back at runtime. > 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. > This part of things has been very concrete stuff, now we get to the > more abstract parts about rendering using cairo only. First of all I > must say your description is kinda handwavy in the details. For > instance, its not at all obvious how multi-window widgets are supposed > to render themselves, or how the window hierarchy is traversed while > rendering. > I think in retrospect, that that is mostly related to the question outlined above about what a GdkWindow is and what it does. It's hard to be concrete if you have no idea about the underlying design. ;) > Secondly, while I think your description of a no-exposes cairo_t-only > rendering system sounds very nice I fear that it is to simple to > handle everything a full featured toolkit will meet in > practice. People will want to put all kinds of weird stuff inside a Gtk > window, including things like: OpenGL rendered stuff, Xv magic, > socket/plug X embedding, embedding things like a flash plugin or old > motif plugins in a browser, etc. There is just no way you can take > things like these and put them transformed on a pdf surface. We have > to expose a more "raw" expose system. > We can have a very simple solution to most of these problems I believe. Something like: gboolean gdk_cairo_is_system_repaint (cairo_t *cr); That function would return TRUE if the cairo_t was created by GDK for repainting and FALSE if it just was a random call to gtk_widget_paint(). You could just return a black area for where your OpenGL stuff would be. Or you could use it for optimized drawing of a cached result: If it's TRUE, just cairo_paint() the cache, otherwise rerender the full contents. Also, for the xv and OpenGL cases you outlined, you probably want to create an X window outside of GDK (you definitely want in GStreamer, and I'm prettty sure I'd want to for GL, too) and handle it manually. In that case it's not GDK's responsibility to get something drawn. And it would be up to the widgets to draw it when doing a non-system draw() call. > Now, say you have a complex dialog with lots of widgetry (and no > native subwindows). The only thing in the update region is the area of > two buttons, at the bottom of the window (maybe you moused over > them). How do we repaint this? > So here's pseudocode for the important functions for redraw handling that exist in my mind. There's probably some corner cases that we need to think about, but in general, i think it works. def expose_event (native_window, invalid_region): cairo_create (get_surface (native_window)); cairo_clip (invalid_region) cairo_push_group() /* for double-buffering */ render_window(native_window) cairo_pop_group_to_source() cairo_set_operator(SOURCE) cairo_paint() def render_window (native_window, cr): foreach (subwindow of native_window): cairo_save() cairo_clip(get_region (subwindow)) if (! everything_clipped ()): cairo_translate(subwindow.x,subwindow.y) gtk_widget_draw (get_widget (subwindow)) cairo_restore() def gtk_widget_draw(widget, cr): cairo_save () cairo_clip (widget.allocation) if (! everything_clipped ()): widget->class->draw () cairo_restore () As you've probably figured out, the everything_clipped() function does all the magic here. It replaces the current cairo_region_intersect() and does basically the same thing: In render_window() it figures out if the window actually overlaps the area to repaint and skips windows that don't. In gtk_widget_draw() it does the same for widgets. If we wanted, we could also use gdk_cairo_is_system_repaint() and check if widget->window is identical, but I don't think that's even necessary. Benjamin _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list