mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
Merge branch 'internal-flag' into ebassi-next
* internal-flag: conform: Add test unit for the destruction of Containers actor: Add internal child flag Clean up whitespace, indentation and comments
This commit is contained in:
commit
b6bd8be6cb
1
.gitignore
vendored
1
.gitignore
vendored
@ -236,6 +236,7 @@ TAGS
|
||||
/tests/conform/test-script-object-property
|
||||
/tests/conform/test-script-animation
|
||||
/tests/conform/test-script-named-object
|
||||
/tests/conform/test-actor-destruction
|
||||
/tests/micro-bench/test-text-perf
|
||||
/tests/micro-bench/test-text
|
||||
/tests/micro-bench/test-picking
|
||||
|
@ -3039,8 +3039,14 @@ clutter_actor_dispose (GObject *object)
|
||||
{
|
||||
ClutterActor *parent = priv->parent_actor;
|
||||
|
||||
if (CLUTTER_IS_CONTAINER (parent))
|
||||
/* go through the Container implementation unless this
|
||||
* is an internal child and has been marked as such
|
||||
*/
|
||||
if (CLUTTER_IS_CONTAINER (parent) &&
|
||||
!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_INTERNAL_CHILD))
|
||||
{
|
||||
clutter_container_remove_actor (CLUTTER_CONTAINER (parent), self);
|
||||
}
|
||||
else
|
||||
priv->parent_actor = NULL;
|
||||
}
|
||||
@ -6736,6 +6742,7 @@ clutter_actor_set_parent (ClutterActor *self,
|
||||
{
|
||||
ClutterActorPrivate *priv;
|
||||
ClutterTextDirection text_dir;
|
||||
ClutterMainContext *ctx;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (parent));
|
||||
@ -6765,6 +6772,14 @@ clutter_actor_set_parent (ClutterActor *self,
|
||||
g_object_ref_sink (self);
|
||||
priv->parent_actor = parent;
|
||||
|
||||
ctx = _clutter_context_get_default ();
|
||||
|
||||
/* if push_internal() has been called then we automatically set
|
||||
* the flag on the actor
|
||||
*/
|
||||
if (ctx->internal_child)
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_INTERNAL_CHILD);
|
||||
|
||||
/* clutter_actor_reparent() will emit ::parent-set for us */
|
||||
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT))
|
||||
g_signal_emit (self, actor_signals[PARENT_SET], 0, NULL);
|
||||
@ -6942,17 +6957,22 @@ clutter_actor_reparent (ClutterActor *self,
|
||||
|
||||
g_object_ref (self);
|
||||
|
||||
if (CLUTTER_IS_CONTAINER (priv->parent_actor))
|
||||
/* go through the Container implementation if this is a regular
|
||||
* child and not an internal one
|
||||
*/
|
||||
if (CLUTTER_IS_CONTAINER (priv->parent_actor) &&
|
||||
!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_INTERNAL_CHILD))
|
||||
{
|
||||
ClutterContainer *parent = CLUTTER_CONTAINER (priv->parent_actor);
|
||||
/* Note, will call unparent() */
|
||||
|
||||
/* this will have to call unparent() */
|
||||
clutter_container_remove_actor (parent, self);
|
||||
}
|
||||
else
|
||||
clutter_actor_unparent (self);
|
||||
|
||||
if (CLUTTER_IS_CONTAINER (new_parent))
|
||||
/* Note, will call parent() */
|
||||
if (CLUTTER_IS_CONTAINER (new_parent))
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self);
|
||||
else
|
||||
clutter_actor_set_parent (self, new_parent);
|
||||
@ -9588,3 +9608,83 @@ clutter_actor_get_text_direction (ClutterActor *self)
|
||||
|
||||
return priv->text_direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_push_internal:
|
||||
*
|
||||
* Should be used by actors implementing the #ClutterContainer and with
|
||||
* internal children added through clutter_actor_set_parent(), for instance:
|
||||
*
|
||||
* |[
|
||||
* static void
|
||||
* my_actor_init (MyActor *self)
|
||||
* {
|
||||
* self->priv = SELF_ACTOR_GET_PRIVATE (self);
|
||||
*
|
||||
* clutter_actor_push_internal ();
|
||||
*
|
||||
* /* calling clutter_actor_set_parent() now will result in
|
||||
* * the internal flag being set on a child of MyActor
|
||||
* */
|
||||
*
|
||||
* /* internal child: a background texture */
|
||||
* self->priv->background_tex = clutter_texture_new ();
|
||||
* clutter_actor_set_parent (self->priv->background_tex,
|
||||
* CLUTTER_ACTOR (self));
|
||||
*
|
||||
* /* internal child: a label */
|
||||
* self->priv->label = clutter_text_new ();
|
||||
* clutter_actor_set_parent (self->priv->label,
|
||||
* CLUTTER_ACTOR (self));
|
||||
*
|
||||
* clutter_actor_pop_internal ();
|
||||
*
|
||||
* /* calling clutter_actor_set_parent() now will not result in
|
||||
* * the internal flag being set on a child of MyActor
|
||||
* */
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* This function will be used by Clutter to toggle an "internal child"
|
||||
* flag whenever clutter_actor_set_parent() is called; internal children
|
||||
* are handled differently by Clutter, specifically when destroying their
|
||||
* parent.
|
||||
*
|
||||
* Call clutter_actor_pop_internal() when you finished adding internal
|
||||
* children.
|
||||
*
|
||||
* Nested calls to clutter_actor_push_internal() are allowed, but each
|
||||
* one must by followed by a clutter_actor_pop_internal() call.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_actor_push_internal (void)
|
||||
{
|
||||
ClutterMainContext *ctx = _clutter_context_get_default ();
|
||||
|
||||
ctx->internal_child += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_pop_internal:
|
||||
*
|
||||
* Disables the effects of clutter_actor_pop_internal()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_actor_pop_internal (void)
|
||||
{
|
||||
ClutterMainContext *ctx = _clutter_context_get_default ();
|
||||
|
||||
if (ctx->internal_child == 0)
|
||||
{
|
||||
g_warning ("Mismatched %s: you need to call "
|
||||
"clutter_actor_push_composite() at least once before "
|
||||
"calling this function", G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->internal_child -= 1;
|
||||
}
|
||||
|
@ -537,6 +537,9 @@ void clutter_actor_set_text_direction (ClutterActor *sel
|
||||
ClutterTextDirection text_dir);
|
||||
ClutterTextDirection clutter_actor_get_text_direction (ClutterActor *self);
|
||||
|
||||
void clutter_actor_push_internal (void);
|
||||
void clutter_actor_pop_internal (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_H__ */
|
||||
|
@ -354,19 +354,6 @@ clutter_get_motion_events_enabled (void)
|
||||
|
||||
guint _clutter_pix_to_id (guchar pixel[4]);
|
||||
|
||||
static inline void init_bits (void)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
|
||||
static gboolean done = FALSE;
|
||||
if (G_LIKELY (done))
|
||||
return;
|
||||
|
||||
ctx = _clutter_context_get_default ();
|
||||
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_id_to_color (guint id, ClutterColor *col)
|
||||
{
|
||||
@ -378,8 +365,10 @@ _clutter_id_to_color (guint id, ClutterColor *col)
|
||||
/* compute the numbers we'll store in the components */
|
||||
red = (id >> (ctx->fb_g_mask_used+ctx->fb_b_mask_used))
|
||||
& (0xff >> (8-ctx->fb_r_mask_used));
|
||||
green = (id >> ctx->fb_b_mask_used) & (0xff >> (8-ctx->fb_g_mask_used));
|
||||
blue = (id) & (0xff >> (8-ctx->fb_b_mask_used));
|
||||
green = (id >> ctx->fb_b_mask_used)
|
||||
& (0xff >> (8-ctx->fb_g_mask_used));
|
||||
blue = (id)
|
||||
& (0xff >> (8-ctx->fb_b_mask_used));
|
||||
|
||||
/* shift left bits a bit and add one, this circumvents
|
||||
* at least some potential rounding errors in GL/GLES
|
||||
@ -456,7 +445,8 @@ _clutter_pixel_to_id (guchar pixel[4])
|
||||
blue = blue >> (ctx->fb_b_mask - ctx->fb_b_mask_used);
|
||||
|
||||
/* combine the correct per component values into the final id */
|
||||
id = blue + (green << ctx->fb_b_mask_used)
|
||||
id = blue
|
||||
+ (green << ctx->fb_b_mask_used)
|
||||
+ (red << (ctx->fb_b_mask_used + ctx->fb_g_mask_used));
|
||||
|
||||
return id;
|
||||
@ -498,28 +488,34 @@ read_pixels_to_file (char *filename_stem,
|
||||
NULL); /* callback data */
|
||||
if (pixbuf)
|
||||
{
|
||||
char *filename =
|
||||
g_strdup_printf ("%s-%05d.png", filename_stem, read_count);
|
||||
char *filename = g_strdup_printf ("%s-%05d.png",
|
||||
filename_stem,
|
||||
read_count);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL))
|
||||
{
|
||||
g_warning ("Failed to save pick buffer to file %s: %s",
|
||||
filename, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
g_object_unref (pixbuf);
|
||||
read_count++;
|
||||
}
|
||||
#else
|
||||
#else /* !USE_GDKPIXBUF */
|
||||
{
|
||||
static gboolean seen = FALSE;
|
||||
|
||||
if (!seen)
|
||||
{
|
||||
g_warning ("dumping buffers to an image isn't supported on platforms "
|
||||
"without gdk pixbuf support\n");
|
||||
seen = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* USE_GDKPIXBUF */
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
@ -780,14 +776,14 @@ clutter_main (void)
|
||||
static void
|
||||
clutter_threads_impl_lock (void)
|
||||
{
|
||||
if (clutter_threads_mutex)
|
||||
if (G_LIKELY (clutter_threads_mutex != NULL))
|
||||
g_mutex_lock (clutter_threads_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_threads_impl_unlock (void)
|
||||
{
|
||||
if (clutter_threads_mutex)
|
||||
if (G_LIKELY (clutter_threads_mutex != NULL))
|
||||
g_mutex_unlock (clutter_threads_mutex);
|
||||
}
|
||||
|
||||
@ -802,6 +798,8 @@ clutter_threads_impl_unlock (void)
|
||||
*
|
||||
* This function must be called before clutter_init().
|
||||
*
|
||||
* It is safe to call this function multiple times.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
void
|
||||
@ -810,6 +808,9 @@ clutter_threads_init (void)
|
||||
if (!g_thread_supported ())
|
||||
g_error ("g_thread_init() must be called before clutter_threads_init()");
|
||||
|
||||
if (clutter_threads_mutex != NULL)
|
||||
return;
|
||||
|
||||
clutter_threads_mutex = g_mutex_new ();
|
||||
|
||||
if (!clutter_threads_lock)
|
||||
@ -1253,6 +1254,7 @@ _clutter_context_get_default (void)
|
||||
|
||||
ClutterCntx = ctx = g_new0 (ClutterMainContext, 1);
|
||||
|
||||
/* create the default backend */
|
||||
ctx->backend = g_object_new (_clutter_backend_impl_get_type (), NULL);
|
||||
|
||||
ctx->is_initialized = FALSE;
|
||||
@ -1414,7 +1416,7 @@ clutter_init_real (GError **error)
|
||||
resolution = clutter_backend_get_resolution (ctx->backend);
|
||||
cogl_pango_font_map_set_resolution (ctx->font_map, resolution);
|
||||
|
||||
if (G_LIKELY (!clutter_disable_mipmap_text))
|
||||
if (!clutter_disable_mipmap_text)
|
||||
cogl_pango_font_map_set_use_mipmapping (ctx->font_map, TRUE);
|
||||
|
||||
clutter_text_direction = clutter_get_text_direction ();
|
||||
|
@ -58,13 +58,26 @@ typedef enum {
|
||||
CLUTTER_ACTOR_IN_DESTRUCTION = 1 << 0,
|
||||
CLUTTER_ACTOR_IS_TOPLEVEL = 1 << 1,
|
||||
CLUTTER_ACTOR_IN_REPARENT = 1 << 2,
|
||||
CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3, /* Used by stage to indicate GL
|
||||
* viewport / perspective etc
|
||||
* needs (re)setting.
|
||||
|
||||
/* Used by the stage to indicate GL viewport / perspective etc needs
|
||||
* (re)setting.
|
||||
*/
|
||||
CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */
|
||||
CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */
|
||||
CLUTTER_STAGE_IN_RESIZE = 1 << 6
|
||||
CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3,
|
||||
|
||||
/* Used to avoid recursion */
|
||||
CLUTTER_ACTOR_IN_PAINT = 1 << 4,
|
||||
|
||||
/* Used to avoid recursion */
|
||||
CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5,
|
||||
|
||||
/* Used by the stage if resizing is an asynchronous operation (like on
|
||||
* X11) to delay queueing relayouts until we got a notification from the
|
||||
* event handling
|
||||
*/
|
||||
CLUTTER_STAGE_IN_RESIZE = 1 << 6,
|
||||
|
||||
/* a flag for internal children of Containers */
|
||||
CLUTTER_ACTOR_INTERNAL_CHILD = 1 << 7
|
||||
} ClutterPrivateFlags;
|
||||
|
||||
struct _ClutterInputDevice
|
||||
@ -134,6 +147,8 @@ struct _ClutterMainContext
|
||||
gulong redraw_count;
|
||||
|
||||
GList *repaint_funcs;
|
||||
|
||||
gint internal_child;
|
||||
};
|
||||
|
||||
#define CLUTTER_CONTEXT() (_clutter_context_get_default ())
|
||||
|
@ -352,6 +352,8 @@ clutter_actor_lower
|
||||
clutter_actor_raise_top
|
||||
clutter_actor_lower_bottom
|
||||
clutter_actor_get_stage
|
||||
clutter_actor_push_internal
|
||||
clutter_actor_pop_internal
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_actor_set_depth
|
||||
|
@ -40,6 +40,7 @@ test_conformance_SOURCES = \
|
||||
test-actor-size.c \
|
||||
test-texture-fbo.c \
|
||||
test-script-parser.c \
|
||||
test-actor-destroy.c \
|
||||
$(NULL)
|
||||
|
||||
# For convenience, this provides a way to easily run individual unit tests:
|
||||
|
168
tests/conform/test-actor-destroy.c
Normal file
168
tests/conform/test-actor-destroy.c
Normal file
@ -0,0 +1,168 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define TEST_TYPE_DESTROY (test_destroy_get_type ())
|
||||
#define TEST_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_DESTROY, TestDestroy))
|
||||
#define TEST_IS_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_DESTROY))
|
||||
|
||||
typedef struct _TestDestroy TestDestroy;
|
||||
typedef struct _TestDestroyClass TestDestroyClass;
|
||||
|
||||
struct _TestDestroy
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterActor *bg;
|
||||
ClutterActor *label;
|
||||
ClutterActor *tex;
|
||||
|
||||
GList *children;
|
||||
};
|
||||
|
||||
struct _TestDestroyClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
static void clutter_container_init (ClutterContainerIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (TestDestroy, test_destroy, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_init));
|
||||
|
||||
static void
|
||||
test_destroy_add (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
TestDestroy *self = TEST_DESTROY (container);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (actor),
|
||||
G_OBJECT_TYPE_NAME (actor));
|
||||
|
||||
self->children = g_list_prepend (self->children, actor);
|
||||
clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_remove (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
TestDestroy *self = TEST_DESTROY (container);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Removing '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (actor),
|
||||
G_OBJECT_TYPE_NAME (actor));
|
||||
|
||||
g_assert (actor != self->bg);
|
||||
g_assert (actor != self->label);
|
||||
|
||||
if (!g_list_find (self->children, actor))
|
||||
g_assert (actor == self->tex);
|
||||
else
|
||||
self->children = g_list_remove (self->children, actor);
|
||||
|
||||
clutter_actor_unparent (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->add = test_destroy_add;
|
||||
iface->remove = test_destroy_remove;
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_destroy (ClutterActor *self)
|
||||
{
|
||||
TestDestroy *test = TEST_DESTROY (self);
|
||||
|
||||
if (test->bg != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->bg),
|
||||
G_OBJECT_TYPE_NAME (test->bg));
|
||||
|
||||
clutter_actor_destroy (test->bg);
|
||||
test->bg = NULL;
|
||||
}
|
||||
|
||||
if (test->label != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->label),
|
||||
G_OBJECT_TYPE_NAME (test->label));
|
||||
|
||||
clutter_actor_destroy (test->label);
|
||||
test->label = NULL;
|
||||
}
|
||||
|
||||
if (test->tex != NULL)
|
||||
{
|
||||
if (g_test_verbose ())
|
||||
g_print ("Destroying '%s' (type:%s)\n",
|
||||
clutter_actor_get_name (test->tex),
|
||||
G_OBJECT_TYPE_NAME (test->tex));
|
||||
|
||||
clutter_actor_destroy (test->tex);
|
||||
test->tex = NULL;
|
||||
}
|
||||
|
||||
g_list_foreach (test->children, (GFunc) clutter_actor_destroy, NULL);
|
||||
g_list_free (test->children);
|
||||
test->children = NULL;
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy)
|
||||
CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self);
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_class_init (TestDestroyClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->destroy = test_destroy_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
test_destroy_init (TestDestroy *self)
|
||||
{
|
||||
clutter_actor_push_internal ();
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding internal children...\n");
|
||||
|
||||
self->bg = clutter_rectangle_new ();
|
||||
clutter_actor_set_parent (self->bg, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->bg, "Background");
|
||||
|
||||
self->label = clutter_text_new ();
|
||||
clutter_actor_set_parent (self->label, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->label, "Label");
|
||||
|
||||
clutter_actor_pop_internal ();
|
||||
|
||||
self->tex = clutter_texture_new ();
|
||||
clutter_actor_set_parent (self->tex, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_name (self->tex, "Texture");
|
||||
}
|
||||
|
||||
void
|
||||
test_actor_destruction (TestConformSimpleFixture *fixture,
|
||||
gconstpointer dummy)
|
||||
{
|
||||
ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL);
|
||||
ClutterActor *child = clutter_rectangle_new ();
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Adding external child...\n");
|
||||
|
||||
clutter_actor_set_name (child, "Child");
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (test), child);
|
||||
|
||||
clutter_actor_destroy (test);
|
||||
}
|
@ -151,6 +151,7 @@ main (int argc, char **argv)
|
||||
TEST_CONFORM_SIMPLE ("/binding-pool", test_binding_pool);
|
||||
|
||||
TEST_CONFORM_SIMPLE ("/actor", test_anchors);
|
||||
TEST_CONFORM_SIMPLE ("/actor", test_actor_destruction);
|
||||
|
||||
TEST_CONFORM_SIMPLE ("/model", test_list_model_populate);
|
||||
TEST_CONFORM_SIMPLE ("/model", test_list_model_iterate);
|
||||
|
Loading…
Reference in New Issue
Block a user