[gtk+/wip/matthiasc/fancy-overlay: 24/26] Add a blur child property to GtkOverlay



commit c9eb292362d0b139461d1906086a72b663d9e11c
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Sep 2 20:42:47 2017 -0400

    Add a blur child property to GtkOverlay
    
    When set, it blurs the content behind the child.

 gtk/gtkoverlay.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 103 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c
index 9c46f34..97ee9eb 100644
--- a/gtk/gtkoverlay.c
+++ b/gtk/gtkoverlay.c
@@ -25,6 +25,7 @@
 #include "gtkscrolledwindow.h"
 #include "gtkwidgetprivate.h"
 #include "gtkmarshalers.h"
+#include "gtksnapshot.h"
 
 #include "gtkprivate.h"
 #include "gtkintl.h"
@@ -65,6 +66,7 @@ struct _GtkOverlayChild
 {
   GtkWidget *widget;
   gboolean pass_through;
+  double blur;
 };
 
 enum {
@@ -76,6 +78,7 @@ enum
 {
   CHILD_PROP_0,
   CHILD_PROP_PASS_THROUGH,
+  CHILD_PROP_BLUR,
   CHILD_PROP_INDEX
 };
 
@@ -539,6 +542,17 @@ gtk_overlay_set_child_property (GtkContainer *container,
            }
        }
       break;
+    case CHILD_PROP_BLUR:
+      if (child_info)
+       {
+         if (g_value_get_double (value) != child_info->blur)
+           {
+             child_info->blur = g_value_get_double (value);
+             gtk_container_child_notify (container, child, "blur");
+              gtk_widget_queue_draw (GTK_WIDGET (overlay));
+           }
+       }
+      break;
     case CHILD_PROP_INDEX:
       if (child_info != NULL)
        gtk_overlay_reorder_overlay (GTK_OVERLAY (container),
@@ -585,6 +599,12 @@ gtk_overlay_get_child_property (GtkContainer *container,
       else
        g_value_set_boolean (value, FALSE);
       break;
+    case CHILD_PROP_BLUR:
+      if (child_info)
+       g_value_set_double (value, child_info->blur);
+      else
+       g_value_set_double (value, 0);
+      break;
     case CHILD_PROP_INDEX:
       g_value_set_int (value, g_slist_index (priv->children, child_info));
       break;
@@ -594,6 +614,77 @@ gtk_overlay_get_child_property (GtkContainer *container,
     }
 }
 
+static void
+gtk_overlay_snapshot (GtkWidget   *widget,
+                      GtkSnapshot *snapshot)
+{
+  GtkWidget *main_widget;
+  GtkWidget *child;
+  GtkAllocation main_alloc;
+  cairo_region_t *clip = NULL;
+  int i;
+
+  main_widget = gtk_bin_get_child (GTK_BIN (widget));
+  gtk_widget_get_allocation (widget, &main_alloc);
+
+  for (child = _gtk_widget_get_first_child (widget);
+       child != NULL;
+       child = _gtk_widget_get_next_sibling (child))
+    {
+      double blur;
+      gtk_container_child_get (GTK_CONTAINER (widget), child, "blur", &blur, NULL);
+      if (blur > 0)
+        {
+          GtkAllocation alloc;
+          graphene_rect_t bounds;
+
+          gtk_widget_get_allocation (child, &alloc);
+          graphene_rect_init (&bounds, alloc.x, alloc.y, alloc.width, alloc.height);
+          gtk_snapshot_push_clip (snapshot, &bounds, "Overlay Effect Clip");
+          gtk_snapshot_push_blur (snapshot, blur, "Overlay Effect");
+          gtk_widget_snapshot_child (widget, main_widget, snapshot);
+          gtk_snapshot_pop (snapshot);
+          gtk_snapshot_pop (snapshot);
+
+          if (clip == NULL)
+            {
+              clip = cairo_region_create ();
+              main_alloc.x = main_alloc.y = 0;
+              cairo_region_union_rectangle (clip, (cairo_rectangle_int_t *)&main_alloc);
+            }
+
+          cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
+        }
+    }
+
+  if (clip == NULL)
+    {
+      GTK_WIDGET_CLASS (gtk_overlay_parent_class)->snapshot (widget, snapshot);
+      return;
+    }
+
+  for (i = 0; i < cairo_region_num_rectangles (clip); i++)
+    {
+      cairo_rectangle_int_t rect;
+      graphene_rect_t bounds;
+
+      cairo_region_get_rectangle (clip, i, &rect);
+      graphene_rect_init (&bounds, rect.x, rect.y, rect.width, rect.height);
+      gtk_snapshot_push_clip (snapshot, &bounds, "Overlay Non-Effect Clip");
+      gtk_widget_snapshot_child (widget, main_widget, snapshot);
+      gtk_snapshot_pop (snapshot);
+    }
+
+  cairo_region_destroy (clip);
+
+  for (child = _gtk_widget_get_first_child (widget);
+       child != NULL;
+       child = _gtk_widget_get_next_sibling (child))
+    {
+      if (child != main_widget)
+        gtk_widget_snapshot_child (widget, child, snapshot);
+    }
+}
 
 static void
 gtk_overlay_class_init (GtkOverlayClass *klass)
@@ -603,6 +694,7 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   widget_class->size_allocate = gtk_overlay_size_allocate;
+  widget_class->snapshot = gtk_overlay_snapshot;
 
   container_class->add = gtk_overlay_add;
   container_class->remove = gtk_overlay_remove;
@@ -625,6 +717,17 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
                             GTK_PARAM_READWRITE));
 
   /**
+   * GtkOverlay:blur:
+   *
+   * Blur the content behind this child with a Gaussian blur of this radius.
+   *
+   * Since: 3.92
+   */
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_BLUR,
+      g_param_spec_double ("blur", P_("Blur Radius"), P_("Apply a blur to the content behind this child"),
+                           0, 100, 0,
+                           GTK_PARAM_READWRITE));
+  /**
    * GtkOverlay:index:
    *
    * The index of the overlay in the parent, -1 for the main child.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]