Compare commits
3 Commits
clutter-1.
...
wip/hit-te
Author | SHA1 | Date |
---|---|---|
Emmanuele Bassi | 8c7dc4ea38 | |
Emmanuele Bassi | 55c4d7ab67 | |
Emmanuele Bassi | c5e1a34408 |
|
@ -2082,7 +2082,8 @@ clutter_actor_should_pick_paint (ClutterActor *self)
|
|||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||
|
||||
if (CLUTTER_ACTOR_IS_MAPPED (self) &&
|
||||
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self) &&
|
||||
CLUTTER_ACTOR_IS_MAPPED (self) &&
|
||||
(_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL ||
|
||||
CLUTTER_ACTOR_IS_REACTIVE (self)))
|
||||
return TRUE;
|
||||
|
@ -5465,6 +5466,30 @@ clutter_actor_real_destroy (ClutterActor *actor)
|
|||
g_object_thaw_notify (G_OBJECT (actor));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_actor_real_contains_point (ClutterActor *self,
|
||||
const ClutterPoint *point)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterRect bounds;
|
||||
|
||||
CLUTTER_NOTE (HIT_TEST, "Point { x:%.2f, y:%.2f } -> '%s' { %.2f, %.2f, %.2f, %.2f }",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
point->x, point->y,
|
||||
priv->allocation.x1,
|
||||
priv->allocation.y1,
|
||||
priv->allocation.x2,
|
||||
priv->allocation.y2);
|
||||
|
||||
clutter_rect_init (&bounds,
|
||||
0.f,
|
||||
0.f,
|
||||
priv->allocation.x2 - priv->allocation.x1,
|
||||
priv->allocation.y2 - priv->allocation.y1);
|
||||
|
||||
return clutter_rect_contains_point (&bounds, point);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
clutter_actor_constructor (GType gtype,
|
||||
guint n_props,
|
||||
|
@ -5526,6 +5551,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||
klass->has_overlaps = clutter_actor_real_has_overlaps;
|
||||
klass->paint = clutter_actor_real_paint;
|
||||
klass->destroy = clutter_actor_real_destroy;
|
||||
klass->contains_point = clutter_actor_real_contains_point;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterActorPrivate));
|
||||
|
||||
|
@ -18535,3 +18561,145 @@ clutter_actor_needs_expand (ClutterActor *self,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_contains_point:
|
||||
* @self: a #ClutterActor
|
||||
* @point: a #ClutterPoint, in actor-relative coordinates
|
||||
*
|
||||
* Calls #ClutterActorClass.contains_point() to check if @self contains
|
||||
* the given @point.
|
||||
*
|
||||
* Return value: %TRUE if the #ClutterActor contains the point
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_contains_point (ClutterActor *self,
|
||||
const ClutterPoint *point)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||
g_return_val_if_fail (point != NULL, FALSE);
|
||||
|
||||
return CLUTTER_ACTOR_GET_CLASS (self)->contains_point (self, point);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
actor_is_transformed (ClutterActor *actor)
|
||||
{
|
||||
const ClutterTransformInfo *info;
|
||||
|
||||
info = _clutter_actor_get_transform_info_or_defaults (actor);
|
||||
|
||||
if (info->depth != 0.f)
|
||||
return TRUE;
|
||||
|
||||
if (info->rx_angle || info->ry_angle || info->rz_angle)
|
||||
return TRUE;
|
||||
|
||||
if (info->scale_x != 1.f || info->scale_y != 1.f)
|
||||
return TRUE;
|
||||
|
||||
if (!clutter_anchor_coord_is_zero (&info->anchor))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_hit_test:
|
||||
* @self: a #ClutterActor
|
||||
* @point: a #ClutterPoint, in actor-relative coordinates
|
||||
*
|
||||
* Finds the innermost #ClutterActor that contains the given @point.
|
||||
*
|
||||
* This function will recurse through the actor tree starting from @self
|
||||
* and will implicitly call #ClutterActorClass.contains_point() to check
|
||||
* if an actor contains the given point.
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterActor, or %NULL
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_actor_hit_test (ClutterActor *self,
|
||||
const ClutterPoint *point)
|
||||
{
|
||||
ClutterActor *retval, *child;
|
||||
ClutterActorIter iter;
|
||||
const CoglMatrix *projection;
|
||||
float viewport[4];
|
||||
ClutterStage *stage;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
|
||||
g_return_val_if_fail (point != NULL, NULL);
|
||||
|
||||
if (!clutter_actor_contains_point (self, point))
|
||||
{
|
||||
CLUTTER_NOTE (HIT_TEST,
|
||||
"The actor '%s' does not contain { x:%.2f, y:%.2f }",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
point->x, point->y);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stage = (ClutterStage *) _clutter_actor_get_stage_internal (self);
|
||||
if (stage == NULL)
|
||||
return NULL;
|
||||
|
||||
/* XXX - need peek() versions of this */
|
||||
projection = _clutter_stage_peek_projection_matrix (stage);
|
||||
|
||||
/* the viewport is defined to be the allocation of the actor */
|
||||
viewport[0] = 0.f;
|
||||
viewport[1] = 0.f;
|
||||
viewport[2] = self->priv->allocation.x2 - self->priv->allocation.x1;
|
||||
viewport[3] = self->priv->allocation.y2 - self->priv->allocation.y1;
|
||||
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
ClutterPoint child_point;
|
||||
|
||||
if (!actor_is_transformed (child))
|
||||
{
|
||||
/* fast path: just offset the coordinates */
|
||||
child_point.x = point->x - child->priv->allocation.x1;
|
||||
child_point.y = point->y - child->priv->allocation.y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterVertex out_vertex = CLUTTER_VERTEX_INIT (0.f, 0.f, 0.f);
|
||||
ClutterVertex in_vertex = CLUTTER_VERTEX_INIT (point->x, point->y, 0.f);
|
||||
|
||||
/* not so fast path: unproject the point */
|
||||
if (!_clutter_util_unproject (&in_vertex,
|
||||
&child->priv->transform,
|
||||
projection,
|
||||
viewport,
|
||||
&out_vertex))
|
||||
{
|
||||
CLUTTER_NOTE (HIT_TEST, "Skipping '%s': unproject failed",
|
||||
_clutter_actor_get_debug_name (child));
|
||||
continue;
|
||||
}
|
||||
|
||||
child_point.x = out_vertex.x - child->priv->allocation.x1;
|
||||
child_point.y = out_vertex.y - child->priv->allocation.y1;
|
||||
}
|
||||
|
||||
retval = clutter_actor_hit_test (child, &child_point);
|
||||
if (retval != NULL)
|
||||
{
|
||||
CLUTTER_NOTE (HIT_TEST,
|
||||
"Hit test success: '%s'",
|
||||
_clutter_actor_get_debug_name (retval));
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (HIT_TEST,
|
||||
"Hit test success: '%s'",
|
||||
_clutter_actor_get_debug_name (self));
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -262,10 +262,12 @@ struct _ClutterActorClass
|
|||
|
||||
void (* paint_node) (ClutterActor *self,
|
||||
ClutterPaintNode *root);
|
||||
gboolean (* contains_point) (ClutterActor *self,
|
||||
const ClutterPoint *point);
|
||||
|
||||
/*< private >*/
|
||||
/* padding for future expansion */
|
||||
gpointer _padding_dummy[27];
|
||||
gpointer _padding_dummy[26];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -527,6 +529,10 @@ gboolean clutter_actor_event
|
|||
ClutterEvent *event,
|
||||
gboolean capture);
|
||||
gboolean clutter_actor_has_pointer (ClutterActor *self);
|
||||
gboolean clutter_actor_contains_point (ClutterActor *self,
|
||||
const ClutterPoint *point);
|
||||
ClutterActor * clutter_actor_hit_test (ClutterActor *self,
|
||||
const ClutterPoint *point);
|
||||
|
||||
/* Text */
|
||||
PangoContext * clutter_actor_get_pango_context (ClutterActor *self);
|
||||
|
|
|
@ -895,8 +895,8 @@ clutter_rect_get_center (ClutterRect *rect,
|
|||
* Since: 1.12
|
||||
*/
|
||||
gboolean
|
||||
clutter_rect_contains_point (ClutterRect *rect,
|
||||
ClutterPoint *point)
|
||||
clutter_rect_contains_point (ClutterRect *rect,
|
||||
const ClutterPoint *point)
|
||||
{
|
||||
g_return_val_if_fail (rect != NULL, FALSE);
|
||||
g_return_val_if_fail (point != NULL, FALSE);
|
||||
|
|
|
@ -23,7 +23,8 @@ typedef enum {
|
|||
CLUTTER_DEBUG_PICK = 1 << 13,
|
||||
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
|
||||
CLUTTER_DEBUG_CLIPPING = 1 << 15,
|
||||
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16
|
||||
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16,
|
||||
CLUTTER_DEBUG_HIT_TEST = 1 << 17
|
||||
} ClutterDebugFlag;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -192,6 +192,7 @@ static const GDebugKey clutter_debug_keys[] = {
|
|||
{ "layout", CLUTTER_DEBUG_LAYOUT },
|
||||
{ "clipping", CLUTTER_DEBUG_CLIPPING },
|
||||
{ "oob-transforms", CLUTTER_DEBUG_OOB_TRANSFORMS },
|
||||
{ "hit-test", CLUTTER_DEBUG_HIT_TEST },
|
||||
};
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
|
|
|
@ -253,6 +253,12 @@ void _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
|
|||
const cairo_rectangle_int_t *src2,
|
||||
cairo_rectangle_int_t *dest);
|
||||
|
||||
gboolean _clutter_util_unproject (const ClutterVertex *in_vertex,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport,
|
||||
ClutterVertex *out_vertex);
|
||||
|
||||
typedef struct _ClutterPlane
|
||||
{
|
||||
float v0[3];
|
||||
|
|
|
@ -44,6 +44,7 @@ void _clutter_stage_set_window (ClutterStage
|
|||
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
||||
void _clutter_stage_get_projection_matrix (ClutterStage *stage,
|
||||
CoglMatrix *projection);
|
||||
const CoglMatrix * _clutter_stage_peek_projection_matrix (ClutterStage *stage);
|
||||
void _clutter_stage_dirty_projection (ClutterStage *stage);
|
||||
void _clutter_stage_set_viewport (ClutterStage *stage,
|
||||
float x,
|
||||
|
|
|
@ -714,22 +714,6 @@ clutter_stage_paint (ClutterActor *self)
|
|||
clutter_actor_paint (child);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_pick (ClutterActor *self,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
|
||||
/* Note: we don't chain up to our parent as we don't want any geometry
|
||||
* emitted for the stage itself. The stage's pick id is effectively handled
|
||||
* by the call to cogl_clear done in clutter-main.c:_clutter_do_pick_async()
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_get_paint_volume (ClutterActor *self,
|
||||
ClutterPaintVolume *volume)
|
||||
|
@ -1864,7 +1848,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|||
actor_class->get_preferred_width = clutter_stage_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_stage_get_preferred_height;
|
||||
actor_class->paint = clutter_stage_paint;
|
||||
actor_class->pick = clutter_stage_pick;
|
||||
actor_class->get_paint_volume = clutter_stage_get_paint_volume;
|
||||
actor_class->realize = clutter_stage_realize;
|
||||
actor_class->unrealize = clutter_stage_unrealize;
|
||||
|
@ -2488,6 +2471,12 @@ _clutter_stage_get_projection_matrix (ClutterStage *stage,
|
|||
*projection = stage->priv->projection;
|
||||
}
|
||||
|
||||
const CoglMatrix *
|
||||
_clutter_stage_peek_projection_matrix (ClutterStage *stage)
|
||||
{
|
||||
return &stage->priv->projection;
|
||||
}
|
||||
|
||||
/* This simply provides a simple mechanism for us to ensure that
|
||||
* the projection matrix gets re-asserted before painting.
|
||||
*
|
||||
|
|
|
@ -297,56 +297,56 @@ GType clutter_rect_get_type (void) G_GNUC_CONST;
|
|||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterRect * clutter_rect_alloc (void);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterRect * clutter_rect_init (ClutterRect *rect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height);
|
||||
ClutterRect * clutter_rect_init (ClutterRect *rect,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterRect * clutter_rect_copy (const ClutterRect *rect);
|
||||
ClutterRect * clutter_rect_copy (const ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_free (ClutterRect *rect);
|
||||
void clutter_rect_free (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
gboolean clutter_rect_equals (ClutterRect *a,
|
||||
ClutterRect *b);
|
||||
gboolean clutter_rect_equals (ClutterRect *a,
|
||||
ClutterRect *b);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterRect * clutter_rect_normalize (ClutterRect *rect);
|
||||
ClutterRect * clutter_rect_normalize (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_get_center (ClutterRect *rect,
|
||||
ClutterPoint *center);
|
||||
void clutter_rect_get_center (ClutterRect *rect,
|
||||
ClutterPoint *center);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
gboolean clutter_rect_contains_point (ClutterRect *rect,
|
||||
ClutterPoint *point);
|
||||
gboolean clutter_rect_contains_point (ClutterRect *rect,
|
||||
const ClutterPoint *point);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
gboolean clutter_rect_contains_rect (ClutterRect *a,
|
||||
ClutterRect *b);
|
||||
gboolean clutter_rect_contains_rect (ClutterRect *a,
|
||||
ClutterRect *b);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_union (ClutterRect *a,
|
||||
ClutterRect *b,
|
||||
ClutterRect *res);
|
||||
void clutter_rect_union (ClutterRect *a,
|
||||
ClutterRect *b,
|
||||
ClutterRect *res);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
gboolean clutter_rect_intersection (ClutterRect *a,
|
||||
ClutterRect *b,
|
||||
ClutterRect *res);
|
||||
gboolean clutter_rect_intersection (ClutterRect *a,
|
||||
ClutterRect *b,
|
||||
ClutterRect *res);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_offset (ClutterRect *rect,
|
||||
float d_x,
|
||||
float d_y);
|
||||
void clutter_rect_offset (ClutterRect *rect,
|
||||
float d_x,
|
||||
float d_y);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_inset (ClutterRect *rect,
|
||||
float d_x,
|
||||
float d_y);
|
||||
void clutter_rect_inset (ClutterRect *rect,
|
||||
float d_x,
|
||||
float d_y);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_rect_clamp_to_pixel (ClutterRect *rect);
|
||||
void clutter_rect_clamp_to_pixel (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_rect_get_x (ClutterRect *rect);
|
||||
float clutter_rect_get_x (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_rect_get_y (ClutterRect *rect);
|
||||
float clutter_rect_get_y (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_rect_get_width (ClutterRect *rect);
|
||||
float clutter_rect_get_width (ClutterRect *rect);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_rect_get_height (ClutterRect *rect);
|
||||
float clutter_rect_get_height (ClutterRect *rect);
|
||||
|
||||
/**
|
||||
* ClutterVertex:
|
||||
|
|
|
@ -182,6 +182,71 @@ _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
|
|||
dest->y = dest_y;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* _clutter_util_unproject:
|
||||
* @in_vertex: a #ClutterVertex with the point to unproject
|
||||
* @modelview: the modelview matrix used to unproject
|
||||
* @projection: the projection matrix used to unproject
|
||||
* @viewport: the viewport, as an array of floats with the origin in the
|
||||
* first two elements and the width and height in the last two
|
||||
* @out_vertex: (out caller-allocates): return location for the unprojected
|
||||
* vertex
|
||||
*
|
||||
* Unprojects @in_vertex according to the provided modelview and projection
|
||||
* matrices, and relative to the viewport.
|
||||
*
|
||||
* Return value: %TRUE if the vertex was successfully unprojected
|
||||
*/
|
||||
gboolean
|
||||
_clutter_util_unproject (const ClutterVertex *in_vertex,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport,
|
||||
ClutterVertex *out_vertex)
|
||||
{
|
||||
float in_v[4], out_v[4];
|
||||
const float *matrix;
|
||||
CoglMatrix final;
|
||||
int i;
|
||||
|
||||
cogl_matrix_multiply (&final, modelview, projection);
|
||||
if (!cogl_matrix_get_inverse (&final, &final))
|
||||
return FALSE;
|
||||
|
||||
in_v[0] = in_vertex->x;
|
||||
in_v[1] = in_vertex->y;
|
||||
in_v[2] = in_vertex->z;
|
||||
in_v[3] = 1.0f;
|
||||
|
||||
/* normalize in GL <-1, 1> space */
|
||||
in_v[0] = (in_v[0] - viewport[0]) / viewport[2];
|
||||
in_v[1] = (in_v[1] - viewport[1]) / viewport[3];
|
||||
|
||||
in_v[0] = in_v[0] * 2 - 1;
|
||||
in_v[1] = in_v[1] * 2 - 1;
|
||||
in_v[2] = in_v[2] * 2 - 1;
|
||||
|
||||
/* multiply the matrix with the vector */
|
||||
matrix = cogl_matrix_get_array (&final);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
out_v[i] = in_v[0] * matrix[0 * 4 + i]
|
||||
+ in_v[1] * matrix[1 * 4 + i]
|
||||
+ in_v[2] * matrix[2 * 4 + i]
|
||||
+ in_v[3] * matrix[3 * 4 + i];
|
||||
}
|
||||
|
||||
if (out_v[3] == 0.f)
|
||||
return FALSE;
|
||||
|
||||
/* denormalize using the viewport */
|
||||
out_vertex->x = MTX_GL_SCALE_X (out_v[0], out_v[3], viewport[2], viewport[0]);
|
||||
out_vertex->y = MTX_GL_SCALE_Y (out_v[1], out_v[3], viewport[3], viewport[1]);
|
||||
out_vertex->z = MTX_GL_SCALE_Z (out_v[2], out_v[3], viewport[2], viewport[0]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GType value_type;
|
||||
|
|
|
@ -83,6 +83,28 @@ animate_rotation (ClutterActor *actor,
|
|||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_capture (ClutterActor *stage,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterActor *hit;
|
||||
ClutterPoint point = { 0, };
|
||||
|
||||
if (clutter_event_type (event) != CLUTTER_MOTION)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
clutter_event_get_position (event, &point);
|
||||
|
||||
hit = clutter_actor_hit_test (stage, &point);
|
||||
if (hit != NULL)
|
||||
g_print ("HIT TEST: %s (at x:%.2f, y:%.2f)\n",
|
||||
clutter_actor_get_name (hit),
|
||||
point.x,
|
||||
point.y);
|
||||
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
|
@ -93,9 +115,11 @@ main (int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "captured-event", G_CALLBACK (on_capture), NULL);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Three Flowers in a Vase");
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_set_name (stage, "Stage");
|
||||
|
||||
/* there are three flowers in a vase */
|
||||
vase = clutter_actor_new ();
|
||||
|
|
Loading…
Reference in New Issue