diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c index a21ad163a0..b1c068b156 100644 --- a/gdk/gdkoffscreenwindow.c +++ b/gdk/gdkoffscreenwindow.c @@ -832,12 +832,38 @@ gdk_offscreen_window_queue_antiexpose (GdkWindow *window, } static void -gdk_offscreen_window_queue_translation (GdkWindow *window, - GdkGC *gc, - cairo_region_t *area, - gint dx, - gint dy) +gdk_offscreen_window_translate (GdkWindow *window, + cairo_region_t *area, + gint dx, + gint dy) { + cairo_surface_t *surface; + cairo_t *cr; + + /* Can't use gdk_cairo_create here due to clipping */ + surface = _gdk_drawable_ref_cairo_surface (window); + cr = cairo_create (surface); + cairo_surface_destroy (surface); + + area = cairo_region_copy (area); + + gdk_cairo_region (cr, area); + cairo_clip (cr); + + /* NB: This is a self-copy and Cairo doesn't support that yet. + * So we do a litle trick. + */ + cairo_push_group (cr); + + gdk_cairo_set_source_pixmap (cr, window, dx, dy); + cairo_paint (cr); + + cairo_pop_group_to_source (cr); + cairo_paint (cr); + + cairo_destroy (cr); + + _gdk_window_add_damage (window, area); } /** @@ -950,7 +976,7 @@ gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface) iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region; iface->set_static_gravities = gdk_offscreen_window_set_static_gravities; iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose; - iface->queue_translation = gdk_offscreen_window_queue_translation; + iface->translate = gdk_offscreen_window_translate; iface->get_root_coords = gdk_offscreen_window_get_root_coords; iface->get_deskrelative_origin = gdk_offscreen_window_get_deskrelative_origin; iface->get_device_state = gdk_offscreen_window_get_device_state; diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 91854a3f60..9cd022f4dd 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -3223,45 +3223,11 @@ do_move_region_bits_on_impl (GdkWindowObject *impl_window, cairo_region_t *dest_region, /* In impl window coords */ int dx, int dy) { - GdkGC *tmp_gc; - GdkRectangle copy_rect; - GdkWindowObject *private; GdkWindowImplIface *impl_iface; - /* We need to get data from subwindows here, because we might have - * shaped a native window over the moving region (with bg none, - * so the pixels are still there). In fact we might need to get data - * from overlapping native window that are not children of this window, - * so we copy from the toplevel with INCLUDE_INFERIORS. - */ - private = impl_window; - while (!gdk_window_is_toplevel (private)) - { - dx -= private->parent->abs_x + private->x; - dy -= private->parent->abs_y + private->y; - private = gdk_window_get_impl_window (private->parent); - } - tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private); + impl_iface = GDK_WINDOW_IMPL_GET_IFACE (impl_window->impl); - cairo_region_get_extents (dest_region, ©_rect); - gdk_gc_set_clip_region (tmp_gc, dest_region); - - /* The region area is moved and we queue translations for all expose events - to the source area that were sent prior to the copy */ - cairo_region_translate (dest_region, -dx, -dy); /* Move to source region */ - impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl); - - impl_iface->queue_translation ((GdkWindow *)impl_window, - tmp_gc, - dest_region, dx, dy); - - gdk_draw_drawable (impl_window->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_iface->translate ((GdkWindow *) impl_window, dest_region, dx, dy); } static GdkWindowRegionMove * @@ -3271,7 +3237,7 @@ gdk_window_region_move_new (cairo_region_t *region, GdkWindowRegionMove *move; move = g_slice_new (GdkWindowRegionMove); - move->dest_region = cairo_region_copy (region); + move->dest_region = cairo_region_copy (region); move->dx = dx; move->dy = dy; diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index 089706f31e..a01244e5ad 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -121,10 +121,15 @@ struct _GdkWindowImplIface * for destroying the region later. */ gboolean (* queue_antiexpose) (GdkWindow *window, - cairo_region_t *update_area); - void (* queue_translation) (GdkWindow *window, - GdkGC *gc, - cairo_region_t *area, + cairo_region_t *update_area); + + /* Called to move @area inside @window by @dx x @dy pixels. @area is + * guaranteed to be inside @window. If part of @area is not invisible or + * invalid, it is this function's job to queue expose events in those + * areas. + */ + void (* translate) (GdkWindow *window, + cairo_region_t *area, gint dx, gint dy); diff --git a/gdk/quartz/gdkgeometry-quartz.c b/gdk/quartz/gdkgeometry-quartz.c index 9881cd71b1..bde84aad94 100644 --- a/gdk/quartz/gdkgeometry-quartz.c +++ b/gdk/quartz/gdkgeometry-quartz.c @@ -22,34 +22,32 @@ #include "gdkprivate-quartz.h" +/* FIXME: Tis function has never been compiled. + * Please make it work. */ void -_gdk_quartz_window_queue_translation (GdkWindow *window, - GdkGC *gc, - cairo_region_t *area, - gint dx, - gint dy) +_gdk_quartz_window_translate (GdkWindow *window, + cairo_region_t *area, + gint dx, + gint dy) { GdkWindowObject *private = (GdkWindowObject *)window; GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *)private->impl; + GdkRectangle extents; - int i, n_rects; - cairo_region_t *intersection; - GdkRectangle rect; + cairo_region_get_extents (area, &extents); - /* We will intersect the known region that needs display with the given - * area. This intersection will be translated by dx, dy. For the end - * result, we will also set that it needs display. - */ + [window_impl->view scrollRect:NSMakeRect (extents.x, extents.y, extents.width, extents.height) + by:NSMakeSize (dx, dy)]; - if (!impl->needs_display_region) - return; + if (impl->needs_display_region) + { + intersection = cairo_region_copy (impl->needs_display_region); + cairo_region_intersect_rectangle (intersection, extents); + cairo_region_translate (intersection, dx, dy); - intersection = cairo_region_copy (impl->needs_display_region); - cairo_region_intersect (intersection, area); - cairo_region_translate (intersection, dx, dy); - - _gdk_quartz_window_set_needs_display_in_region (window, intersection); - cairo_region_destroy (intersection); + _gdk_quartz_window_set_needs_display_in_region (window, intersection); + cairo_region_destroy (intersection); + } } gboolean diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 815a3b5a4f..6e72baa768 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -3102,6 +3102,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region; iface->set_static_gravities = gdk_window_quartz_set_static_gravities; iface->queue_antiexpose = _gdk_quartz_window_queue_antiexpose; - iface->queue_translation = _gdk_quartz_window_queue_translation; + iface->translate = _gdk_quartz_window_translate; iface->destroy = _gdk_quartz_window_destroy; } diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index 53676b7364..3d5e4e725b 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -3282,25 +3282,27 @@ _gdk_win32_window_queue_antiexpose (GdkWindow *window, return FALSE; } -/* - * queue_translation is meant to only move any outstanding invalid area - * in the given area by dx,dy. A typical example of when its needed is an - * app with two toplevels where one (A) overlaps the other (B). If the - * app first moves A so that B is invalidated and then scrolls B before - * handling the expose. The scroll operation will copy the invalid area - * to a new position, but when the invalid area is then exposed it only - * redraws the old areas not the place where the invalid data was copied - * by the scroll. - */ +/* FIXME: Tis function has never been compiled. + * Please make it work. */ static void -_gdk_win32_window_queue_translation (GdkWindow *window, - GdkGC *gc, - cairo_region_t *area, - gint dx, - gint dy) +_gdk_win32_window_translate (GdkWindow *window, + cairo_region_t *area, + gint dx, + gint dy) { HRGN hrgn = CreateRectRgn (0, 0, 0, 0); - int ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE); + HDC hdc; + int ret; + GdkRectangle extents; + + cairo_region_get_extents (area, &extents); + hdc = _gdk_win32_drawable_acquire_dc (GDK_DRAWABLE (window)); + GDI_CALL (BitBlt, (hdc, extents.x, extents.y, extents.width, extents.height, + hdc, extents.x + dx, extents.y + dy, SRCCOPY)); + + /* XXX: We probably need to get invalidations for the whole extents and not + * just the area as we BitBlt */ + ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE); if (ret == ERROR) WIN32_API_FAILED ("GetUpdateRgn"); else if (ret != NULLREGION) @@ -3374,7 +3376,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin; iface->set_static_gravities = gdk_win32_window_set_static_gravities; iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose; - iface->queue_translation = _gdk_win32_window_queue_translation; + iface->translate = _gdk_win32_window_translate; iface->destroy = _gdk_win32_window_destroy; } diff --git a/gdk/x11/gdkgeometry-x11.c b/gdk/x11/gdkgeometry-x11.c index 83a899561c..4ddf5b422b 100644 --- a/gdk/x11/gdkgeometry-x11.c +++ b/gdk/x11/gdkgeometry-x11.c @@ -226,24 +226,62 @@ gdk_window_queue (GdkWindow *window, } void -_gdk_x11_window_queue_translation (GdkWindow *window, - GdkGC *gc, - cairo_region_t *area, - gint dx, - gint dy) +_gdk_x11_window_translate (GdkWindow *window, + cairo_region_t *area, + gint dx, + gint dy) { - GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1); - item->type = GDK_WINDOW_QUEUE_TRANSLATE; - item->u.translate.area = area ? cairo_region_copy (area) : NULL; - item->u.translate.dx = dx; - item->u.translate.dy = dy; + GdkWindowQueueItem *item; + GdkGC *tmp_gc; + GdkRectangle extents; + GdkWindowObject *private, *impl; + int px, py; + + /* We need to get data from subwindows here, because we might have + * shaped a native window over the moving region (with bg none, + * so the pixels are still there). In fact we might need to get data + * from overlapping native window that are not children of this window, + * so we copy from the toplevel with INCLUDE_INFERIORS. + */ + private = impl = (GdkWindowObject *) window; + px = py = 0; + while (private->parent != NULL && + private->parent->window_type != GDK_WINDOW_ROOT) + { + dx -= private->parent->abs_x + private->x; + dy -= private->parent->abs_y + private->y; + private = (GdkWindowObject *) _gdk_window_get_impl_window ((GdkWindow *) private->parent); + } + + cairo_region_get_extents (area, &extents); + + tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private); + gdk_gc_set_clip_region (tmp_gc, area); + + cairo_region_translate (area, -dx, -dy); /* Move to source region */ /* Ensure that the gc is flushed so that we get the right serial from NextRequest in gdk_window_queue, i.e. the the serial for the XCopyArea, not the ones from flushing the gc. */ - _gdk_x11_gc_flush (gc); + _gdk_x11_gc_flush (tmp_gc); + + item = g_new (GdkWindowQueueItem, 1); + item->type = GDK_WINDOW_QUEUE_TRANSLATE; + item->u.translate.area = cairo_region_copy (area); + item->u.translate.dx = dx; + item->u.translate.dy = dy; gdk_window_queue (window, item); + + XCopyArea (GDK_WINDOW_XDISPLAY (impl), + GDK_DRAWABLE_IMPL_X11 (private->impl)->xid, + GDK_DRAWABLE_IMPL_X11 (impl->impl)->xid, + GDK_GC_GET_XGC (tmp_gc), + extents.x - dx, extents.y - dy, + extents.width, extents.height, + extents.x, extents.y); + + gdk_gc_set_clip_region (tmp_gc, NULL); } gboolean diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index e536f867d7..236164fc49 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -118,8 +118,7 @@ void _gdk_window_process_expose (GdkWindow *window, gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window, cairo_region_t *area); -void _gdk_x11_window_queue_translation (GdkWindow *window, - GdkGC *gc, +void _gdk_x11_window_translate (GdkWindow *window, cairo_region_t *area, gint dx, gint dy); diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 30620077b8..1339b7bbb4 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -5562,7 +5562,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region; iface->set_static_gravities = gdk_window_x11_set_static_gravities; iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose; - iface->queue_translation = _gdk_x11_window_queue_translation; + iface->translate = _gdk_x11_window_translate; iface->destroy = _gdk_x11_window_destroy; iface->supports_native_bg = TRUE; }