gtk2/csw-fixes.patch
2009-07-08 05:47:59 +00:00

184 lines
5.9 KiB
Diff

diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
index 869d535..44652bc 100644
--- a/gdk/gdkdraw.c
+++ b/gdk/gdkdraw.c
@@ -752,9 +752,6 @@ gdk_draw_image (GdkDrawable *drawable,
* On older X servers, rendering pixbufs with an alpha channel involves round
* trips to the X server, and may be somewhat slow.
*
- * The clip mask of @gc is ignored, but clip rectangles and clip regions work
- * fine.
- *
* If GDK is built with the Sun mediaLib library, the gdk_draw_pixbuf
* function is accelerated using mediaLib, which provides hardware
* acceleration on Intel, AMD, and Sparc chipsets. If desired, mediaLib
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
index b4c6f81..699cebf 100644
--- a/gdk/gdkgc.c
+++ b/gdk/gdkgc.c
@@ -646,24 +646,49 @@ _gdk_gc_add_drawable_clip (GdkGC *gc,
GdkPixmap *new_mask;
GdkGC *tmp_gc;
GdkColor black = {0, 0, 0, 0};
+ GdkRectangle r;
+ GdkOverlapType overlap;
- priv->old_clip_mask = g_object_ref (priv->clip_mask);
- gdk_drawable_get_size (priv->old_clip_mask, &w, &h);
-
- new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
- tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
-
- gdk_gc_set_foreground (tmp_gc, &black);
- gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
- _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
- gdk_draw_drawable (new_mask,
- tmp_gc,
- priv->old_clip_mask,
- 0, 0,
- 0, 0,
- -1, -1);
- gdk_gc_set_clip_region (tmp_gc, NULL);
- gdk_gc_set_clip_mask (gc, new_mask);
+ gdk_drawable_get_size (priv->clip_mask, &w, &h);
+
+ r.x = 0;
+ r.y = 0;
+ r.width = w;
+ r.height = h;
+
+ /* Its quite common to expose areas that are completely in or outside
+ * the region, so we try to avoid allocating bitmaps that are just fully
+ * set or completely unset.
+ */
+ overlap = gdk_region_rect_in (region, &r);
+ if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+ {
+ /* The region and the mask intersect, create a new clip mask that
+ includes both areas */
+ priv->old_clip_mask = g_object_ref (priv->clip_mask);
+ new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
+
+ gdk_gc_set_foreground (tmp_gc, &black);
+ gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
+ _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
+ gdk_draw_drawable (new_mask,
+ tmp_gc,
+ priv->old_clip_mask,
+ 0, 0,
+ 0, 0,
+ -1, -1);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+ gdk_gc_set_clip_mask (gc, new_mask);
+ }
+ else if (overlap == GDK_OVERLAP_RECTANGLE_OUT)
+ {
+ GdkRegion *empty = gdk_region_new ();
+
+ priv->old_clip_mask = g_object_ref (priv->clip_mask);
+ _gdk_windowing_gc_set_clip_region (gc, empty, FALSE);
+ gdk_region_destroy (empty);
+ }
}
else
{
@@ -775,6 +800,24 @@ _gdk_gc_get_clip_region (GdkGC *gc)
}
/**
+ * _gdk_gc_get_clip_mask:
+ * @gc: a #GdkGC
+ *
+ * Gets the current clip mask for @gc, if any.
+ *
+ * Return value: the clip mask for the GC, or %NULL.
+ * (if a clip region is set, the return will be %NULL)
+ * This value is owned by the GC and must not be freed.
+ **/
+GdkBitmap *
+_gdk_gc_get_clip_mask (GdkGC *gc)
+{
+ g_return_val_if_fail (GDK_IS_GC (gc), NULL);
+
+ return GDK_GC_GET_PRIVATE (gc)->clip_mask;
+}
+
+/**
* _gdk_gc_get_fill:
* @gc: a #GdkGC
*
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 946c3f9..c984386 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -399,6 +399,7 @@ void _gdk_gc_init (GdkGC *gc,
GdkGCValuesMask values_mask);
GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc);
+GdkBitmap *_gdk_gc_get_clip_mask (GdkGC *gc);
gboolean _gdk_gc_get_exposures (GdkGC *gc);
GdkFill _gdk_gc_get_fill (GdkGC *gc);
GdkPixmap *_gdk_gc_get_tile (GdkGC *gc);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 6e72cab..d9b1e5b 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -639,7 +639,12 @@ remove_child_area (GdkWindowObject *private,
child_region = gdk_region_rectangle (&r);
if (child->shape)
- gdk_region_intersect (child_region, child->shape);
+ {
+ /* Adjust shape region to parent window coords */
+ gdk_region_offset (child->shape, child->x, child->y);
+ gdk_region_intersect (child_region, child->shape);
+ gdk_region_offset (child->shape, -child->x, -child->y);
+ }
else if (private->window_type == GDK_WINDOW_FOREIGN)
{
shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
@@ -4660,7 +4665,12 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
child_region = gdk_region_rectangle (&r);
if (child->shape)
- gdk_region_intersect (child_region, child->shape);
+ {
+ /* Adjust shape region to parent window coords */
+ gdk_region_offset (child->shape, child->x, child->y);
+ gdk_region_intersect (child_region, child->shape);
+ gdk_region_offset (child->shape, -child->x, -child->y);
+ }
if (child->impl == private->impl)
{
diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c
index 537a47e..b2cac29 100644
--- a/gdk/x11/gdkdrawable-x11.c
+++ b/gdk/x11/gdkdrawable-x11.c
@@ -388,9 +388,22 @@ gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
else
{
XRenderPictureAttributes pa;
- pa.clip_mask = None;
+ GdkBitmap *mask;
+ gulong pa_mask;
+
+ pa_mask = CPClipMask;
+ if (gc && (mask = _gdk_gc_get_clip_mask (gc)))
+ {
+ pa.clip_mask = GDK_PIXMAP_XID (mask);
+ pa.clip_x_origin = gc->clip_x_origin;
+ pa.clip_y_origin = gc->clip_y_origin;
+ pa_mask |= CPClipXOrigin | CPClipYOrigin;
+ }
+ else
+ pa.clip_mask = None;
+
XRenderChangePicture (xdisplay, picture,
- CPClipMask, &pa);
+ pa_mask, &pa);
}
}