963
1016
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
1018
ClutterActorPrivate *priv = self->priv;
965
1020
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_VISIBLE);
966
1022
/* we notify on the "visible" flag in the clutter_actor_show()
967
1023
* wrapper so the entire show signal emission completes first
970
1026
clutter_actor_update_map_state (self, MAP_STATE_CHECK);
972
clutter_actor_queue_relayout (self);
1028
/* we queue a relayout unless the actor is inside a
1029
* container that explicitly told us not to
1031
if (priv->parent_actor &&
1032
(!(priv->parent_actor->flags & CLUTTER_ACTOR_NO_LAYOUT)))
1034
/* While an actor is hidden the parent may not have
1035
* allocated/requested so we need to start from scratch
1036
* and avoid the short-circuiting in
1037
* clutter_actor_queue_relayout().
1039
priv->needs_width_request = FALSE;
1040
priv->needs_height_request = FALSE;
1041
priv->needs_allocation = FALSE;
1042
clutter_actor_queue_relayout (self);
1630
/* Transforms a vertex using the passed matrix; vertex is
1631
* an in-out parameter
1634
mtx_transform (const CoglMatrix *matrix,
1635
full_vertex_t *vertex)
1637
cogl_matrix_transform_point (matrix,
1644
/* Help macros to scale from OpenGL <-1,1> coordinates system to our
1645
* X-window based <0,window-size> coordinates
1647
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0) / 2) * (v1)) + (v2))
1648
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0) / 2) * (v1)) + (v2))
1649
#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2)))
1651
1759
/* transforms a 4-tuple of coordinates using @matrix and
1652
* places the result into a fixed @vertex
1760
* places the result into a @vertex
1654
1762
static inline void
1655
1763
full_vertex_transform (const CoglMatrix *matrix,
1660
1768
full_vertex_t *vertex)
1662
full_vertex_t tmp = { 0, };
1669
mtx_transform (matrix, &tmp);
1770
cogl_matrix_transform_point (matrix, &x, &y, &z, &w);
1778
/* Help macros to scale from OpenGL <-1,1> coordinates system to our
1779
* X-window based <0,window-size> coordinates
1781
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0) / 2) * (v1)) + (v2))
1782
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0) / 2) * (v1)) + (v2))
1783
#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2)))
1674
1785
/* scales a fixed @vertex using @matrix and @viewport, and
1675
1786
* transforms the result into a ClutterVertex, filling @vertex_p
1921
2051
cogl_pop_matrix();
1924
/* Recursively tranform supplied box with the tranform for the current
2054
/* _clutter_actor_ensure_stage_current
2056
* Ensures that the actors corresponding stage is made current so we
2057
* have a valid viewport, projection matrix and modelview matrix stack.
2060
_clutter_actor_ensure_stage_current (ClutterActor *self)
2062
ClutterActor *stage;
2064
/* We essentially have to dupe some code from clutter_redraw() here
2065
* to make sure GL Matrices etc are initialised if we're called and we
2066
* haven't yet rendered anything.
2068
* Simply duping code for now in wait for Cogl cleanup that can hopefully
2069
* address this in a nicer way.
2071
stage = clutter_actor_get_stage (self);
2073
/* FIXME: if were not yet added to a stage, its probably unsafe to
2074
* return default - ideally the func should fail
2077
stage = clutter_stage_get_default ();
2079
clutter_stage_ensure_current (CLUTTER_STAGE (stage));
2080
_clutter_stage_maybe_setup_viewport (CLUTTER_STAGE (stage));
2083
/* _clutter_actor_get_relative_modelview:
2085
* Retrives the modelview transformation relative to some ancestor actor, or
2086
* the stage if NULL is given for the ancestor.
2088
* It assumes you currently have an empty matrix stack.
2090
/* FIXME: We should be caching the stage relative modelview along with the
2092
/* TODO: Replace all other occurrences of this code pattern in clutter-actor.c:
2093
* cogl_push_matrix();
2094
* _clutter_actor_apply_modelview_transform_recursive (self, ancestor)
2095
* cogl_get_modelview_matrix()
2096
* cogl_pop_matrix();
2097
* with a call to this function:
2100
_clutter_actor_get_relative_modelview (ClutterActor *self,
2101
ClutterActor *ancestor,
2104
_clutter_actor_ensure_stage_current (self);
2106
/* FIXME: init_identity instead of assuming we have an empty stack! */
2108
cogl_push_matrix ();
2110
_clutter_actor_apply_modelview_transform_recursive (self, ancestor);
2112
cogl_get_modelview_matrix (matrix);
2117
/* _clutter_actor_get_projection_and_viewport
2119
* Retrieves the projection matrix and viewport for the actors corresponding
2123
_clutter_actor_get_projection_and_viewport (ClutterActor *self,
2127
_clutter_actor_ensure_stage_current (self);
2129
cogl_get_projection_matrix (matrix);
2130
cogl_get_viewport (viewport);
2133
/* Recursively transform supplied box with the transform for the current
1925
2134
* actor and all its ancestors (like clutter_actor_transform_point()
1926
2135
* but for all the vertices in one go) and project it into screen
1930
clutter_actor_transform_and_project_box (ClutterActor *self,
1931
const ClutterActorBox *box,
1932
ClutterVertex verts[])
2139
_clutter_actor_transform_and_project_box (ClutterActor *self,
2140
const ClutterActorBox *box,
2141
ClutterVertex verts[])
1934
ClutterActor *stage;
1935
2143
CoglMatrix mtx;
1936
2144
CoglMatrix mtx_p;
1938
gfloat width, height;
1939
2146
full_vertex_t vertices[4];
1941
width = box->x2 - box->x1;
1942
height = box->y2 - box->y1;
1944
/* We essentially have to dupe some code from clutter_redraw() here
1945
* to make sure GL Matrices etc are initialised if we're called and we
1946
* havn't yet rendered anything.
1948
* Simply duping code for now in wait for Cogl cleanup that can hopefully
1949
* address this in a nicer way.
1951
stage = clutter_actor_get_stage (self);
1953
/* FIXME: if were not yet added to a stage, its probably unsafe to
1954
* return default - ideally the func should fail
1957
stage = clutter_stage_get_default ();
1959
clutter_stage_ensure_current (CLUTTER_STAGE (stage));
1960
_clutter_stage_maybe_setup_viewport (CLUTTER_STAGE (stage));
1964
_clutter_actor_apply_modelview_transform_recursive (self, NULL);
1966
cogl_get_modelview_matrix (&mtx);
1968
full_vertex_transform (&mtx, 0, 0, 0, 1.0, &vertices[0]);
1969
full_vertex_transform (&mtx, width, 0, 0, 1.0, &vertices[1]);
1970
full_vertex_transform (&mtx, 0, height, 0, 1.0, &vertices[2]);
1971
full_vertex_transform (&mtx, width, height, 0, 1.0, &vertices[3]);
1975
cogl_get_projection_matrix (&mtx_p);
1976
cogl_get_viewport (v);
2148
_clutter_actor_get_relative_modelview (self, NULL, &mtx);
2150
full_vertex_transform (&mtx, box->x1, box->y1, 0, 1.0, &vertices[0]);
2151
full_vertex_transform (&mtx, box->x2, box->y1, 0, 1.0, &vertices[1]);
2152
full_vertex_transform (&mtx, box->x1, box->y2, 0, 1.0, &vertices[2]);
2153
full_vertex_transform (&mtx, box->x2, box->y2, 0, 1.0, &vertices[3]);
2155
_clutter_actor_get_projection_and_viewport (self, &mtx_p, v);
1978
2157
full_vertex_scale (&mtx_p, &vertices[0], v, &verts[0]);
1979
2158
full_vertex_scale (&mtx_p, &vertices[1], v, &verts[1]);
4359
4631
clutter_actor_queue_redraw_with_origin (self, self);
4635
_clutter_actor_get_allocation_clip (ClutterActor *self,
4636
ClutterActorBox *clip)
4638
ClutterActorBox allocation;
4640
/* XXX: we don't care if we get an out of date allocation here
4641
* because clutter_actor_queue_redraw_with_origin knows to ignore
4642
* the clip if the actor's allocation is invalid.
4644
* This is noted because clutter_actor_get_allocation_box does some
4645
* unnecessary work to support buggy code with a comment suggesting
4646
* that it could be changed later which would be good for this use
4649
clutter_actor_get_allocation_box (self, &allocation);
4651
/* NB: clutter_actor_queue_clipped_redraw expects a box in the
4652
* actor's own coordinate space but the allocation is in parent
4656
clip->x2 = allocation.x2 - allocation.x1;
4657
clip->y2 = allocation.y2 - allocation.y1;
4661
* clutter_actor_queue_redraw_with_clip:
4662
* @self: A #ClutterActor
4663
* @flags: A mask of #ClutterRedrawFlags controlling the behaviour of
4664
* this queue redraw.
4665
* @clip: A #ClutterActorBox describing the bounds of what needs to be
4666
* redrawn or %NULL if you are just using a @flag to state your
4669
* Queues up a clipped redraw of an actor and any children. The redraw
4670
* occurs once the main loop becomes idle (after the current batch of
4671
* events has been processed, roughly).
4673
* If the %CLUTTER_REDRAW_CLIPPED_TO_BOX @flag is used, the clip box is
4674
* specified in actor coordinates and tells Clutter that only content
4675
* within this box has been changed so Clutter can optionally optimize
4678
* If you are queuing a clipped redraw it is assumed that the actor is
4679
* flat, and once the clip rectangle is projected into stage
4680
* coordinates it will cover the area of the stage that needs to be
4681
* redrawn. This is not possible to determine for 3D actors since the
4682
* projection of such actors may escape the clip rectangle.
4684
* If the %CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION @flag is used, @clip
4685
* should be NULL and this tells Clutter to use the actors current
4686
* allocation as a clip box. As above this flag can only be used for
4689
* Applications rarely need to call this, as redraws are handled
4690
* automatically by modification functions.
4692
* This function will not do anything if @self is not visible, or if
4693
* the actor is inside an invisible part of the scenegraph.
4695
* Also be aware that painting is a NOP for actors with an opacity of
4699
_clutter_actor_queue_redraw_with_clip (ClutterActor *self,
4700
ClutterRedrawFlags flags,
4701
ClutterActorBox *clip)
4703
ClutterActorBox allocation_clip;
4705
/* If the actor doesn't have a valid allocation then we will queue a
4706
* full stage redraw */
4707
if (self->priv->needs_allocation)
4709
clutter_actor_queue_redraw (self);
4713
/* SYNC_MATRICES is a flag for the stage, which means that we just
4714
* got resized and we need to re-setup the viewport.
4715
* IN_RESIZE is used on X11 where the resize is asynchronous, so we
4716
* don't ask for a viewport change before we have the final size.
4718
* If either of these flags are set then we won't be able to
4719
* transform the given clip rectangle into valid stage coordinates,
4720
* so we instead queue a full stage redraw.
4722
* (Note: to some extent this is redundant because these flags
4723
* should imply a full stage redraw will be queued, but we at least
4724
* avoid needlessly traversing the actors ancestors to derive an
4725
* incorrect modelview matrix.)
4727
if ((CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_SYNC_MATRICES) &&
4728
!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_STAGE_IN_RESIZE))
4730
clutter_actor_queue_redraw (self);
4734
if (flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION)
4736
_clutter_actor_get_allocation_clip (self, &allocation_clip);
4737
clip = &allocation_clip;
4740
/* XXX: Ideally the redraw signal would take a clip rectangle
4741
* argument, but that would be an ABI break. Until we can break the
4742
* ABI we pass the argument out-of-band via an actor->priv member...
4745
_clutter_actor_set_queue_redraw_clip (self, clip);
4747
clutter_actor_queue_redraw_with_origin (self, self);
4749
/* Just in case anyone is manually firing redraw signals without
4750
* using the public queue_redraw() API we are careful to ensure that
4751
* our out-of-band clip member is cleared before returning...
4753
* Note: A NULL clip denotes a full-stage, un-clipped redraw
4755
_clutter_actor_set_queue_redraw_clip (self, NULL);
4363
4759
* clutter_actor_queue_relayout:
4364
4760
* @self: A #ClutterActor
5661
* clutter_actor_get_request_mode:
5662
* @self: a #ClutterActor
5664
* Retrieves the geometry request mode of @self
5666
* Return value: the request mode for the actor
5671
clutter_actor_get_request_mode (ClutterActor *self)
5673
g_return_val_if_fail (CLUTTER_IS_ACTOR (self),
5674
CLUTTER_REQUEST_HEIGHT_FOR_WIDTH);
5676
return self->priv->request_mode;
5679
/* variant of set_width() without checks and without notification
5680
* freeze+thaw, for internal usage only
5683
clutter_actor_set_width_internal (ClutterActor *self,
5688
/* the Stage will use the :min-width to control the minimum
5689
* width to be resized to, so we should not be setting it
5690
* along with the :natural-width
5692
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
5693
clutter_actor_set_min_width (self, width);
5695
clutter_actor_set_natural_width (self, width);
5699
/* we only unset the :natural-width for the Stage */
5700
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
5701
clutter_actor_set_min_width_set (self, FALSE);
5703
clutter_actor_set_natural_width_set (self, FALSE);
5707
/* variant of set_height() without checks and without notification
5708
* freeze+thaw, for internal usage only
5711
clutter_actor_set_height_internal (ClutterActor *self,
5716
/* see the comment above in set_width_internal() */
5717
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
5718
clutter_actor_set_min_height (self, height);
5720
clutter_actor_set_natural_height (self, height);
5724
/* see the comment above in set_width_internal() */
5725
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL))
5726
clutter_actor_set_min_height_set (self, FALSE);
5728
clutter_actor_set_natural_height_set (self, FALSE);
5171
5733
* clutter_actor_set_size
5172
5734
* @self: A #ClutterActor
5173
5735
* @width: New width of actor in pixels, or -1
6684
7281
g_return_if_fail (CLUTTER_IS_ACTOR (self));
6686
7283
parent = clutter_actor_get_parent (self);
7284
if (parent == NULL || !CLUTTER_IS_CONTAINER (parent))
6689
g_warning ("Actor of type %s is not inside a container",
6690
g_type_name (G_OBJECT_TYPE (self)));
7286
g_warning ("%s: Actor '%s' is not inside a container",
7288
self->priv->name != NULL ? self->priv->name
7289
: G_OBJECT_TYPE_NAME (self));
6696
7295
if (parent != clutter_actor_get_parent (below))
6698
g_warning ("Actor of type %s is not in the same "
6699
"container of actor of type %s",
6700
g_type_name (G_OBJECT_TYPE (self)),
6701
g_type_name (G_OBJECT_TYPE (below)));
7297
g_warning ("%s Actor '%s' is not in the same container as "
7300
self->priv->name != NULL ? self->priv->name
7301
: G_OBJECT_TYPE_NAME (self),
7302
below->priv->name != NULL ? below->priv->name
7303
: G_OBJECT_TYPE_NAME (below));
8742
* clutter_actor_box_interpolate:
8743
* @initial: the initial #ClutterActorBox
8744
* @final: the final #ClutterActorBox
8745
* @progress: the interpolation progress
8746
* @result: (out): return location for the interpolation
8748
* Interpolates between @initial and @final #ClutterActorBox<!-- -->es
8754
clutter_actor_box_interpolate (const ClutterActorBox *initial,
8755
const ClutterActorBox *final,
8757
ClutterActorBox *result)
8759
g_return_if_fail (initial != NULL);
8760
g_return_if_fail (final != NULL);
8761
g_return_if_fail (result != NULL);
8763
result->x1 = initial->x1 + (final->x1 - initial->x1) * progress;
8764
result->y1 = initial->y1 + (final->y1 - initial->y1) * progress;
8765
result->x2 = initial->x2 + (final->x2 - initial->x2) * progress;
8766
result->y2 = initial->y2 + (final->y2 - initial->y2) * progress;
8770
* clutter_actor_box_clamp_to_pixel:
8771
* @box: (inout): the #ClutterActorBox to clamp
8773
* Clamps the components of @box to the nearest integer
8778
clutter_actor_box_clamp_to_pixel (ClutterActorBox *box)
8780
g_return_if_fail (box != NULL);
8782
box->x1 = floorf (box->x1 + 0.5);
8783
box->y1 = floorf (box->y1 + 0.5);
8784
box->x2 = floorf (box->x2 + 0.5);
8785
box->y2 = floorf (box->y2 + 0.5);
8133
8788
/******************************************************************************/
8135
8790
struct _ShaderData
9187
9845
* - enable_model_view_transform == FALSE
9190
return self->priv->opacity_parent != NULL &&
9191
!self->priv->enable_model_view_transform;
9850
return priv->opacity_parent != NULL &&
9851
!priv->enable_model_view_transform;
9855
set_direction_recursive (ClutterActor *actor,
9858
ClutterTextDirection text_dir = GPOINTER_TO_INT (user_data);
9860
clutter_actor_set_text_direction (actor, text_dir);
9864
* clutter_actor_set_text_direction:
9865
* @self: a #ClutterActor
9866
* @text_dir: the text direction for @self
9868
* Sets the #ClutterTextDirection for an actor
9870
* The passed text direction must not be %CLUTTER_TEXT_DIRECTION_DEFAULT
9872
* If @self implements #ClutterContainer then this function will recurse
9873
* inside all the children of @self (including the internal ones).
9875
* Composite actors not implementing #ClutterContainer, or actors requiring
9876
* special handling when the text direction changes, should connect to
9877
* the #GObject::notify signal for the #ClutterActor:text-direction property
9882
clutter_actor_set_text_direction (ClutterActor *self,
9883
ClutterTextDirection text_dir)
9885
ClutterActorPrivate *priv;
9887
g_return_if_fail (CLUTTER_IS_ACTOR (self));
9888
g_return_if_fail (text_dir != CLUTTER_TEXT_DIRECTION_DEFAULT);
9892
if (priv->text_direction != text_dir)
9894
priv->text_direction = text_dir;
9896
/* we need to emit the notify::text-direction first, so that
9897
* the sub-classes can catch that and do specific handling of
9898
* the text direction; see clutter_text_direction_changed_cb()
9899
* inside clutter-text.c
9901
g_object_notify (G_OBJECT (self), "text-direction");
9903
/* if this is a container we need to recurse */
9904
if (CLUTTER_IS_CONTAINER (self))
9906
ClutterContainer *container = CLUTTER_CONTAINER (self);
9908
clutter_container_foreach_with_internals (container,
9909
set_direction_recursive,
9910
GINT_TO_POINTER (text_dir));
9913
clutter_actor_queue_relayout (self);
9918
_clutter_actor_set_has_pointer (ClutterActor *self,
9919
gboolean has_pointer)
9921
ClutterActorPrivate *priv = self->priv;
9923
if (priv->has_pointer != has_pointer)
9925
priv->has_pointer = has_pointer;
9927
g_object_notify (G_OBJECT (self), "has-pointer");
9932
* clutter_actor_get_text_direction:
9933
* @self: a #ClutterActor
9935
* Retrieves the value set using clutter_actor_set_text_direction()
9937
* If no text direction has been previously set, the default text
9938
* direction, as returned by clutter_get_default_text_direction(), will
9939
* be returned instead
9941
* Return value: the #ClutterTextDirection for the actor
9945
ClutterTextDirection
9946
clutter_actor_get_text_direction (ClutterActor *self)
9948
ClutterActorPrivate *priv;
9950
g_return_val_if_fail (CLUTTER_IS_ACTOR (self),
9951
CLUTTER_TEXT_DIRECTION_LTR);
9955
/* if no direction has been set yet use the default */
9956
if (priv->text_direction == CLUTTER_TEXT_DIRECTION_DEFAULT)
9957
priv->text_direction = clutter_get_default_text_direction ();
9959
return priv->text_direction;
9963
* clutter_actor_push_internal:
9964
* @self: a #ClutterActor
9966
* Should be used by actors implementing the #ClutterContainer and with
9967
* internal children added through clutter_actor_set_parent(), for instance:
9971
* my_actor_init (MyActor *self)
9973
* self->priv = SELF_ACTOR_GET_PRIVATE (self);
9975
* clutter_actor_push_internal (CLUTTER_ACTOR (self));
9977
* /* calling clutter_actor_set_parent() now will result in
9978
* * the internal flag being set on a child of MyActor
9981
* /* internal child: a background texture */
9982
* self->priv->background_tex = clutter_texture_new ();
9983
* clutter_actor_set_parent (self->priv->background_tex,
9984
* CLUTTER_ACTOR (self));
9986
* /* internal child: a label */
9987
* self->priv->label = clutter_text_new ();
9988
* clutter_actor_set_parent (self->priv->label,
9989
* CLUTTER_ACTOR (self));
9991
* clutter_actor_pop_internal (CLUTTER_ACTOR (self));
9993
* /* calling clutter_actor_set_parent() now will not result in
9994
* * the internal flag being set on a child of MyActor
9999
* This function will be used by Clutter to toggle an "internal child"
10000
* flag whenever clutter_actor_set_parent() is called; internal children
10001
* are handled differently by Clutter, specifically when destroying their
10004
* Call clutter_actor_pop_internal() when you finished adding internal
10007
* Nested calls to clutter_actor_push_internal() are allowed, but each
10008
* one must by followed by a clutter_actor_pop_internal() call.
10013
clutter_actor_push_internal (ClutterActor *self)
10015
g_return_if_fail (CLUTTER_IS_ACTOR (self));
10017
self->priv->internal_child += 1;
10021
* clutter_actor_pop_internal:
10022
* @self: a #ClutterActor
10024
* Disables the effects of clutter_actor_pop_internal()
10029
clutter_actor_pop_internal (ClutterActor *self)
10031
ClutterActorPrivate *priv;
10033
g_return_if_fail (CLUTTER_IS_ACTOR (self));
10037
if (priv->internal_child == 0)
10039
g_warning ("Mismatched %s: you need to call "
10040
"clutter_actor_push_composite() at least once before "
10041
"calling this function", G_STRFUNC);
10045
priv->internal_child -= 1;
10049
* clutter_actor_has_pointer:
10050
* @self: a #ClutterActor
10052
* Checks whether an actor contains the the pointer of a
10053
* #ClutterInputDevice
10055
* Return value: %TRUE if the actor contains the pointer, and
10061
clutter_actor_has_pointer (ClutterActor *self)
10063
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
10065
return self->priv->has_pointer;
10068
/* XXX: This is a workaround for not being able to break the ABI of
10069
* the QUEUE_REDRAW signal. It is an out-of-band argument. See
10070
* clutter_actor_queue_clipped_redraw() for details.
10072
const ClutterActorBox *
10073
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
10075
return self->priv->oob_queue_redraw_clip;
10079
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
10080
const ClutterActorBox *clip)
10082
self->priv->oob_queue_redraw_clip = clip;