[gtk+] Update shape handling
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+] Update shape handling
- Date: Mon, 31 Aug 2009 13:49:04 +0000 (UTC)
commit 4d3b19fa7cd4177d66ab6f20b52bf49ead10eb41
Author: Alexander Larsson <alexl redhat com>
Date: Thu Aug 27 18:04:07 2009 +0200
Update shape handling
For toplevels, never apply clip as shape, instead apply shape.
This way we don't have to re-set it all the time as the window size
changes. Furthermore, this change fixes unsetting a shape on a
toplevel window which didn't actually unset the shape before.
Additionally we never apply clips as shape if the shape would just
be the same as the regular window size. This means we won't unnecessarily
add a useless shape to most native child windows (and additionally this
helps apps that do weird X stuff that don't expect these shaped windows).
gdk/gdkinternals.h | 1 +
gdk/gdkwindow.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 74 insertions(+), 17 deletions(-)
---
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 4cc45f9..e35d939 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -262,6 +262,7 @@ struct _GdkWindowObject
guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */
guint native_visibility : 2; /* the native visibility of a impl windows */
guint viewable : 1; /* mapped and all parents mapped */
+ guint applied_shape : 1;
guint num_offscreen_children;
GdkWindowPaint *implicit_paint;
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index dfacc15..2785702 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -822,6 +822,61 @@ gdk_window_update_visibility_recursively (GdkWindowObject *private,
}
}
+static gboolean
+should_apply_clip_as_shape (GdkWindowObject *private)
+{
+ return
+ gdk_window_has_impl (private) &&
+ /* Not for offscreens */
+ private->window_type != GDK_WINDOW_OFFSCREEN &&
+ /* or for toplevels */
+ !gdk_window_is_toplevel (private) &&
+ /* or for foreign windows */
+ private->window_type != GDK_WINDOW_FOREIGN &&
+ /* or for the root window */
+ private->window_type != GDK_WINDOW_ROOT;
+}
+
+static void
+apply_shape (GdkWindowObject *private,
+ GdkRegion *region)
+{
+ GdkWindowImplIface *impl_iface;
+
+ /* We trash whether we applied a shape so that
+ we can avoid unsetting it many times, which
+ could happen in e.g. apply_clip_as_shape as
+ windows get resized */
+ impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+ if (region)
+ impl_iface->shape_combine_region ((GdkWindow *)private,
+ region, 0, 0);
+ else if (private->applied_shape)
+ impl_iface->shape_combine_region ((GdkWindow *)private,
+ NULL, 0, 0);
+
+ private->applied_shape = region != NULL;
+}
+
+static void
+apply_clip_as_shape (GdkWindowObject *private)
+{
+ GdkRectangle r;
+
+ r.x = r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
+
+ /* We only apply the clip region if would differ
+ from the actual clip region implied by the size
+ of the window. This is to avoid unneccessarily
+ adding meaningless shapes to all native subwindows */
+ if (!gdk_region_rect_equal (private->clip_region, &r))
+ apply_shape (private, private->clip_region);
+ else
+ apply_shape (private, NULL);
+}
+
static void
recompute_visible_regions_internal (GdkWindowObject *private,
gboolean recalculate_clip,
@@ -971,21 +1026,8 @@ recompute_visible_regions_internal (GdkWindowObject *private,
}
if (clip_region_changed &&
- gdk_window_has_impl (private) &&
- /* Not for offscreens */
- private->window_type != GDK_WINDOW_OFFSCREEN &&
- /* or for non-shaped toplevels */
- (private->shaped ||
- (private->parent != NULL &&
- private->parent->window_type != GDK_WINDOW_ROOT)) &&
- /* or for foreign windows */
- private->window_type != GDK_WINDOW_FOREIGN &&
- /* or for the root window */
- private->window_type != GDK_WINDOW_ROOT
- )
- {
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
- }
+ should_apply_clip_as_shape (private))
+ apply_clip_as_shape (private);
if (recalculate_siblings &&
!gdk_window_is_toplevel (private))
@@ -1470,7 +1512,7 @@ gdk_window_reparent (GdkWindow *window,
GdkWindowObject *new_parent_private;
GdkWindowObject *old_parent;
GdkScreen *screen;
- gboolean show, was_mapped;
+ gboolean show, was_mapped, applied_clip_as_shape;
gboolean do_reparent_to_impl;
GdkEventMask old_native_event_mask;
GdkWindowImplIface *impl_iface;
@@ -1525,6 +1567,8 @@ gdk_window_reparent (GdkWindow *window,
new_parent_private->window_type == GDK_WINDOW_FOREIGN)
gdk_window_ensure_native (window);
+ applied_clip_as_shape = should_apply_clip_as_shape (private);
+
old_native_event_mask = 0;
do_reparent_to_impl = FALSE;
if (gdk_window_has_impl (private))
@@ -1616,6 +1660,13 @@ gdk_window_reparent (GdkWindow *window,
if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
recompute_visible_regions (old_parent, FALSE, TRUE);
+ /* We used to apply the clip as the shape, but no more.
+ Reset this to the real shape */
+ if (gdk_window_has_impl (private) &&
+ applied_clip_as_shape &&
+ !should_apply_clip_as_shape (private))
+ apply_shape (private, private->shape);
+
if (do_reparent_to_impl)
reparent_to_impl (private);
else
@@ -1714,7 +1765,8 @@ gdk_window_ensure_native (GdkWindow *window)
/* The shape may not have been set, as the clip region doesn't actually
change, so do it here manually */
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+ if (should_apply_clip_as_shape (private))
+ apply_clip_as_shape (private);
reparent_to_impl (private);
@@ -7700,6 +7752,10 @@ gdk_window_shape_combine_region (GdkWindow *window,
recompute_visible_regions (private, TRUE, FALSE);
+ if (gdk_window_has_impl (private) &&
+ !should_apply_clip_as_shape (private))
+ apply_shape (private, private->shape);
+
if (old_region)
{
new_region = gdk_region_copy (private->clip_region);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]