gint shape)
{
GdkWindowObject *private = (GdkWindowObject *)window;
- gint xoffset, yoffset;
-
+
- #ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
ShapeSet,
YXBanded);
+ if (shape == ShapeBounding)
+ {
+ _gdk_x11_window_tmp_reset_parent_bg (window);
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
+ }
+
g_free (xrects);
}
- #endif /* HAVE_SHAPE_EXT */
}
static void
gdk_window_set_mwm_hints (window, &hints);
}
-/*
- * 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
+static GdkRegion *
+xwindow_get_shape (Display *xdisplay,
+ Window window,
+ gint shape_type)
{
- gint start;
- gint end;
- struct _gdk_span *next;
-};
+ GdkRegion *shape;
+ GdkRectangle *rl;
+ XRectangle *xrl;
+ gint rn, ord, i;
-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));
+ shape = NULL;
+
- #if defined(HAVE_SHAPE_EXT)
+ xrl = XShapeGetRectangles (xdisplay,
+ window,
+ shape_type, &rn, &ord);
- if (noo)
+ if (rn == 0)
+ return gdk_region_new (); /* Empty */
+
+ if (ord != YXBanded)
{
- noo->start = x;
- noo->end = xx;
- if (ptr2)
- {
- noo->next = ptr2->next;
- ptr2->next = noo;
- }
- else
- {
- noo->next = NULL;
- *s = noo;
- }
+ /* This really shouldn't happen with any xserver, as they
+ generally convert regions to YXBanded internally */
+ g_warning ("non YXBanded shape masks not supported");
+ XFree (xrl);
+ return NULL;
}
- return;
-}
-static void
-gdk_add_rectangles (Display *disp,
- Window win,
- struct _gdk_span **spans,
- gint basew,
- gint baseh,
- gint x,
- gint y)
-{
- 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);
+ rl = g_new (GdkRectangle, rn);
+ for (i = 0; i < rn; i++)
+ {
+ rl[i].x = xrl[i].x;
+ rl[i].y = xrl[i].y;
+ rl[i].width = xrl[i].width;
+ rl[i].height = xrl[i].height;
}
- #endif
+ XFree (xrl);
+
+ shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
+ g_free (rl);
+
+ return shape;
}
-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);
+
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+ GdkDisplay *display;
+ Window window;
+ GdkRegion *region;
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (mask));
+
+ window = XCreateSimpleWindow (GDK_DISPLAY_XDISPLAY (display),
+ GDK_SCREEN_XROOTWIN (gdk_display_get_default_screen (display)),
+ -1, -1, 1, 1, 0,
+ 0, 0);
+ XShapeCombineMask (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ ShapeBounding,
+ 0, 0,
+ GDK_PIXMAP_XID (mask),
+ ShapeSet);
- 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);
+ region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+ window, ShapeBounding);
+
+ XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ return region;
}
-static inline void
-do_child_shapes (GdkWindow *window,
- gboolean merge)
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
{
- #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), ShapeBounding);
- #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)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
{
- #if defined(HAVE_SHAPE_EXT)
+ #if 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);
- }
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ 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);
+ return NULL;
}
-
static void
gdk_window_set_static_bit_gravity (GdkWindow *window,
gboolean on)