Re: Virtualizing paint functions



Owen Taylor skrev:
On Tue, 2006-04-04 at 00:12 +0200, Anders Carlsson wrote:
Owen Taylor skrev:
So:

if (GDK_IS_PAINTABLE(window)->impl)) {
     GDK_PAINTABLE(impl)->invalidate_region(region);
     return;
   }

 [ Current implementation ]

That *is* another way of doing backend customization from what we have
as well, but at least it's a way that fits into the general GObject
patterns.
Ah, that looks way better that the hack I had. When I was looking at inheritance, I was concerned with not being able to provide a default implementation.

I guess the remaining issue now is how to override gdk_window_process_all_updates, without requiring copies of the function in the different backend implementations.

Can you explain the issue here more?
						Owen
The problem was that I wanted to override gdk_window_process_all_updates, which is a void function. I have everything pretty much working (aside from some issues with the Cairo Quartz backend) since gdk_window_process_all_updates is normally called from an idle func and Cocoa already calls the necessary repaint functions in the mainloop anyway.

I've put together a patch which provides the necessary hooks for me in the way you suggested. It's pretty non-obtrusive, and since it's an implementation detail it can easily be changed later.

Regards,
Anders

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.7712
diff -u -p -r1.7712 ChangeLog
--- ChangeLog	7 Apr 2006 17:18:07 -0000	1.7712
+++ ChangeLog	9 Apr 2006 22:19:16 -0000
@@ -1,3 +1,15 @@
+2006-04-10  Anders Carlsson  <andersca imendio com>
+
+        * gdk/gdkinternals.h:
+        * gdk/gdkwindow.c:
+        (_gdk_paintable_get_type):
+        (gdk_window_begin_paint_region):
+        (gdk_window_end_paint):
+        (gdk_window_process_updates):
+        (gdk_window_invalidate_maybe_recurse):
+        Add new GdkPaintable interface which implementation objects can 
+        implement in order to override gdk painting functions.
+
 2006-04-07  Hans Breuer  <hans breuer org>
 
 	* gtk/makefile.msc.in tests/makefile.msc : updated
Index: gdk/gdkinternals.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkinternals.h,v
retrieving revision 1.40
diff -u -p -r1.40 gdkinternals.h
--- gdk/gdkinternals.h	3 Apr 2006 20:36:50 -0000	1.40
+++ gdk/gdkinternals.h	9 Apr 2006 22:19:16 -0000
@@ -337,6 +337,31 @@ void _gdk_windowing_window_destroy_forei
 void _gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
 					      const gchar *sm_client_id);
 
+#define GDK_TYPE_PAINTABLE            (_gdk_paintable_get_type ())
+#define GDK_IS_PAINTABLE(obj)	      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_PAINTABLE))
+#define GDK_PAINTABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GDK_TYPE_PAINTABLE, GdkPaintableIface))
+
+typedef struct _GdkPaintable        GdkPaintable;
+typedef struct _GdkPaintableIface   GdkPaintableIface;
+
+struct _GdkPaintableIface
+{
+  GTypeInterface g_iface;
+  
+  void (* begin_paint_region) (GdkPaintable *paintable,
+			       GdkRegion    *region);
+  void (* end_paint)          (GdkPaintable *paintable);
+
+  void (* invalidate_maybe_recurse) (GdkPaintable *paintable,
+				     GdkRegion    *region,
+				     gboolean    (*child_func) (GdkWindow *, gpointer),
+				     gpointer      user_data);
+  void (* process_updates)          (GdkPaintable *paintable,
+				     gboolean      update_children);
+};
+
+GType _gdk_paintable_get_type (void) G_GNUC_CONST;
+
 /* Implementation types */
 GType _gdk_window_impl_get_type (void) G_GNUC_CONST;
 GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.182
diff -u -p -r1.182 gdkwindow.c
--- gdk/gdkwindow.c	4 Apr 2006 14:02:01 -0000	1.182
+++ gdk/gdkwindow.c	9 Apr 2006 22:19:16 -0000
@@ -192,6 +192,30 @@ static void gdk_window_clear_backing_rec
 
 G_DEFINE_TYPE (GdkWindowObject, gdk_window_object, GDK_TYPE_DRAWABLE);
 
+GType
+_gdk_paintable_get_type (void)
+{
+  static GType paintable_type = 0;
+
+  if (!paintable_type)
+    {
+      static const GTypeInfo paintable_info =
+      {
+	sizeof (GdkPaintableIface),  /* class_size */
+	NULL,                        /* base_init */
+	NULL,                        /* base_finalize */
+      };
+
+      paintable_type = g_type_register_static (G_TYPE_INTERFACE,
+					       g_intern_static_string ("GdkPaintable"),
+					       &paintable_info, 0);
+
+      g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
+    }
+
+  return paintable_type;
+}
+
 static void
 gdk_window_object_init (GdkWindowObject *window)
 {
@@ -936,6 +960,13 @@ gdk_window_begin_paint_region (GdkWindow
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  if (GDK_IS_PAINTABLE (private->impl) &&
+      GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region) 
+    {
+      (* GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region) ((GdkPaintable *)private->impl, region);
+      return;
+    }
+
   gdk_region_get_clipbox (region, &clip_box);
 
   paint = g_new (GdkWindowPaint, 1);
@@ -997,6 +1028,13 @@ gdk_window_end_paint (GdkWindow *window)
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  if (GDK_IS_PAINTABLE (private->impl) &&
+      GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint) 
+    {
+      (* GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint) ((GdkPaintable *)private->impl);
+      return;
+    }
+
   if (private->paint_stack == NULL)
     {
       g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
@@ -2350,6 +2388,13 @@ gdk_window_process_updates (GdkWindow *w
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  if (GDK_IS_PAINTABLE (private->impl) &&
+      GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates)
+    {
+      (* GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates) ((GdkPaintable *)private->impl, update_children);
+      return;
+    }
+  
   if (private->update_area && !private->update_freeze_count)
     {      
       gdk_window_process_updates_internal (window);
@@ -2478,6 +2523,14 @@ gdk_window_invalidate_maybe_recurse (Gdk
   
   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
     return;
+
+  if (GDK_IS_PAINTABLE (private->impl) &&
+      GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse)
+    {
+      (* GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse) ((GdkPaintable *)private->impl, region,
+									     child_func, user_data);
+      return;
+    }
 
   visible_region = gdk_drawable_get_visible_region (window);
   gdk_region_intersect (visible_region, region);


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