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> 2007-11-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter.pc.in: Bump up glib-2.0 dependency. * 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 * be a #ClutterActor, either by using one of the classes provided by
* Clutter, or by implementing a new #ClutterActor subclass. * Clutter, or by implementing a new #ClutterActor subclass.
* *
* Ordering of tranformations. FIXME. * Ordering on/Notes on tranformations. FIXME.
* *
* Notes on clutter actor events: * Notes on clutter actor events:
* <orderedlist> * <orderedlist>
* <listitem><para>Actors emit pointer events if set reactive, see * <listitem><para>Actors emit pointer events if set reactive, see
* clutter_actor_set_reactive()</para></listitem> * 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 * <listitem><para>Events are handled by connecting signal handlers to
* the numerous event signal types.</para></listitem> * the numerous event signal types.</para></listitem>
* <listitem><para>Event handlers must return %TRUE if they handled * <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 * phase transversing back up via parents to the stage. An event
* handler can abort this chain at point by returning * handler can abort this chain at point by returning
* %TRUE.</para></listitem> * %TRUE.</para></listitem>
* <listitem><para>Pointer events will 'pass through' non reactive actors.
* </para></listitem>
* </orderedlist> * </orderedlist>
*/ */
@ -322,31 +325,11 @@ clutter_actor_unrealize (ClutterActor *self)
(klass->unrealize) (self); (klass->unrealize) (self);
} }
/** static void
* clutter_actor_pick: clutter_actor_real_pick (ClutterActor *self,
* @self: A #ClutterActor const ClutterColor *color)
* @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,
const ClutterColor *color)
{ {
ClutterActorClass *klass; if (clutter_actor_should_pick_paint (self))
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
{ {
cogl_color (color); cogl_color (color);
cogl_rectangle (0, 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 * Utility functions for manipulating transformation matrix
* *
@ -741,26 +778,21 @@ clutter_actor_paint (ClutterActor *self)
ClutterColor col; ClutterColor col;
guint32 id; guint32 id;
if (context->pick_mode == CLUTTER_PICK_ALL id = clutter_actor_get_gid (self);
|| (context->pick_mode == CLUTTER_PICK_REACTIVE
&& CLUTTER_ACTOR_IS_REACTIVE(self)))
{
id = clutter_actor_get_gid (self);
cogl_get_bitmasks (&r, &g, &b, NULL); cogl_get_bitmasks (&r, &g, &b, NULL);
/* Encode the actor id into a color, taking into account bpp */ /* Encode the actor id into a color, taking into account bpp */
col.red = ((id >> (g+b)) & (0xff>>(8-r)))<<(8-r); col.red = ((id >> (g+b)) & (0xff>>(8-r)))<<(8-r);
col.green = ((id >> b) & (0xff>>(8-g))) << (8-g); col.green = ((id >> b) & (0xff>>(8-g))) << (8-g);
col.blue = (id & (0xff>>(8-b)))<<(8-b); col.blue = (id & (0xff>>(8-b)))<<(8-b);
col.alpha = 0xff; col.alpha = 0xff;
/* Actor will then paint silhouette of itself in supplied /* Actor will then paint silhouette of itself in supplied
* color. See clutter_stage_get_actor_at_pos() for where * color. See clutter_stage_get_actor_at_pos() for where
* picking is enabled. * picking is enabled.
*/ */
clutter_actor_pick (self, &col); clutter_actor_pick (self, &col);
}
} }
else else
{ {
@ -1557,6 +1589,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
klass->show_all = clutter_actor_show; klass->show_all = clutter_actor_show;
klass->hide = clutter_actor_real_hide; klass->hide = clutter_actor_real_hide;
klass->hide_all = clutter_actor_hide; klass->hide_all = clutter_actor_hide;
klass->pick = clutter_actor_real_pick;
} }
static void static void

View File

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

View File

@ -112,12 +112,14 @@ static void
clutter_group_pick (ClutterActor *actor, clutter_group_pick (ClutterActor *actor,
const ClutterColor *color) 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 /* Just forward to the paint call which in turn will trigger
* the child actors also getting 'picked'. To make ourselves * the child actors also getting 'picked'.
* 'sensitive' to clicks we could also paint a bounding rect */
* but this is not currently done. if (CLUTTER_ACTOR_IS_MAPPED (actor))
*/ clutter_group_paint (actor);
clutter_group_paint (actor);
} }

View File

@ -226,7 +226,8 @@ _clutter_do_pick (ClutterStage *stage,
* could be nicer. * could be nicer.
*/ */
glFinish(); 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); 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); 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 static void
clutter_stage_set_property (GObject *object, clutter_stage_set_property (GObject *object,
guint prop_id, guint prop_id,
@ -218,6 +230,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
gobject_class->get_property = clutter_stage_get_property; gobject_class->get_property = clutter_stage_get_property;
actor_class->paint = clutter_stage_paint; actor_class->paint = clutter_stage_paint;
actor_class->pick = clutter_stage_pick;
/** /**
* ClutterStage:fullscreen: * ClutterStage:fullscreen:

View File

@ -274,14 +274,22 @@ texture_init_tiles (ClutterTexture *texture)
priv->n_x_tiles = tile_dimension (priv->width, x_pot, priv->n_x_tiles = tile_dimension (priv->width, x_pot,
priv->max_tile_waste, NULL); 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); priv->x_tiles = g_new (ClutterTextureTileDimension, priv->n_x_tiles);
tile_dimension (priv->width, x_pot, priv->max_tile_waste, priv->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); priv->y_tiles = g_new (ClutterTextureTileDimension, priv->n_y_tiles);
tile_dimension (priv->height, y_pot, priv->max_tile_waste, priv->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, x_pot, priv->width, y_pot, priv->height,
priv->max_tile_waste, priv->max_tile_waste,
priv->n_x_tiles, priv->n_y_tiles); priv->n_x_tiles, priv->n_y_tiles);
} }
static void static void

View File

@ -86,6 +86,14 @@ clutter_backend_egl_finalize (GObject *gobject)
static void static void
clutter_backend_egl_dispose (GObject *gobject) 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); 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); printf("[%s] BUTTON RELEASE", source);
if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage)) if (clutter_event_get_source (event) == CLUTTER_ACTOR (stage))
clutter_stage_set_key_focus (stage, NULL); 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); clutter_stage_set_key_focus (stage, actor);
break; break;
case CLUTTER_SCROLL: case CLUTTER_SCROLL:
@ -152,10 +153,11 @@ input_cb (ClutterActor *actor,
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
ClutterActor *stage, *actor, *focus_box; ClutterActor *stage, *actor, *focus_box, *group;
ClutterColor rcol = { 0xff, 0, 0, 0xff}, ClutterColor rcol = { 0xff, 0, 0, 0xff},
bcol = { 0, 0, 0xff, 0xff }, bcol = { 0, 0, 0xff, 0xff },
gcol = { 0, 0xff, 0, 0xff }, gcol = { 0, 0xff, 0, 0xff },
ycol = { 0xff, 0xff, 0, 0xff },
ncol = { 0, 0, 0, 0xff }; ncol = { 0, 0, 0, 0xff };
clutter_init (&argc, &argv); clutter_init (&argc, &argv);
@ -224,6 +226,7 @@ main (int argc, char *argv[])
/* Fullscreen */ /* Fullscreen */
g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL); g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL);
/* non reactive */
actor = clutter_rectangle_new_with_color (&ncol); actor = clutter_rectangle_new_with_color (&ncol);
clutter_actor_set_size (actor, 400, 50); clutter_actor_set_size (actor, 400, 50);
clutter_actor_set_position (actor, 100, 250); 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), g_signal_connect (stage, "focus-in", G_CALLBACK (key_focus_in_cb),
focus_box); 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)); clutter_actor_show_all (CLUTTER_ACTOR (stage));