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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user