]> Pileus Git - ~andy/gtk/commitdiff
Track direct window cairo access and avoid tricks when used
authorAlexander Larsson <alexl@redhat.com>
Tue, 19 Jan 2010 13:44:52 +0000 (14:44 +0100)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 4 Apr 2010 00:55:21 +0000 (20:55 -0400)
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.

gdk/gdkinternals.h
gdk/gdkwindow.c

index 0681bdcd18a6c746c165b3c490f8cb52fb8399dc..822335fcd4be1f1919967bdd2da790551de5afb4 100644 (file)
@@ -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)
index 9e6b14a736f7aa3901496983deac76a6545fbf3c..5b39995f9e2f2dada4dd79bb3b73cf69fa90b549 100644 (file)
@@ -2622,6 +2622,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
@@ -3327,7 +3330,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,
@@ -4846,6 +4849,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 *
@@ -4889,11 +4893,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);