[gtk+] Update shape handling



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]