[gtk+/gtk-2-18] Track direct window cairo access and avoid tricks when used



commit ed7db8ea55df8a2d7aaf006c2770e0f8966f84e6
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Jan 19 14:44:52 2010 +0100

    Track direct window cairo access and avoid tricks when used
    
    When a cairo surface is requested for direct window access (i.e. not
    when double-buffering) we can't really track when the actual drawing happens
    as cairo drawing is not virtualized. This means we can't properly flush
    any outstanding window moves or implicit paints.
    
    This actually causes problems with e.g. abiword (bug #606009) where they
    draw without double-buffering. If you press down it scrolls the window
    and then draws the caret, but the caret drawing does not flush the
    outstanding move from the scroll, so the caret gets drawn on the wrong
    screen.
    
    We fix this by never allowing either implicit paints or outstanding window
    moves on impl-windows where any windows related to it has an outstanding
    direct cairo surface. Luckily this is not very common so in practice this
    doesn't matter much.
    (cherry picked from commit 841fa4771505b6810da341ea379d5f56af7ef1d1)

 gdk/gdkinternals.h |    1 +
 gdk/gdkwindow.c    |    9 +++++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
---
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 0681bdc..822335f 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -273,6 +273,7 @@ struct _GdkWindowObject
   GdkRegion *input_shape;
   
   cairo_surface_t *cairo_surface;
+  guint outstanding_surfaces; /* only set on impl window */
 };
 
 #define GDK_WINDOW_TYPE(d) (((GdkWindowObject*)(GDK_WINDOW (d)))->window_type)
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 612f5ac..11c3e3f 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -2611,6 +2611,9 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
       private->implicit_paint != NULL)
     return FALSE; /* Don't stack implicit paints */
 
+  if (private->outstanding_surfaces != 0)
+    return FALSE; /* May conflict with direct drawing to cairo surface */
+
   /* Never do implicit paints for foreign windows, they don't need
    * double buffer combination since they have no client side children,
    * and creating pixmaps for them is risky since they could disappear
@@ -3316,7 +3319,7 @@ move_region_on_impl (GdkWindowObject *impl_window,
       gdk_region_destroy (exposing);
     }
 
-  if (1) /* Enable flicker free handling of moves. */
+  if (impl_window->outstanding_surfaces == 0) /* Enable flicker free handling of moves. */
     append_move_region (impl_window, region, dx, dy);
   else
     do_move_region_bits_on_impl (impl_window,
@@ -4837,6 +4840,7 @@ gdk_window_cairo_surface_destroy (void *data)
   GdkWindowObject *private = (GdkWindowObject*) data;
 
   private->cairo_surface = NULL;
+  private->impl_window->outstanding_surfaces--;
 }
 
 static cairo_surface_t *
@@ -4880,11 +4884,12 @@ gdk_window_ref_cairo_surface (GdkDrawable *drawable)
 
 	  source = _gdk_drawable_get_source_drawable (drawable);
 
-	  /* TODO: Avoid the typecheck crap by adding virtual call */
 	  private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
 
 	  if (private->cairo_surface)
 	    {
+	      private->impl_window->outstanding_surfaces++;
+
 	      cairo_surface_set_device_offset (private->cairo_surface,
 					       private->abs_x,
 					       private->abs_y);



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