[gtk+/wip/matthiasc/fancy-overlay: 1/2] Add an effect child property to GtkOverlay



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

    Add an effect child property to GtkOverlay
    
    When set, it turns on an 'effect' for the child. Currently,
    it is turning the content underneath grayscale. The eventual
    goal here is to blur it...

 gtk/gtkoverlay.c |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c
index 9c46f34..a05d419 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;
+  gboolean effect;
 };
 
 enum {
@@ -76,6 +78,7 @@ enum
 {
   CHILD_PROP_0,
   CHILD_PROP_PASS_THROUGH,
+  CHILD_PROP_EFFECT,
   CHILD_PROP_INDEX
 };
 
@@ -539,6 +542,17 @@ gtk_overlay_set_child_property (GtkContainer *container,
            }
        }
       break;
+    case CHILD_PROP_EFFECT:
+      if (child_info)
+       {
+         if (g_value_get_boolean (value) != child_info->effect)
+           {
+             child_info->effect = g_value_get_boolean (value);
+             gtk_container_child_notify (container, child, "effect");
+              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_EFFECT:
+      if (child_info)
+       g_value_set_boolean (value, child_info->effect);
+      else
+       g_value_set_boolean (value, FALSE);
+      break;
     case CHILD_PROP_INDEX:
       g_value_set_int (value, g_slist_index (priv->children, child_info));
       break;
@@ -594,6 +614,91 @@ gtk_overlay_get_child_property (GtkContainer *container,
     }
 }
 
+static void
+gtk_overlay_snapshot (GtkWidget   *widget,
+                      GtkSnapshot *snapshot)
+{
+  GtkWidget *main_widget;
+  GtkWidget *child;
+  graphene_rect_t bounds;
+  gboolean effect;
+  double value;
+  graphene_matrix_t matrix;
+  graphene_vec4_t offset;
+  GtkAllocation alloc;
+  GtkAllocation effect_alloc;
+  cairo_region_t *clip;
+  int i;
+
+  for (child = _gtk_widget_get_first_child (widget);
+       child != NULL;
+       child = _gtk_widget_get_next_sibling (child))
+    {
+      gtk_container_child_get (GTK_CONTAINER (widget), child, "effect", &effect, NULL);
+      if (effect)
+        {
+          gtk_widget_get_allocation (child, &effect_alloc);
+          break;
+        }
+    }
+
+  if (!effect)
+    {
+      GTK_WIDGET_CLASS (gtk_overlay_parent_class)->snapshot (widget, snapshot);
+      return;
+    }
+
+  main_widget = gtk_bin_get_child (GTK_BIN (widget));
+
+  /* invert */
+#define R 0.2126
+#define G 0.7152
+#define B 0.0722
+
+  value = 1.0;
+      graphene_matrix_init_from_float (&matrix, (float[16]) {
+                                           1.0 - (1.0 - R) * value, R * value, R * value, 0.0,
+                                           G * value, 1.0 - (1.0 - G) * value, G * value, 0.0,
+                                           B * value, B * value, 1.0 - (1.0 - B) * value, 0.0,
+                                           0.0, 0.0, 0.0, 1.0
+                                       });
+      graphene_vec4_init (&offset, 0.0, 0.0, 0.0, 0.0);
+
+  gtk_widget_get_allocation (widget, &alloc);
+  graphene_rect_init (&bounds, effect_alloc.x, effect_alloc.y, effect_alloc.width, effect_alloc.height);
+  gtk_snapshot_push_clip (snapshot, &bounds, "Overlay Effect Clip");
+  gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset, "Overlay Effect");
+
+  gtk_widget_snapshot_child (widget, main_widget, snapshot);
+
+  gtk_snapshot_pop (snapshot);
+  gtk_snapshot_pop (snapshot);
+
+  clip = cairo_region_create ();
+  alloc.x = alloc.y = 0;
+  cairo_region_union_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
+  cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&effect_alloc);
+
+  for (i = 0; i < cairo_region_num_rectangles (clip); i++)
+    {
+      cairo_rectangle_int_t rect;
+      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 +708,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;
@@ -624,6 +730,10 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
                             FALSE,
                             GTK_PARAM_READWRITE));
 
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_EFFECT,
+      g_param_spec_boolean ("effect", NULL, NULL,
+                            FALSE,
+                            GTK_PARAM_READWRITE));
   /**
    * GtkOverlay:index:
    *


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