diff --git a/clutter/clutter-cairo-texture.c b/clutter/clutter-cairo-texture.c index f5ec31030..a6a5b88d9 100644 --- a/clutter/clutter-cairo-texture.c +++ b/clutter/clutter-cairo-texture.c @@ -67,7 +67,7 @@ #include "config.h" #endif -#include +#include #include @@ -88,6 +88,7 @@ enum PROP_SURFACE_WIDTH, PROP_SURFACE_HEIGHT, + PROP_AUTO_RESIZE, PROP_LAST }; @@ -125,6 +126,8 @@ struct _ClutterCairoTexturePrivate guint surface_height; cairo_t *cr_context; + + guint auto_resize : 1; }; typedef struct { @@ -173,6 +176,9 @@ clutter_cairo_texture_set_property (GObject *object, switch (prop_id) { case PROP_SURFACE_WIDTH: + /* we perform the resize on notify to coalesce separate + * surface-width/surface-height property set + */ priv->surface_width = g_value_get_uint (value); break; @@ -180,6 +186,11 @@ clutter_cairo_texture_set_property (GObject *object, priv->surface_height = g_value_get_uint (value); break; + case PROP_AUTO_RESIZE: + clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (object), + g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -206,6 +217,10 @@ clutter_cairo_texture_get_property (GObject *object, g_value_set_uint (value, priv->surface_height); break; + case PROP_AUTO_RESIZE: + g_value_set_boolean (value, priv->auto_resize); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -431,6 +446,32 @@ clutter_cairo_texture_get_preferred_height (ClutterActor *actor, *natural_height = (gfloat) priv->surface_height; } +static void +clutter_cairo_texture_allocate (ClutterActor *self, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (self)->priv; + ClutterActorClass *parent_class; + + parent_class = CLUTTER_ACTOR_CLASS (clutter_cairo_texture_parent_class); + parent_class->allocate (self, allocation, flags); + + if (priv->auto_resize) + { + ClutterCairoTexture *texture = CLUTTER_CAIRO_TEXTURE (self); + gfloat width, height; + + clutter_actor_box_get_size (allocation, &width, &height); + + priv->surface_width = ceilf (width + 0.5); + priv->surface_height = ceilf (height + 0.5); + + clutter_cairo_texture_surface_resize_internal (texture); + clutter_cairo_texture_invalidate (texture); + } +} + static gboolean clutter_cairo_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume) @@ -521,6 +562,8 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass) clutter_cairo_texture_get_preferred_width; actor_class->get_preferred_height = clutter_cairo_texture_get_preferred_height; + actor_class->allocate = + clutter_cairo_texture_allocate; klass->create_surface = clutter_cairo_texture_create_surface; @@ -557,9 +600,24 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass) 0, CLUTTER_PARAM_READWRITE); - g_object_class_install_properties (gobject_class, - PROP_LAST, - obj_props); + /** + * ClutterCairoTexture:auto-resize: + * + * Controls whether the #ClutterCairoTexture should automatically + * resize the Cairo surface whenever the actor's allocation changes. + * If :auto-resize is set to %TRUE the surface contents will also + * be invalidated automatically. + * + * Since: 1.8 + */ + obj_props[PROP_AUTO_RESIZE] = + g_param_spec_boolean ("auto-resize", + P_("Auto Resize"), + P_("Whether the surface should match the allocation"), + FALSE, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); /** * ClutterCairoTexture::create-surface: @@ -1058,3 +1116,57 @@ clutter_cairo_texture_clear (ClutterCairoTexture *self) if (priv->cr_context == NULL) cairo_destroy (cr); } + +/** + * clutter_cairo_texture_set_auto_resize: + * @self: a #ClutterCairoTexture + * @value: %TRUE if the #ClutterCairoTexture should bind the surface + * size to the allocation + * + * Sets whether the #ClutterCairoTexture should ensure that the + * backing Cairo surface used matches the allocation assigned to + * the actor. If the allocation changes, the contents of the + * #ClutterCairoTexture will also be invalidated automatically. + * + * Since: 1.8 + */ +void +clutter_cairo_texture_set_auto_resize (ClutterCairoTexture *self, + gboolean value) +{ + ClutterCairoTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + value = !!value; + + priv = self->priv; + + if (priv->auto_resize == value) + return; + + priv->auto_resize = value; + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_AUTO_RESIZE]); +} + +/** + * clutter_cairo_texture_get_auto_resize: + * @self: a #ClutterCairoTexture + * + * Retrieves the value set using clutter_cairo_texture_set_auto_resize(). + * + * Return value: %TRUE if the #ClutterCairoTexture should track the + * allocation, and %FALSE otherwise + * + * Since: 1.8 + */ +gboolean +clutter_cairo_texture_get_auto_resize (ClutterCairoTexture *self) +{ + g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), FALSE); + + return self->priv->auto_resize; +} diff --git a/clutter/clutter-cairo-texture.h b/clutter/clutter-cairo-texture.h index 4126a62cb..4b65f8cc9 100644 --- a/clutter/clutter-cairo-texture.h +++ b/clutter/clutter-cairo-texture.h @@ -131,6 +131,9 @@ void clutter_cairo_texture_set_surface_size (ClutterCairoTex void clutter_cairo_texture_get_surface_size (ClutterCairoTexture *self, guint *width, guint *height); +void clutter_cairo_texture_set_auto_resize (ClutterCairoTexture *self, + gboolean value); +gboolean clutter_cairo_texture_get_auto_resize (ClutterCairoTexture *self); void clutter_cairo_texture_clear (ClutterCairoTexture *self); diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 6d35cd196..21e4da270 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1756,6 +1756,8 @@ ClutterCairoTextureClass clutter_cairo_texture_new clutter_cairo_texture_set_surface_size clutter_cairo_texture_get_surface_size +clutter_cairo_texture_set_auto_resize +clutter_cairo_texture_get_auto_resize clutter_cairo_texture_create diff --git a/tests/interactive/test-cairo-clock.c b/tests/interactive/test-cairo-clock.c index b88772381..f847e7abd 100644 --- a/tests/interactive/test-cairo-clock.c +++ b/tests/interactive/test-cairo-clock.c @@ -78,10 +78,11 @@ test_cairo_clock_main (int argc, char *argv[]) if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return EXIT_FAILURE; - /* create a fixed size stage */ + /* create a resizable stage */ stage = clutter_stage_new (); clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock"); clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); clutter_actor_set_size (stage, 300, 300); clutter_actor_show (stage); @@ -89,6 +90,12 @@ test_cairo_clock_main (int argc, char *argv[]) canvas = clutter_cairo_texture_new (300, 300); clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas); + /* bind the size of the canvas to that of the stage */ + clutter_actor_add_constraint (canvas, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0)); + + /* make sure to match allocation to canvas size */ + clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (canvas), TRUE); + /* quit on destroy */ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);