[gtk+/client-side-windows: 57/284] Implement shaped windows
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+/client-side-windows: 57/284] Implement shaped windows
- Date: Thu, 2 Apr 2009 14:04:31 -0400 (EDT)
commit 4ba2b181bfdac308e5f10f707c5a493ad93d1679
Author: Alexander Larsson <alexl redhat com>
Date: Tue Dec 16 20:09:20 2008 +0100
Implement shaped windows
---
gdk/gdkinternals.h | 2 +
gdk/gdkwindow.c | 98 ++++++++++++++++++++++++++++++++++--------
gdk/gdkwindow.h | 2 +
gdk/x11/gdkwindow-x11.c | 108 +++++++++++++++++++++++++++++++++--------------
4 files changed, 159 insertions(+), 51 deletions(-)
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 2766c8d..7c119a4 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -336,6 +336,8 @@ 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_get_shape_for_mask (GdkBitmap *mask);
+
void _gdk_windowing_get_pointer (GdkDisplay *display,
GdkScreen **screen,
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 9655e31..6ea81d0 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -457,10 +457,25 @@ remove_child_area (GdkWindowObject *private,
r.y = child->y;
r.width = child->width;
r.height = child->height;
-
+
child_region = gdk_region_rectangle (&r);
+
+ if (child->shape)
+ 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)
+ {
+ gdk_region_intersect (child_region, shape);
+ gdk_region_destroy (shape);
+ }
+ }
+
gdk_region_subtract (region, child_region);
gdk_region_destroy (child_region);
+
}
}
@@ -512,7 +527,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
r.width = private->width;
r.height = private->height;
new_clip = gdk_region_rectangle (&r);
-
+
if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
gdk_region_intersect (new_clip, private->parent->clip_region);
@@ -524,6 +539,9 @@ recompute_visible_regions_internal (GdkWindowObject *private,
/* Convert from parent coords to window coords */
gdk_region_offset (new_clip, -private->x, -private->y);
+ if (private->shape)
+ gdk_region_intersect (new_clip, private->shape);
+
if (private->clip_region == NULL ||
!gdk_region_equal (private->clip_region, new_clip))
clip_region_changed = TRUE;
@@ -562,9 +580,10 @@ recompute_visible_regions_internal (GdkWindowObject *private,
gdk_window_has_impl (private) &&
/* Not for offscreens */
private->window_type != GDK_WINDOW_OFFSCREEN &&
- /* or for toplevels */
- private->parent != NULL &&
- GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT &&
+ /* or for non-shaped toplevels */
+ (private->shaped ||
+ (private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
/* or for foreign windows */
GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
)
@@ -6171,12 +6190,19 @@ gdk_window_shape_combine_mask (GdkWindow *window,
gint y)
{
GdkWindowObject *private;
+ GdkRegion *region;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+ region = _gdk_windowing_get_shape_for_mask (mask);
+
+ gdk_window_shape_combine_region (window,
+ region,
+ x, y);
+
+ gdk_region_destroy (region);
}
/**
@@ -6214,7 +6240,47 @@ gdk_window_shape_combine_region (GdkWindow *window,
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ private->shaped = (shape_region != NULL);
+
+ if (private->shape)
+ gdk_region_destroy (private->shape);
+
+ if (shape_region)
+ {
+ private->shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->shape, offset_x, offset_y);
+ }
+ else
+ private->shape = NULL;
+
+ recompute_visible_regions (private, TRUE, FALSE);
+}
+
+static void
+do_child_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, region);
+
+ if (merge && private->shape)
+ gdk_region_subtract (region, private->shape);
+
+ gdk_window_shape_combine_region (window, region, 0, 0);
}
/**
@@ -6229,13 +6295,9 @@ gdk_window_shape_combine_region (GdkWindow *window,
void
gdk_window_set_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+ do_child_shapes (window, FALSE);
}
/**
@@ -6254,13 +6316,9 @@ gdk_window_set_child_shapes (GdkWindow *window)
void
gdk_window_merge_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+ do_child_shapes (window, TRUE);
}
@@ -6650,10 +6708,12 @@ static gboolean
point_in_window (GdkWindowObject *window,
double x, double y)
{
- /* TODO: Input Shape */
return
x >= 0 && x < window->width &&
- y >= 0 && y < window->height;
+ y >= 0 && y < window->height &&
+ (window->shape == NULL ||
+ gdk_region_point_in (window->shape,
+ x, y));
}
static void
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 5c47578..bc08cbc 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -337,6 +337,8 @@ struct _GdkWindowObject
GdkWindowPaint *implicit_paint;
GList *outstanding_moves;
+
+ GdkRegion *shape;
cairo_surface_t *cairo_surface;
};
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 2b00d95..85f81e5 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -4757,48 +4757,92 @@ gdk_add_to_span (struct _gdk_span **s,
return;
}
-GdkRegion *
-_gdk_windowing_window_get_shape (GdkWindow *window)
+static GdkRegion *
+xwindow_get_shape (Display *xdisplay,
+ Window window)
{
GdkRegion *shape;
+ GdkRectangle *rl;
+ XRectangle *xrl;
+ gint rn, ord, i;
shape = NULL;
#if defined(HAVE_SHAPE_EXT)
- if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ xrl = XShapeGetRectangles (xdisplay,
+ window,
+ ShapeBounding, &rn, &ord);
+
+ if (rn == 0)
+ return NULL;
+
+ if (ord != YXBanded)
{
- GdkRectangle *rl;
- XRectangle *xrl;
- gint rn, ord, i;
-
- xrl = XShapeGetRectangles (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- ShapeBounding, &rn, &ord);
-
- if (ord != YXBanded)
- {
- /* 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 (rl);
- return NULL;
- }
+ /* 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;
+ }
- 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;
- }
-
- shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
- g_free (rl);
- 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;
}
+ XFree (xrl);
+
+ shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
+ g_free (rl);
+#endif
+
+ return shape;
+}
+
+
+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);
+
+ region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ return region;
+}
+
+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)))
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window));
#endif
+
+ return NULL;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]