From d7e369c27af92616309cfede96b768332b01e431 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 17 Dec 2008 11:24:46 +0100 Subject: [PATCH] Implement input shapes --- gdk/gdk.symbols | 8 +- gdk/gdkinternals.h | 1 + gdk/gdkoffscreenwindow.c | 13 +- gdk/gdkwindow.c | 214 ++++++++++++++++- gdk/gdkwindow.h | 1 + gdk/gdkwindowimpl.h | 6 +- gdk/x11/gdkwindow-x11.c | 492 ++------------------------------------- 7 files changed, 242 insertions(+), 493 deletions(-) diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index b0d82eba45..0bd950030e 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -666,6 +666,10 @@ gdk_window_shape_combine_mask gdk_window_shape_combine_region gdk_window_set_child_shapes gdk_window_merge_child_shapes +gdk_window_input_shape_combine_mask +gdk_window_input_shape_combine_region +gdk_window_set_child_input_shapes +gdk_window_merge_child_input_shapes gdk_window_set_static_gravities gdk_window_reparent gdk_window_add_filter @@ -749,8 +753,6 @@ gdk_window_set_startup_id gdk_window_set_transient_for gdk_window_get_root_origin gdk_window_get_frame_extents -gdk_window_input_shape_combine_mask -gdk_window_input_shape_combine_region gdk_window_set_override_redirect gdk_window_set_accept_focus gdk_window_set_focus_on_map @@ -774,8 +776,6 @@ gdk_window_set_group gdk_window_get_decorations gdk_window_set_decorations gdk_window_set_functions -gdk_window_set_child_input_shapes -gdk_window_merge_child_input_shapes gdk_window_begin_move_drag gdk_window_begin_resize_drag gdk_window_enable_synchronized_configure diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 7c119a493f..62d9f132fe 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -336,6 +336,7 @@ void _gdk_windowing_window_get_offsets (GdkWindow *window, gint *x_offset, gint *y_offset); GdkRegion *_gdk_windowing_window_get_shape (GdkWindow *window); +GdkRegion *_gdk_windowing_window_get_input_shape(GdkWindow *window); GdkRegion *_gdk_windowing_get_shape_for_mask (GdkBitmap *mask); diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c index 1fa7018e78..408a27dc57 100644 --- a/gdk/gdkoffscreenwindow.c +++ b/gdk/gdkoffscreenwindow.c @@ -1010,12 +1010,10 @@ gdk_offscreen_window_shape_combine_region (GdkWindow *window, } static void -gdk_offscreen_window_set_child_shapes (GdkWindow *window) -{ -} - -static void -gdk_offscreen_window_merge_child_shapes (GdkWindow *window) +gdk_offscreen_window_input_shape_combine_region (GdkWindow *window, + const GdkRegion *shape_region, + gint offset_x, + gint offset_y) { } @@ -1170,8 +1168,7 @@ gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface) iface->set_cursor = gdk_offscreen_window_set_cursor; iface->get_geometry = gdk_offscreen_window_get_geometry; iface->shape_combine_region = gdk_offscreen_window_shape_combine_region; - iface->set_child_shapes = gdk_offscreen_window_set_child_shapes; - iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes; + 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; diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 6ea81d042d..8fdb622ec3 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -383,6 +383,12 @@ gdk_window_finalize (GObject *object) obj->impl = NULL; } + if (obj->shape) + gdk_region_destroy (obj->shape); + + if (obj->input_shape) + gdk_region_destroy (obj->input_shape); + if (obj->cursor) gdk_cursor_unref (obj->cursor); @@ -431,12 +437,14 @@ gdk_window_has_no_impl (GdkWindowObject *window) static void remove_child_area (GdkWindowObject *private, GdkWindowObject *until, + gboolean for_input, GdkRegion *region) { GdkWindowObject *child; GdkRegion *child_region; GdkRectangle r; GList *l; + GdkRegion *shape; for (l = private->children; l; l = l->next) { @@ -464,7 +472,6 @@ remove_child_area (GdkWindowObject *private, gdk_region_intersect (child_region, child->shape); else if (private->window_type == GDK_WINDOW_FOREIGN) { - GdkRegion *shape; shape = _gdk_windowing_window_get_shape ((GdkWindow *)child); if (shape) { @@ -472,6 +479,21 @@ remove_child_area (GdkWindowObject *private, gdk_region_destroy (shape); } } + + if (for_input) + { + if (child->input_shape) + gdk_region_intersect (child_region, child->input_shape); + else if (private->window_type == GDK_WINDOW_FOREIGN) + { + shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child); + if (shape) + { + gdk_region_intersect (child_region, shape); + gdk_region_destroy (shape); + } + } + } gdk_region_subtract (region, child_region); gdk_region_destroy (child_region); @@ -533,7 +555,7 @@ recompute_visible_regions_internal (GdkWindowObject *private, gdk_region_intersect (new_clip, private->parent->clip_region); /* Remove all overlapping children from parent */ - remove_child_area (private->parent, private, new_clip); + remove_child_area (private->parent, private, FALSE, new_clip); } /* Convert from parent coords to window coords */ @@ -552,7 +574,7 @@ recompute_visible_regions_internal (GdkWindowObject *private, old_clip_region_with_children = private->clip_region_with_children; private->clip_region_with_children = gdk_region_copy (private->clip_region); - remove_child_area (private, NULL, private->clip_region_with_children); + remove_child_area (private, NULL, FALSE, private->clip_region_with_children); if (clip_region_changed || !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children)) @@ -590,8 +612,7 @@ recompute_visible_regions_internal (GdkWindowObject *private, { GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0); } - - + if (recalculate_siblings && private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT) @@ -1119,6 +1140,8 @@ gdk_window_set_has_native (GdkWindow *window, gboolean has_native) private->impl = old_impl; change_impl (private, new_impl); + + GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0); } else { @@ -6275,7 +6298,7 @@ do_child_shapes (GdkWindow *window, r.height = private->height; region = gdk_region_rectangle (&r); - remove_child_area (private, NULL, region); + remove_child_area (private, NULL, FALSE, region); if (merge && private->shape) gdk_region_subtract (region, private->shape); @@ -6321,6 +6344,182 @@ gdk_window_merge_child_shapes (GdkWindow *window) do_child_shapes (window, TRUE); } +/** + * gdk_window_input_shape_combine_mask: + * @window: a #GdkWindow + * @mask: shape mask + * @x: X position of shape mask with respect to @window + * @y: Y position of shape mask with respect to @window + * + * Like gdk_window_shape_combine_mask(), but the shape applies + * only to event handling. Mouse events which happen while + * the pointer position corresponds to an unset bit in the + * mask will be passed on the window below @window. + * + * An input shape is typically used with RGBA windows. + * The alpha channel of the window defines which pixels are + * invisible and allows for nicely antialiased borders, + * and the input shape controls where the window is + * "clickable". + * + * On the X11 platform, this requires version 1.1 of the + * shape extension. + * + * On the Win32 platform, this functionality is not present and the + * function does nothing. + * + * Since: 2.10 + */ +void +gdk_window_input_shape_combine_mask (GdkWindow *window, + GdkBitmap *mask, + gint x, + gint y) +{ + GdkWindowObject *private; + GdkRegion *region; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + private = (GdkWindowObject *) window; + + region = _gdk_windowing_get_shape_for_mask (mask); + + gdk_window_input_shape_combine_region (window, + region, + x, y); + + gdk_region_destroy (region); +} + +/** + * gdk_window_input_shape_combine_region: + * @window: a #GdkWindow + * @shape_region: region of window to be non-transparent + * @offset_x: X position of @shape_region in @window coordinates + * @offset_y: Y position of @shape_region in @window coordinates + * + * Like gdk_window_shape_combine_region(), but the shape applies + * only to event handling. Mouse events which happen while + * the pointer position corresponds to an unset bit in the + * mask will be passed on the window below @window. + * + * An input shape is typically used with RGBA windows. + * The alpha channel of the window defines which pixels are + * invisible and allows for nicely antialiased borders, + * and the input shape controls where the window is + * "clickable". + * + * On the X11 platform, this requires version 1.1 of the + * shape extension. + * + * On the Win32 platform, this functionality is not present and the + * function does nothing. + * + * Since: 2.10 + */ +void +gdk_window_input_shape_combine_region (GdkWindow *window, + const GdkRegion *shape_region, + gint offset_x, + gint offset_y) +{ + GdkWindowObject *private; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + private = (GdkWindowObject *) window; + + if (GDK_WINDOW_DESTROYED (window)) + return; + + if (private->input_shape) + gdk_region_destroy (private->input_shape); + + if (shape_region) + { + private->input_shape = gdk_region_copy (shape_region); + gdk_region_offset (private->shape, offset_x, offset_y); + } + else + private->input_shape = NULL; + + if (gdk_window_has_impl (private)) + GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0); + + /* Pointer may have e.g. moved outside window due to the input mask change */ + _gdk_syntesize_crossing_events_for_geometry_change (window); +} + +static void +do_child_input_shapes (GdkWindow *window, + gboolean merge) +{ + GdkWindowObject *private; + GdkRectangle r; + GdkRegion *region; + + private = (GdkWindowObject *) window; + + r.x = 0; + r.y = 0; + r.width = private->width; + r.height = private->height; + + region = gdk_region_rectangle (&r); + remove_child_area (private, NULL, TRUE, region); + + if (merge && private->shape) + gdk_region_subtract (region, private->shape); + if (merge && private->input_shape) + gdk_region_subtract (region, private->input_shape); + + gdk_window_input_shape_combine_region (window, region, 0, 0); +} + + +/** + * gdk_window_set_child_input_shapes: + * @window: a #GdkWindow + * + * Sets the input shape mask of @window to the union of input shape masks + * for all children of @window, ignoring the input shape mask of @window + * itself. Contrast with gdk_window_merge_child_input_shapes() which includes + * the input shape mask of @window in the masks to be merged. + * + * Since: 2.10 + **/ +void +gdk_window_set_child_input_shapes (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + do_child_input_shapes (window, FALSE); +} + +/** + * gdk_window_merge_child_input_shapes: + * @window: a #GdkWindow + * + * Merges the input shape masks for any child windows into the + * input shape mask for @window. i.e. the union of all input masks + * for @window and its children will become the new input mask + * for @window. See gdk_window_input_shape_combine_mask(). + * + * This function is distinct from gdk_window_set_child_input_shapes() + * because it includes @window's input shape mask in the set of + * shapes to be merged. + * + * Since: 2.10 + **/ +void +gdk_window_merge_child_input_shapes (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + do_child_input_shapes (window, TRUE); +} + /** * gdk_window_set_static_gravities: @@ -6713,6 +6912,9 @@ point_in_window (GdkWindowObject *window, y >= 0 && y < window->height && (window->shape == NULL || gdk_region_point_in (window->shape, + x, y)) && + (window->input_shape == NULL || + gdk_region_point_in (window->input_shape, x, y)); } diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index bc08cbc51b..0956dd693e 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -339,6 +339,7 @@ struct _GdkWindowObject GList *outstanding_moves; GdkRegion *shape; + GdkRegion *input_shape; cairo_surface_t *cairo_surface; }; diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index 5b252a2abf..dacaf747a7 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -90,8 +90,10 @@ struct _GdkWindowImplIface const GdkRegion *shape_region, gint offset_x, gint offset_y); - void (* set_child_shapes) (GdkWindow *window); - void (* merge_child_shapes) (GdkWindow *window); + void (* input_shape_combine_region) (GdkWindow *window, + const GdkRegion *shape_region, + gint offset_x, + gint offset_y); gboolean (* set_static_gravities) (GdkWindow *window, gboolean use_static); diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 90f38964cb..f2641f7d1f 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -3375,44 +3375,6 @@ gdk_window_add_colormap_windows (GdkWindow *window) XFree (old_windows); } -/** - * gdk_window_input_shape_combine_mask: - * @window: a #GdkWindow - * @mask: shape mask - * @x: X position of shape mask with respect to @window - * @y: Y position of shape mask with respect to @window - * - * Like gdk_window_shape_combine_mask(), but the shape applies - * only to event handling. Mouse events which happen while - * the pointer position corresponds to an unset bit in the - * mask will be passed on the window below @window. - * - * An input shape is typically used with RGBA windows. - * The alpha channel of the window defines which pixels are - * invisible and allows for nicely antialiased borders, - * and the input shape controls where the window is - * "clickable". - * - * On the X11 platform, this requires version 1.1 of the - * shape extension. - * - * On the Win32 platform, this functionality is not present and the - * function does nothing. - * - * Since: 2.10 - */ -void -gdk_window_input_shape_combine_mask (GdkWindow *window, - GdkBitmap *mask, - gint x, - gint y) -{ -#ifdef ShapeInput - do_shape_combine_mask (window, mask, x, y, ShapeInput); -#endif -} - - static inline void do_shape_combine_region (GdkWindow *window, const GdkRegion *shape_region, @@ -3479,37 +3441,11 @@ gdk_window_x11_shape_combine_region (GdkWindow *window, do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding); } -/** - * gdk_window_input_shape_combine_region: - * @window: a #GdkWindow - * @shape_region: region of window to be non-transparent - * @offset_x: X position of @shape_region in @window coordinates - * @offset_y: Y position of @shape_region in @window coordinates - * - * Like gdk_window_shape_combine_region(), but the shape applies - * only to event handling. Mouse events which happen while - * the pointer position corresponds to an unset bit in the - * mask will be passed on the window below @window. - * - * An input shape is typically used with RGBA windows. - * The alpha channel of the window defines which pixels are - * invisible and allows for nicely antialiased borders, - * and the input shape controls where the window is - * "clickable". - * - * On the X11 platform, this requires version 1.1 of the - * shape extension. - * - * On the Win32 platform, this functionality is not present and the - * function does nothing. - * - * Since: 2.10 - */ -void -gdk_window_input_shape_combine_region (GdkWindow *window, - const GdkRegion *shape_region, - gint offset_x, - gint offset_y) +static void +gdk_window_x11_input_shape_combine_region (GdkWindow *window, + const GdkRegion *shape_region, + gint offset_x, + gint offset_y) { #ifdef ShapeInput do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput); @@ -4568,152 +4504,10 @@ gdk_window_set_functions (GdkWindow *window, gdk_window_set_mwm_hints (window, &hints); } -#ifdef HAVE_SHAPE_EXT - -/* - * propagate the shapes from all child windows of a GDK window to the parent - * window. Shamelessly ripped from Enlightenment's code - * - * - Raster - */ -struct _gdk_span -{ - gint start; - gint end; - struct _gdk_span *next; -}; - -static void -gdk_add_to_span (struct _gdk_span **s, - gint x, - gint xx) -{ - struct _gdk_span *ptr1, *ptr2, *noo, *ss; - gchar spanning; - - ptr2 = NULL; - ptr1 = *s; - spanning = 0; - ss = NULL; - /* scan the spans for this line */ - while (ptr1) - { - /* -- -> new span */ - /* == -> existing span */ - /* ## -> spans intersect */ - /* if we are in the middle of spanning the span into the line */ - if (spanning) - { - /* case: ---- ==== */ - if (xx < ptr1->start - 1) - { - /* ends before next span - extend to here */ - ss->end = xx; - return; - } - /* case: ----##=== */ - else if (xx <= ptr1->end) - { - /* crosses into next span - delete next span and append */ - ss->end = ptr1->end; - ss->next = ptr1->next; - g_free (ptr1); - return; - } - /* case: ---###--- */ - else - { - /* overlaps next span - delete and keep checking */ - ss->next = ptr1->next; - g_free (ptr1); - ptr1 = ss; - } - } - /* otherwise havent started spanning it in yet */ - else - { - /* case: ---- ==== */ - if (xx < ptr1->start - 1) - { - /* insert span here in list */ - noo = g_malloc (sizeof (struct _gdk_span)); - - if (noo) - { - noo->start = x; - noo->end = xx; - noo->next = ptr1; - if (ptr2) - ptr2->next = noo; - else - *s = noo; - } - return; - } - /* case: ----##=== */ - else if ((x < ptr1->start) && (xx <= ptr1->end)) - { - /* expand this span to the left point of the new one */ - ptr1->start = x; - return; - } - /* case: ===###=== */ - else if ((x >= ptr1->start) && (xx <= ptr1->end)) - { - /* throw the span away */ - return; - } - /* case: ---###--- */ - else if ((x < ptr1->start) && (xx > ptr1->end)) - { - ss = ptr1; - spanning = 1; - ptr1->start = x; - ptr1->end = xx; - } - /* case: ===##---- */ - else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end)) - { - ss = ptr1; - spanning = 1; - ptr1->end = xx; - } - /* case: ==== ---- */ - /* case handled by next loop iteration - first case */ - } - ptr2 = ptr1; - ptr1 = ptr1->next; - } - /* it started in the middle but spans beyond your current list */ - if (spanning) - { - ptr2->end = xx; - return; - } - /* it does not start inside a span or in the middle, so add it to the end */ - noo = g_malloc (sizeof (struct _gdk_span)); - - if (noo) - { - noo->start = x; - noo->end = xx; - if (ptr2) - { - noo->next = ptr2->next; - ptr2->next = noo; - } - else - { - noo->next = NULL; - *s = noo; - } - } - return; -} - static GdkRegion * xwindow_get_shape (Display *xdisplay, - Window window) + Window window, + gint shape_type) { GdkRegion *shape; GdkRectangle *rl; @@ -4725,8 +4519,8 @@ xwindow_get_shape (Display *xdisplay, #if defined(HAVE_SHAPE_EXT) xrl = XShapeGetRectangles (xdisplay, window, - ShapeBounding, &rn, &ord); - + shape_type, &rn, &ord); + if (rn == 0) return gdk_region_new (); /* Empty */ @@ -4778,7 +4572,7 @@ _gdk_windowing_get_shape_for_mask (GdkBitmap *mask) ShapeSet); region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display), - window); + window, ShapeBounding); XDestroyWindow (GDK_DISPLAY_XDISPLAY (display), window); @@ -4793,273 +4587,26 @@ _gdk_windowing_window_get_shape (GdkWindow *window) if (!GDK_WINDOW_DESTROYED (window) && gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))) return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window)); + GDK_WINDOW_XID (window), ShapeBounding); #endif return NULL; } -static void -gdk_add_rectangles (Display *disp, - Window win, - struct _gdk_span **spans, - gint basew, - gint baseh, - gint x, - gint y) +GdkRegion * +_gdk_windowing_window_get_input_shape (GdkWindow *window) { - gint a, k; - gint x1, y1, x2, y2; - gint rn, ord; - XRectangle *rl; - - rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord); - if (rl) - { - /* go through all clip rects in this window's shape */ - for (k = 0; k < rn; k++) - { - /* for each clip rect, add it to each line's spans */ - x1 = x + rl[k].x; - x2 = x + rl[k].x + (rl[k].width - 1); - y1 = y + rl[k].y; - y2 = y + rl[k].y + (rl[k].height - 1); - if (x1 < 0) - x1 = 0; - if (y1 < 0) - y1 = 0; - if (x2 >= basew) - x2 = basew - 1; - if (y2 >= baseh) - y2 = baseh - 1; - for (a = y1; a <= y2; a++) - { - if ((x2 - x1) >= 0) - gdk_add_to_span (&spans[a], x1, x2); - } - } - XFree (rl); - } -} - -static void -gdk_propagate_shapes (Display *disp, - Window win, - gboolean merge, - int shape) -{ - Window rt, par, *list = NULL; - gint i, j, num = 0, num_rects = 0; - gint x, y, contig; - guint w, h, d; - gint baseh, basew; - XRectangle *rects = NULL; - struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3; - XWindowAttributes xatt; - - XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d); - if (h <= 0) - return; - basew = w; - baseh = h; - spans = g_malloc (sizeof (struct _gdk_span *) * h); - - for (i = 0; i < h; i++) - spans[i] = NULL; - XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num); - if (list) - { - /* go through all child windows and create/insert spans */ - for (i = 0; i < num; i++) - { - if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped)) - if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d)) - gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y); - } - if (merge) - gdk_add_rectangles (disp, win, spans, basew, baseh, x, y); - - /* go through the spans list and build a list of rects */ - rects = g_malloc (sizeof (XRectangle) * 256); - num_rects = 0; - for (i = 0; i < baseh; i++) - { - ptr1 = spans[i]; - /* go through the line for all spans */ - while (ptr1) - { - rects[num_rects].x = ptr1->start; - rects[num_rects].y = i; - rects[num_rects].width = ptr1->end - ptr1->start + 1; - rects[num_rects].height = 1; - j = i + 1; - /* if there are more lines */ - contig = 1; - /* while contigous rects (same start/end coords) exist */ - while ((contig) && (j < baseh)) - { - /* search next line for spans matching this one */ - contig = 0; - ptr2 = spans[j]; - ptr3 = NULL; - while (ptr2) - { - /* if we have an exact span match set contig */ - if ((ptr2->start == ptr1->start) && - (ptr2->end == ptr1->end)) - { - contig = 1; - /* remove the span - not needed */ - if (ptr3) - { - ptr3->next = ptr2->next; - g_free (ptr2); - ptr2 = NULL; - } - else - { - spans[j] = ptr2->next; - g_free (ptr2); - ptr2 = NULL; - } - break; - } - /* gone past the span point no point looking */ - else if (ptr2->start < ptr1->start) - break; - if (ptr2) - { - ptr3 = ptr2; - ptr2 = ptr2->next; - } - } - /* if a contiguous span was found increase the rect h */ - if (contig) - { - rects[num_rects].height++; - j++; - } - } - /* up the rect count */ - num_rects++; - /* every 256 new rects increase the rect array */ - if ((num_rects % 256) == 0) - rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256)); - ptr1 = ptr1->next; - } - } - /* set the rects as the shape mask */ - if (rects) - { - XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects, - ShapeSet, YXSorted); - g_free (rects); - } - XFree (list); - } - /* free up all the spans we made */ - for (i = 0; i < baseh; i++) - { - ptr1 = spans[i]; - while (ptr1) - { - ptr2 = ptr1; - ptr1 = ptr1->next; - g_free (ptr2); - } - } - g_free (spans); -} - -#endif /* HAVE_SHAPE_EXT */ - -static inline void -do_child_shapes (GdkWindow *window, - gboolean merge) -{ -#ifdef HAVE_SHAPE_EXT +#if defined(HAVE_SHAPE_EXT) if (!GDK_WINDOW_DESTROYED (window) && gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))) - { - gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - merge, - ShapeBounding); - } + return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + ShapeInput); #endif -} -static void -gdk_window_x11_set_child_shapes (GdkWindow *window) -{ - do_child_shapes (window, FALSE); + return NULL; } -static void -gdk_window_x11_merge_child_shapes (GdkWindow *window) -{ - do_child_shapes (window, TRUE); -} - -static inline void -do_child_input_shapes (GdkWindow *window, - gboolean merge) -{ -#if defined(HAVE_SHAPE_EXT) && defined(ShapeInput) - if (!GDK_WINDOW_DESTROYED (window) && - gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))) - { - gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - merge, - ShapeInput); - } -#endif -} - -/** - * gdk_window_set_child_input_shapes: - * @window: a #GdkWindow - * - * Sets the input shape mask of @window to the union of input shape masks - * for all children of @window, ignoring the input shape mask of @window - * itself. Contrast with gdk_window_merge_child_input_shapes() which includes - * the input shape mask of @window in the masks to be merged. - * - * Since: 2.10 - **/ -void -gdk_window_set_child_input_shapes (GdkWindow *window) -{ - g_return_if_fail (GDK_IS_WINDOW (window)); - - do_child_input_shapes (window, FALSE); -} - -/** - * gdk_window_merge_child_input_shapes: - * @window: a #GdkWindow - * - * Merges the input shape masks for any child windows into the - * input shape mask for @window. i.e. the union of all input masks - * for @window and its children will become the new input mask - * for @window. See gdk_window_input_shape_combine_mask(). - * - * This function is distinct from gdk_window_set_child_input_shapes() - * because it includes @window's input shape mask in the set of - * shapes to be merged. - * - * Since: 2.10 - **/ -void -gdk_window_merge_child_input_shapes (GdkWindow *window) -{ - g_return_if_fail (GDK_IS_WINDOW (window)); - - do_child_input_shapes (window, TRUE); -} - - static void gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on) @@ -5962,8 +5509,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->get_origin = gdk_window_x11_get_origin; iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin; iface->shape_combine_region = gdk_window_x11_shape_combine_region; - iface->set_child_shapes = gdk_window_x11_set_child_shapes; - iface->merge_child_shapes = gdk_window_x11_merge_child_shapes; + 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;