[gtk+/client-side-windows: 45/284] Implement flicker free handling of window moves/resizes
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+/client-side-windows: 45/284] Implement flicker free handling of window moves/resizes
- Date: Thu, 2 Apr 2009 14:03:30 -0400 (EDT)
commit d74d94ce69b1637390b5268f904a8832a8e88ddd
Author: Alexander Larsson <alexl redhat com>
Date: Tue Dec 9 20:13:02 2008 +0100
Implement flicker free handling of window moves/resizes
---
gdk/gdkwindow.c | 236 ++++++++++++++++++++++++++++++++++++++++++++-----------
gdk/gdkwindow.h | 2 +
2 files changed, 191 insertions(+), 47 deletions(-)
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 43723cc..a561c2d 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -72,6 +72,12 @@ struct _GdkWindowPaint
guint32 region_tag;
};
+typedef struct {
+ GdkRegion *region; /* The destination region */
+ int dx, dy;
+} GdkWindowRegionMove;
+
+
/* Global info */
static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
@@ -230,6 +236,12 @@ static void remove_redirect_from_children (GdkWindowObject *private,
static void recompute_visible_regions (GdkWindowObject *private,
gboolean recalculate_siblings,
gboolean recalculate_children);
+static void gdk_window_flush (GdkWindow *window);
+static void do_move_region_bits_on_impl (GdkWindowObject *private,
+ GdkDrawable *dest,
+ int dest_off_x, int dest_off_y,
+ GdkRegion *region, /* In impl window coords */
+ int dx, int dy);
static gpointer parent_class = NULL;
@@ -1743,6 +1755,9 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowPaint *paint;
+ GdkRectangle r, clipbox;
+ GList *l;
+ GdkWindowRegionMove *move;
g_assert (gdk_window_has_impl (private));
@@ -1753,15 +1768,43 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
private->implicit_paint != NULL)
return FALSE; /* Don't stack implicit paints */
+ r = *rect;
+ for (l = private->outstanding_moves; l != NULL; l = l->next)
+ {
+ move = l->data;
+
+ gdk_region_get_clipbox (move->region, &clipbox);
+ gdk_rectangle_union (&r, &clipbox, &r);
+ }
+
paint = g_new (GdkWindowPaint, 1);
paint->region = gdk_region_new (); /* Empty */
- paint->x_offset = rect->x;
- paint->y_offset = rect->y;
+ paint->x_offset = r.x;
+ paint->y_offset = r.y;
paint->uses_implicit = FALSE;
paint->surface = NULL;
paint->pixmap =
gdk_pixmap_new (window,
- MAX (rect->width, 1), MAX (rect->height, 1), -1);
+ MAX (r.width, 1), MAX (r.height, 1), -1);
+
+ _gdk_pixmap_set_as_backing (paint->pixmap,
+ window, r.x, r.y);
+
+ for (l = private->outstanding_moves; l != NULL; l = l->next)
+ {
+ move = l->data;
+
+ gdk_region_union (paint->region, move->region);
+ g_object_ref (paint->pixmap);
+ do_move_region_bits_on_impl (private,
+ paint->pixmap,
+ paint->x_offset, paint->y_offset,
+ move->region, /* In impl window coords */
+ move->dx, move->dy);
+ gdk_region_destroy (move->region);
+ g_slice_free (GdkWindowRegionMove, move);
+ }
+ private->outstanding_moves = NULL;
private->implicit_paint = paint;
@@ -2201,12 +2244,155 @@ gdk_window_free_paint_stack (GdkWindow *window)
}
}
+static void
+do_move_region_bits_on_impl (GdkWindowObject *private,
+ GdkDrawable *dest,
+ int dest_off_x, int dest_off_y,
+ GdkRegion *region, /* In impl window coords */
+ int dx, int dy)
+{
+ GdkGC *tmp_gc;
+ GdkRectangle copy_rect;
+
+ gdk_region_get_clipbox (region, ©_rect);
+ gdk_region_offset (region, -dest_off_x, -dest_off_y);
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkWindow *)private, TRUE);
+ gdk_gc_set_clip_region (tmp_gc, region);
+ gdk_draw_drawable (dest,
+ tmp_gc,
+ private->impl,
+ copy_rect.x-dx, copy_rect.y-dy,
+ copy_rect.x - dest_off_x, copy_rect.y - dest_off_y,
+ copy_rect.width, copy_rect.height);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+}
+
+static void
+append_move_region (GdkWindowObject *impl_window,
+ GdkRegion *region,
+ int dx, int dy)
+{
+ GList *moves_to_add, *l, *s;
+ GdkRegion *intersection;
+ GdkWindowRegionMove *move, *new_move, *existing_move;
+
+ move = g_slice_new (GdkWindowRegionMove);
+ move->region = region;
+ move->dx = dx;
+ move->dy = dy;
+
+ moves_to_add = g_list_prepend (NULL, move);
+
+ for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
+ {
+ existing_move = l->data;
+
+ for (s = moves_to_add; s != NULL; s = s->next)
+ {
+ move = s->data;
+
+ intersection = gdk_region_copy (move->region);
+ gdk_region_offset (intersection, -move->dx, -move->dy);
+ gdk_region_intersect (intersection, existing_move->region);
+ gdk_region_offset (intersection, move->dx, move->dy);
+
+ if (!gdk_region_empty (intersection))
+ {
+
+ new_move = g_slice_new (GdkWindowRegionMove);
+ new_move->region = intersection;
+ new_move->dx = move->dx + existing_move->dx;
+ new_move->dy = move->dy + existing_move->dy;
+ moves_to_add = g_list_prepend (moves_to_add, new_move);
+
+ gdk_region_subtract (move->region, intersection);
+ gdk_region_subtract (existing_move->region, intersection);
+ }
+ else
+ gdk_region_destroy (intersection);
+ }
+ }
+
+ impl_window->outstanding_moves = g_list_concat (impl_window->outstanding_moves,
+ moves_to_add);
+
+}
+
+/* Moves bits and update area by dx/dy in impl window
+ * Takes ownership of region.
+ */
+static void
+move_region_on_impl (GdkWindowObject *private,
+ GdkRegion *region, /* In impl window coords */
+ int dx, int dy)
+{
+ GdkWindowObject *impl_window;
+ gboolean free_region;
+
+ free_region = TRUE;
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (1) /* Enable flicker free handling of moves. */
+ {
+ free_region = FALSE;
+
+ append_move_region (impl_window, region, dx, dy);
+ }
+ else
+ do_move_region_bits_on_impl (private,
+ private->impl, 0,0,
+ region, dx, dy);
+
+ /* Move any old invalid regions in the copy source area by dx/dy */
+ if (impl_window->update_area)
+ {
+ GdkRegion *update_area;
+
+ update_area = gdk_region_copy (region);
+ /* Convert from target to source */
+ gdk_region_offset (update_area, -dx, -dy);
+ gdk_region_intersect (update_area, impl_window->update_area);
+ gdk_region_subtract (impl_window->update_area, update_area);
+ /* Convert back */
+ gdk_region_offset (update_area, dx, dy);
+ gdk_region_union (impl_window->update_area, update_area);
+ gdk_region_destroy (update_area);
+ }
+
+ if (free_region)
+ gdk_region_destroy (region);
+}
+
/* Flushes all outstanding changes to the window, call this
* before drawing directly to the window (i.e. outside a begin/end_paint pair).
*/
static void
gdk_window_flush (GdkWindow *window)
{
+ GdkWindowObject *private;
+ GdkWindowObject *impl_window;
+ GList *l;
+ GdkWindowRegionMove *move;
+
+ private = (GdkWindowObject *) window;
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
+ {
+ move = l->data;
+
+ do_move_region_bits_on_impl (private,
+ private->impl, 0, 0,
+ move->region, move->dx, move->dy);
+
+ gdk_region_destroy (move->region);
+ g_slice_free (GdkWindowRegionMove, move);
+ }
+
+ g_list_free (impl_window->outstanding_moves);
+ impl_window->outstanding_moves = NULL;
+
gdk_window_flush_implicit_paint (window);
}
@@ -5249,50 +5435,6 @@ move_native_children (GdkWindowObject *private)
}
}
-/* Moves bits and update area by dx/dy in impl window
- * Takes ownership of region.
- */
-static void
-move_region_on_impl (GdkWindowObject *private,
- GdkRegion *region, /* In impl window coords */
- int dx, int dy)
-{
- GdkGC *tmp_gc;
- GdkRectangle copy_rect;
- GdkWindowObject *impl_window;
-
- gdk_region_get_clipbox (region, ©_rect);
- tmp_gc = _gdk_drawable_get_scratch_gc ((GdkWindow *)private, TRUE);
- gdk_gc_set_clip_region (tmp_gc, region);
- gdk_draw_drawable (private->impl,
- tmp_gc,
- private->impl,
- copy_rect.x-dx, copy_rect.y-dy,
- copy_rect.x, copy_rect.y,
- copy_rect.width, copy_rect.height);
- gdk_gc_set_clip_region (tmp_gc, NULL);
-
- impl_window = gdk_window_get_impl_window (private);
-
- /* Move any old invalid regions in the copy source area by dx/dy */
- if (impl_window->update_area)
- {
- GdkRegion *update_area;
-
- update_area = gdk_region_copy (region);
- /* Convert from target to source */
- gdk_region_offset (update_area, -dx, -dy);
- gdk_region_intersect (update_area, impl_window->update_area);
- gdk_region_subtract (impl_window->update_area, update_area);
- /* Convert back */
- gdk_region_offset (update_area, dx, dy);
- gdk_region_union (impl_window->update_area, update_area);
- gdk_region_destroy (update_area);
- }
-
- gdk_region_destroy (region);
-}
-
static void
gdk_window_move_resize_internal (GdkWindow *window,
gboolean with_move,
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 5b18ad2..5c47578 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -335,6 +335,8 @@ struct _GdkWindowObject
gint8 toplevel_window_type;
GdkWindowPaint *implicit_paint;
+
+ GList *outstanding_moves;
cairo_surface_t *cairo_surface;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]