2007-11-18 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-actor.c:
        * clutter/clutter-actor.h:
        * clutter/clutter-group.c:
        * clutter/clutter-main.c:
        * clutter/clutter-stage.c:
        * tests/test-events.c:
        Parent Actors no longer need to be set reactive for reactive
        children to get events. Also makes groups now pickable.
        (#597, #423)

        * clutter/clutter-texture.c:
        Handle case when 1x1 tiled texture is created,
        falling 'back' to being non tiled. (#596)

        * clutter/eglx/clutter-backend-egl.c:
        Call EglTerminate on backend shutdown.
This commit is contained in:
Matthew Allum 2007-11-18 23:24:55 +00:00
parent 8580a97b4b
commit 382852f921
9 changed files with 159 additions and 58 deletions

View File

@ -1,3 +1,22 @@
2007-11-18 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c:
* clutter/clutter-actor.h:
* clutter/clutter-group.c:
* clutter/clutter-main.c:
* clutter/clutter-stage.c:
* tests/test-events.c:
Parent Actors no longer need to be set reactive for reactive
children to get events. Also makes groups now pickable.
(#597, #423)
* clutter/clutter-texture.c:
Handle case when 1x1 tiled texture is created,
falling 'back' to being non tiled. (#596)
* clutter/eglx/clutter-backend-egl.c:
Call EglTerminate on backend shutdown.
2007-11-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter.pc.in: Bump up glib-2.0 dependency.

View File

@ -32,12 +32,13 @@
* be a #ClutterActor, either by using one of the classes provided by
* Clutter, or by implementing a new #ClutterActor subclass.
*
* Ordering of tranformations. FIXME.
* Ordering on/Notes on tranformations. FIXME.
*
* Notes on clutter actor events:
* <orderedlist>
* <listitem><para>Actors emit pointer events if set reactive, see
* clutter_actor_set_reactive()</para></listitem>
* <listitem><para>The stage is always reactive</para></listitem>
* <listitem><para>Events are handled by connecting signal handlers to
* the numerous event signal types.</para></listitem>
* <listitem><para>Event handlers must return %TRUE if they handled
@ -56,6 +57,8 @@
* phase transversing back up via parents to the stage. An event
* handler can abort this chain at point by returning
* %TRUE.</para></listitem>
* <listitem><para>Pointer events will 'pass through' non reactive actors.
* </para></listitem>
* </orderedlist>
*/
@ -322,31 +325,11 @@ clutter_actor_unrealize (ClutterActor *self)
(klass->unrealize) (self);
}
/**
* clutter_actor_pick:
* @self: A #ClutterActor
* @color: A #ClutterColor
*
* Renders a silhouette of the actor in supplied color.
*
* This function should not never be called directly by applications.
**/
void
clutter_actor_pick (ClutterActor *self,
static void
clutter_actor_real_pick (ClutterActor *self,
const ClutterColor *color)
{
ClutterActorClass *klass;
klass = CLUTTER_ACTOR_GET_CLASS (self);
if (G_UNLIKELY(klass->pick))
{
/* Its pretty unlikely anything other than a container actor
* would need to supply its own pick method.
*/
(klass->pick) (self, color);
}
else
if (clutter_actor_should_pick_paint (self))
{
cogl_color (color);
cogl_rectangle (0,
@ -356,6 +339,60 @@ clutter_actor_pick (ClutterActor *self,
}
}
/**
* clutter_actor_pick:
* @self: A #ClutterActor
* @color: A #ClutterColor
*
* Renders a silhouette of the actor in supplied color. Used internally for
* mapping pointer events to actors.
*
* This function should not never be called directly by applications.
*
* Subclasses overiding this method should call
* #clutter_actor_should_pick_paint to decide if to render there
* silhouette but in any case should still recursively call pick for
* any children.
*
* Since 0.4
**/
void
clutter_actor_pick (ClutterActor *self,
const ClutterColor *color)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (color != NULL);
CLUTTER_ACTOR_GET_CLASS (self)->pick(self, color);
}
/**
* clutter_actor_should_pick_paint:
* @self: A #ClutterActor
*
* Utility call for subclasses overiding the pick method.
*
* This function should not never be called directly by applications.
*
* Return value: TRUE if the actor should paint its silhouette, FALSE otherwise
*/
gboolean
clutter_actor_should_pick_paint (ClutterActor *self)
{
ClutterMainContext *context;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
context = clutter_context_get_default ();
if (CLUTTER_ACTOR_IS_MAPPED (self)
&& (G_UNLIKELY(context->pick_mode == CLUTTER_PICK_ALL)
|| CLUTTER_ACTOR_IS_REACTIVE (self)))
return TRUE;
return FALSE;
}
/*
* Utility functions for manipulating transformation matrix
*
@ -741,10 +778,6 @@ clutter_actor_paint (ClutterActor *self)
ClutterColor col;
guint32 id;
if (context->pick_mode == CLUTTER_PICK_ALL
|| (context->pick_mode == CLUTTER_PICK_REACTIVE
&& CLUTTER_ACTOR_IS_REACTIVE(self)))
{
id = clutter_actor_get_gid (self);
cogl_get_bitmasks (&r, &g, &b, NULL);
@ -761,7 +794,6 @@ clutter_actor_paint (ClutterActor *self)
*/
clutter_actor_pick (self, &col);
}
}
else
{
if (G_LIKELY(klass->paint))
@ -1557,6 +1589,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
klass->show_all = clutter_actor_show;
klass->hide = clutter_actor_real_hide;
klass->hide_all = clutter_actor_hide;
klass->pick = clutter_actor_real_pick;
}
static void

View File

@ -407,6 +407,8 @@ gboolean clutter_actor_event (ClutterActor *actor,
gboolean capture);
ClutterActor * clutter_get_actor_by_gid (guint32 id);
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
G_END_DECLS
#endif /* _HAVE_CLUTTER_ACTOR_H */

View File

@ -112,11 +112,13 @@ static void
clutter_group_pick (ClutterActor *actor,
const ClutterColor *color)
{
/* Chain up so we get a bounding box pained (if we are reactive) */
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, color);
/* Just forward to the paint call which in turn will trigger
* the child actors also getting 'picked'. To make ourselves
* 'sensitive' to clicks we could also paint a bounding rect
* but this is not currently done.
* the child actors also getting 'picked'.
*/
if (CLUTTER_ACTOR_IS_MAPPED (actor))
clutter_group_paint (actor);
}

View File

@ -226,7 +226,8 @@ _clutter_do_pick (ClutterStage *stage,
* could be nicer.
*/
glFinish();
glEnable (GL_DITHER);
/* glEnable (GL_DITHER); we never enabled this originally, so its
probably not safe to then enable it */
glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);

View File

@ -101,6 +101,18 @@ clutter_stage_paint (ClutterActor *self)
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
}
static void
clutter_stage_pick (ClutterActor *self,
const ClutterColor *color)
{
/* Paint nothing, cogl_paint_init() effectively paints the stage
* silhouette for us - see _clutter_do_pick().
* Chain up to the groups paint howerer so our children get picked
* - clutter_group_pick
*/
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
}
static void
clutter_stage_set_property (GObject *object,
guint prop_id,
@ -218,6 +230,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
gobject_class->get_property = clutter_stage_get_property;
actor_class->paint = clutter_stage_paint;
actor_class->pick = clutter_stage_pick;
/**
* ClutterStage:fullscreen:

View File

@ -274,14 +274,22 @@ texture_init_tiles (ClutterTexture *texture)
priv->n_x_tiles = tile_dimension (priv->width, x_pot,
priv->max_tile_waste, NULL);
if (priv->y_tiles)
g_free (priv->y_tiles);
priv->n_y_tiles = tile_dimension (priv->height, y_pot,
priv->max_tile_waste, NULL);
if (priv->n_x_tiles == 1 && priv->n_y_tiles == 1)
{
/* So were not actually tiled... */
priv->n_x_tiles = priv->n_y_tiles = 0;
priv->is_tiled = FALSE;
return;
}
priv->x_tiles = g_new (ClutterTextureTileDimension, priv->n_x_tiles);
tile_dimension (priv->width, x_pot, priv->max_tile_waste, priv->x_tiles);
if (priv->y_tiles)
g_free (priv->y_tiles);
priv->n_y_tiles = tile_dimension (priv->height, y_pot,
priv->max_tile_waste, NULL);
priv->y_tiles = g_new (ClutterTextureTileDimension, priv->n_y_tiles);
tile_dimension (priv->height, y_pot, priv->max_tile_waste, priv->y_tiles);
@ -291,7 +299,6 @@ texture_init_tiles (ClutterTexture *texture)
x_pot, priv->width, y_pot, priv->height,
priv->max_tile_waste,
priv->n_x_tiles, priv->n_y_tiles);
}
static void

View File

@ -86,6 +86,14 @@ clutter_backend_egl_finalize (GObject *gobject)
static void
clutter_backend_egl_dispose (GObject *gobject)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
if (backend_egl->edpy)
{
eglTerminate (backend_egl->edpy);
backend_egl->edpy = NULL;
}
G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
}

View File

@ -119,7 +119,8 @@ input_cb (ClutterActor *actor,
printf("[%s] BUTTON RELEASE", source);
if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage))
clutter_stage_set_key_focus (stage, NULL);
else if (clutter_event_get_source (event) == actor)
else if (clutter_event_get_source (event) == actor
&& clutter_actor_get_parent (actor) == stage)
clutter_stage_set_key_focus (stage, actor);
break;
case CLUTTER_SCROLL:
@ -152,10 +153,11 @@ input_cb (ClutterActor *actor,
int
main (int argc, char *argv[])
{
ClutterActor *stage, *actor, *focus_box;
ClutterActor *stage, *actor, *focus_box, *group;
ClutterColor rcol = { 0xff, 0, 0, 0xff},
bcol = { 0, 0, 0xff, 0xff },
gcol = { 0, 0xff, 0, 0xff },
ycol = { 0xff, 0xff, 0, 0xff },
ncol = { 0, 0, 0, 0xff };
clutter_init (&argc, &argv);
@ -224,6 +226,7 @@ main (int argc, char *argv[])
/* Fullscreen */
g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL);
/* non reactive */
actor = clutter_rectangle_new_with_color (&ncol);
clutter_actor_set_size (actor, 400, 50);
clutter_actor_set_position (actor, 100, 250);
@ -237,6 +240,19 @@ main (int argc, char *argv[])
g_signal_connect (stage, "focus-in", G_CALLBACK (key_focus_in_cb),
focus_box);
/* non reactive group, with reactive child */
actor = clutter_rectangle_new_with_color (&ycol);
clutter_actor_set_size (actor, 100, 100);
clutter_actor_set_reactive (actor, TRUE);
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "yellow box");
/* note group not reactive */
group = clutter_group_new ();
clutter_container_add (CLUTTER_CONTAINER(group), actor, NULL);
clutter_container_add (CLUTTER_CONTAINER(stage), group, NULL);
clutter_actor_set_position (group, 100, 350);
clutter_actor_show_all (group);
clutter_actor_show_all (CLUTTER_ACTOR (stage));