diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index c9d537828d..0acd617069 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -265,6 +265,11 @@ GdkPixmap *_gdk_bitmap_create_from_data (GdkDrawable *drawable, const gchar *data, gint width, gint height); +void _gdk_pixmap_set_as_backing (GdkPixmap *pixmap, + GdkWindow *window, + int x_offset, + int y_offset); + void _gdk_window_impl_new (GdkWindow *window, GdkWindow *real_parent, diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c index 4a67feb4db..3b27eda589 100644 --- a/gdk/gdkpixmap.c +++ b/gdk/gdkpixmap.c @@ -225,6 +225,9 @@ gdk_pixmap_finalize (GObject *object) g_object_unref (obj->impl); obj->impl = NULL; + + if (obj->backing_for) + g_object_unref (obj->backing_for); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -277,6 +280,30 @@ gdk_pixmap_create_from_data (GdkDrawable *drawable, } +/* Make GraphicsExposures and NoExposures and similar things report + * events on this window. Make sure to ref the pixmap for each operation + * that will result in a GraphicsExposure, because the core code will unref + * if for each such event. This is so that the pixmap live long enought to + * get the events on the window. + */ +void +_gdk_pixmap_set_as_backing (GdkPixmap *pixmap, + GdkWindow *window, + int x_offset, + int y_offset) +{ + GdkPixmapObject *private = (GdkPixmapObject *)pixmap; + + if (private->backing_for) + g_object_unref (private->backing_for); + private->backing_for = window; + if (private->backing_for) + g_object_ref (private->backing_for); + private->backing_x_offset = x_offset; + private->backing_y_offset = y_offset; + +} + static GdkGC * gdk_pixmap_create_gc (GdkDrawable *drawable, GdkGCValues *values, diff --git a/gdk/gdkpixmap.h b/gdk/gdkpixmap.h index e309038915..863fa1b499 100644 --- a/gdk/gdkpixmap.h +++ b/gdk/gdkpixmap.h @@ -54,6 +54,9 @@ struct _GdkPixmapObject GdkDrawable *impl; /* window-system-specific delegate object */ gint depth; + GdkWindow *backing_for; + int backing_x_offset; + int backing_y_offset; }; struct _GdkPixmapObjectClass diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 26e5de456b..2a8c32c779 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -902,6 +902,9 @@ gdk_event_translate (GdkDisplay *display, GdkToplevelX11 *toplevel = NULL; GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display); Window xwindow, filter_xwindow; + int exposure_x_offset = 0; + int exposure_y_offset = 0; + GdkWindow *unref_pixmap = NULL; return_val = FALSE; @@ -929,13 +932,31 @@ gdk_event_translate (GdkDisplay *display, * are reported same as structure events */ get_real_window (display, xevent, &xwindow, &filter_xwindow); - + window = gdk_window_lookup_for_display (display, xwindow); + /* We may receive events such as NoExpose/GraphicsExpose * and ShmCompletion for pixmaps */ if (window && !GDK_IS_WINDOW (window)) - window = NULL; + { + GdkPixmapObject *pixmap = (GdkPixmapObject *)window; + if ((xevent->type == GraphicsExpose || + xevent->type == NoExpose) && + GDK_IS_PIXMAP (window) && + pixmap->backing_for != NULL) + { + /* Unref the pixmap once for each finished set of GraphicsExposes */ + if (xevent->type == NoExpose || + xevent->xgraphicsexpose.count == 0) + unref_pixmap = window; + window = g_object_ref (pixmap->backing_for); + exposure_x_offset = pixmap->backing_x_offset; + exposure_y_offset = pixmap->backing_x_offset; + } + else + window = NULL; + } window_private = (GdkWindowObject *) window; /* We always run the filters for the window where the event @@ -1660,8 +1681,8 @@ gdk_event_translate (GdkDisplay *display, break; } - expose_rect.x = xevent->xgraphicsexpose.x; - expose_rect.y = xevent->xgraphicsexpose.y; + expose_rect.x = xevent->xgraphicsexpose.x + exposure_x_offset; + expose_rect.y = xevent->xgraphicsexpose.y + exposure_y_offset; expose_rect.width = xevent->xgraphicsexpose.width; expose_rect.height = xevent->xgraphicsexpose.height; @@ -2202,6 +2223,9 @@ gdk_event_translate (GdkDisplay *display, if (window) g_object_unref (window); + + if (unref_pixmap) + g_object_unref (unref_pixmap); return return_val; }