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).
This commit is contained in:
Alexander Larsson
2009-08-27 18:04:07 +02:00
parent cc5b22cc81
commit 4d3b19fa7c
2 changed files with 74 additions and 17 deletions

View File

@@ -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;

View File

@@ -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);