Add a blur child property to GtkOverlay
When set, it blurs the content behind the child.
This commit is contained in:
103
gtk/gtkoverlay.c
103
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;
|
||||
@@ -624,6 +716,17 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
|
||||
FALSE,
|
||||
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:
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user