mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
cairo-texture: Add the :auto-resize property
Keeping the backing Cairo surface of a CairoTexture canvas in sync with the actor's allocation is tedious and prone to mistakes. We can definitely do better by simply exposing a property that does the surface resize and invalidation automagically on ::allocate.
This commit is contained in:
parent
301551aacf
commit
7f8838d7cc
@ -67,7 +67,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <cairo-gobject.h>
|
#include <cairo-gobject.h>
|
||||||
|
|
||||||
@ -88,6 +88,7 @@ enum
|
|||||||
|
|
||||||
PROP_SURFACE_WIDTH,
|
PROP_SURFACE_WIDTH,
|
||||||
PROP_SURFACE_HEIGHT,
|
PROP_SURFACE_HEIGHT,
|
||||||
|
PROP_AUTO_RESIZE,
|
||||||
|
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
@ -125,6 +126,8 @@ struct _ClutterCairoTexturePrivate
|
|||||||
guint surface_height;
|
guint surface_height;
|
||||||
|
|
||||||
cairo_t *cr_context;
|
cairo_t *cr_context;
|
||||||
|
|
||||||
|
guint auto_resize : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -173,6 +176,9 @@ clutter_cairo_texture_set_property (GObject *object,
|
|||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
case PROP_SURFACE_WIDTH:
|
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);
|
priv->surface_width = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -180,6 +186,11 @@ clutter_cairo_texture_set_property (GObject *object,
|
|||||||
priv->surface_height = g_value_get_uint (value);
|
priv->surface_height = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_AUTO_RESIZE:
|
||||||
|
clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (object),
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -206,6 +217,10 @@ clutter_cairo_texture_get_property (GObject *object,
|
|||||||
g_value_set_uint (value, priv->surface_height);
|
g_value_set_uint (value, priv->surface_height);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_AUTO_RESIZE:
|
||||||
|
g_value_set_boolean (value, priv->auto_resize);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -431,6 +446,32 @@ clutter_cairo_texture_get_preferred_height (ClutterActor *actor,
|
|||||||
*natural_height = (gfloat) priv->surface_height;
|
*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
|
static gboolean
|
||||||
clutter_cairo_texture_get_paint_volume (ClutterActor *self,
|
clutter_cairo_texture_get_paint_volume (ClutterActor *self,
|
||||||
ClutterPaintVolume *volume)
|
ClutterPaintVolume *volume)
|
||||||
@ -521,6 +562,8 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass)
|
|||||||
clutter_cairo_texture_get_preferred_width;
|
clutter_cairo_texture_get_preferred_width;
|
||||||
actor_class->get_preferred_height =
|
actor_class->get_preferred_height =
|
||||||
clutter_cairo_texture_get_preferred_height;
|
clutter_cairo_texture_get_preferred_height;
|
||||||
|
actor_class->allocate =
|
||||||
|
clutter_cairo_texture_allocate;
|
||||||
|
|
||||||
klass->create_surface = clutter_cairo_texture_create_surface;
|
klass->create_surface = clutter_cairo_texture_create_surface;
|
||||||
|
|
||||||
@ -557,9 +600,24 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass)
|
|||||||
0,
|
0,
|
||||||
CLUTTER_PARAM_READWRITE);
|
CLUTTER_PARAM_READWRITE);
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class,
|
/**
|
||||||
PROP_LAST,
|
* ClutterCairoTexture:auto-resize:
|
||||||
obj_props);
|
*
|
||||||
|
* 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:
|
* ClutterCairoTexture::create-surface:
|
||||||
@ -1058,3 +1116,57 @@ clutter_cairo_texture_clear (ClutterCairoTexture *self)
|
|||||||
if (priv->cr_context == NULL)
|
if (priv->cr_context == NULL)
|
||||||
cairo_destroy (cr);
|
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;
|
||||||
|
}
|
||||||
|
@ -131,6 +131,9 @@ void clutter_cairo_texture_set_surface_size (ClutterCairoTex
|
|||||||
void clutter_cairo_texture_get_surface_size (ClutterCairoTexture *self,
|
void clutter_cairo_texture_get_surface_size (ClutterCairoTexture *self,
|
||||||
guint *width,
|
guint *width,
|
||||||
guint *height);
|
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);
|
void clutter_cairo_texture_clear (ClutterCairoTexture *self);
|
||||||
|
|
||||||
|
@ -1756,6 +1756,8 @@ ClutterCairoTextureClass
|
|||||||
clutter_cairo_texture_new
|
clutter_cairo_texture_new
|
||||||
clutter_cairo_texture_set_surface_size
|
clutter_cairo_texture_set_surface_size
|
||||||
clutter_cairo_texture_get_surface_size
|
clutter_cairo_texture_get_surface_size
|
||||||
|
clutter_cairo_texture_set_auto_resize
|
||||||
|
clutter_cairo_texture_get_auto_resize
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
clutter_cairo_texture_create
|
clutter_cairo_texture_create
|
||||||
|
@ -78,10 +78,11 @@ test_cairo_clock_main (int argc, char *argv[])
|
|||||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
/* create a fixed size stage */
|
/* create a resizable stage */
|
||||||
stage = clutter_stage_new ();
|
stage = clutter_stage_new ();
|
||||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock");
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock");
|
||||||
clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue);
|
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_set_size (stage, 300, 300);
|
||||||
clutter_actor_show (stage);
|
clutter_actor_show (stage);
|
||||||
|
|
||||||
@ -89,6 +90,12 @@ test_cairo_clock_main (int argc, char *argv[])
|
|||||||
canvas = clutter_cairo_texture_new (300, 300);
|
canvas = clutter_cairo_texture_new (300, 300);
|
||||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas);
|
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 */
|
/* quit on destroy */
|
||||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user