mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
Enforce invariants on mapped, realized, visibility states
Bug 1138 - No trackable "mapped" state * Add a VISIBLE flag tracking application programmer's expected showing-state for the actor, allowing us to always ensure we keep what the app wants while tracking internal implementation state separately. * Make MAPPED reflect whether the actor will be painted; add notification on a ClutterActor::mapped property. Keep MAPPED state updated as the actor is shown, ancestors are shown, actor is reparented, etc. * Require a stage and realized parents to realize; this means at realization time the correct window system and GL resources are known. But unparented actors can no longer be realized. * Allow children to be unrealized even if parent is realized. Otherwise in effect either all actors or no actors are realized, i.e. it becomes a stage-global flag. * Allow clutter_actor_realize() to "fail" if not inside a toplevel * Rework clutter_actor_unrealize() so internally we have a flavor that does not mess with visibility flag * Add _clutter_actor_rerealize() to encapsulate a somewhat tricky operation we were doing in a couple of places * Do not realize/unrealize children in ClutterGroup, ClutterActor already does it * Do not realize impl by hand in clutter_stage_show(), since showing impl already does that * Do not unrealize in various dispose() methods, since ClutterActor dispose implementation already does it and chaining up is mandatory * ClutterTexture uses COGL while unrealizable (before it's added to a stage). Previously this breakage was affecting ClutterActor because we had to allow realize outside a stage. Move the breakage to ClutterTexture, by making ClutterTexture just use COGL while not realized. * Unrealize before we set parent to NULL in clutter_actor_unparent(). This means unrealize() implementations can get to the stage. Because actors need the stage in order to detach from stage. * Update clutter-actor-invariants.txt to reflect latest changes * Remove explicit hide/unrealize from ClutterActor::dispose since unparent already forces those Instead just assert that unparent() occurred and did the right thing. * Check whether parent implements unrealize before chaining up Needed because ClutterGroup no longer has to implement unrealize. * Perform unrealize in the default handler for the signal. This allows non-containers that have children to work properly, and allows containers to override how it's done. * Add map/unmap virtual methods and set MAPPED flag on self and children in there. This allows subclasses to hook map/unmap. These are not signals, because notify::mapped is better for anything it's legitimate for a non-subclass to do. Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
This commit is contained in:
parent
b73ee6992c
commit
125bded814
File diff suppressed because it is too large
Load Diff
@ -76,7 +76,7 @@ G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_ACTOR_IS_MAPPED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_MAPPED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_REALIZED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REALIZED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_VISIBLE(e) (CLUTTER_ACTOR_IS_MAPPED (e) && CLUTTER_ACTOR_IS_REALIZED (e))
|
||||
#define CLUTTER_ACTOR_IS_VISIBLE(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_VISIBLE) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_REACTIVE(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REACTIVE) != FALSE)
|
||||
|
||||
typedef struct _ClutterActorClass ClutterActorClass;
|
||||
@ -102,11 +102,12 @@ typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data);
|
||||
|
||||
/**
|
||||
* ClutterActorFlags:
|
||||
* @CLUTTER_ACTOR_MAPPED: the actor has been painted
|
||||
* @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside a toplevel, and all parents visible)
|
||||
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
|
||||
* allocated
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
|
||||
* signals
|
||||
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
|
||||
*
|
||||
* Flags used to signal the state of an actor.
|
||||
*/
|
||||
@ -114,7 +115,8 @@ typedef enum
|
||||
{
|
||||
CLUTTER_ACTOR_MAPPED = 1 << 1,
|
||||
CLUTTER_ACTOR_REALIZED = 1 << 2,
|
||||
CLUTTER_ACTOR_REACTIVE = 1 << 3
|
||||
CLUTTER_ACTOR_REACTIVE = 1 << 3,
|
||||
CLUTTER_ACTOR_VISIBLE = 1 << 4
|
||||
} ClutterActorFlags;
|
||||
|
||||
/**
|
||||
@ -220,6 +222,8 @@ struct _ClutterActorClass
|
||||
void (* hide_all) (ClutterActor *actor);
|
||||
void (* realize) (ClutterActor *actor);
|
||||
void (* unrealize) (ClutterActor *actor);
|
||||
void (* map) (ClutterActor *actor);
|
||||
void (* unmap) (ClutterActor *actor);
|
||||
void (* paint) (ClutterActor *actor);
|
||||
void (* parent_set) (ClutterActor *actor,
|
||||
ClutterActor *old_parent);
|
||||
@ -280,6 +284,8 @@ void clutter_actor_hide (ClutterActor
|
||||
void clutter_actor_hide_all (ClutterActor *self);
|
||||
void clutter_actor_realize (ClutterActor *self);
|
||||
void clutter_actor_unrealize (ClutterActor *self);
|
||||
void clutter_actor_map (ClutterActor *self);
|
||||
void clutter_actor_unmap (ClutterActor *self);
|
||||
void clutter_actor_paint (ClutterActor *self);
|
||||
void clutter_actor_pick (ClutterActor *self,
|
||||
const ClutterColor *color);
|
||||
|
@ -105,22 +105,6 @@ clutter_group_paint (ClutterActor *actor)
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_realize (ClutterActor *actor)
|
||||
{
|
||||
clutter_container_foreach (CLUTTER_CONTAINER (actor),
|
||||
CLUTTER_CALLBACK (clutter_actor_realize),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_unrealize (ClutterActor *actor)
|
||||
{
|
||||
clutter_container_foreach (CLUTTER_CONTAINER (actor),
|
||||
CLUTTER_CALLBACK (clutter_actor_unrealize),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
@ -587,8 +571,6 @@ clutter_group_class_init (ClutterGroupClass *klass)
|
||||
actor_class->pick = clutter_group_pick;
|
||||
actor_class->show_all = clutter_group_real_show_all;
|
||||
actor_class->hide_all = clutter_group_real_hide_all;
|
||||
actor_class->realize = clutter_group_realize;
|
||||
actor_class->unrealize = clutter_group_unrealize;
|
||||
|
||||
actor_class->get_preferred_width = clutter_group_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_group_get_preferred_height;
|
||||
|
@ -217,6 +217,10 @@ gboolean _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint,
|
||||
void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor);
|
||||
|
||||
void _clutter_actor_rerealize (ClutterActor *self,
|
||||
ClutterCallback callback,
|
||||
void *data);
|
||||
|
||||
void _clutter_actor_set_opacity_parent (ClutterActor *self,
|
||||
ClutterActor *parent);
|
||||
|
||||
|
@ -263,15 +263,13 @@ clutter_stage_realize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* Make sure the viewport and projection matrix are valid for the
|
||||
first paint (which will likely occur before the ConfigureNotify
|
||||
is received) */
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->realize (priv->impl);
|
||||
clutter_actor_realize (priv->impl);
|
||||
|
||||
/* ensure that the stage is using the context if the
|
||||
* realization sequence was successful
|
||||
@ -287,12 +285,9 @@ clutter_stage_unrealize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
/* unset the flag */
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* and then unrealize the implementation */
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->unrealize (priv->impl);
|
||||
clutter_actor_unrealize (priv->impl);
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
}
|
||||
@ -304,9 +299,6 @@ clutter_stage_show (ClutterActor *self)
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
clutter_actor_realize (priv->impl);
|
||||
|
||||
clutter_actor_show (priv->impl);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
|
||||
@ -394,6 +386,14 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_offscreen_while_unrealized (ClutterActor *actor,
|
||||
void *data)
|
||||
{
|
||||
CLUTTER_STAGE (actor)->priv->is_offscreen =
|
||||
GPOINTER_TO_INT (data);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -415,24 +415,26 @@ clutter_stage_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case PROP_OFFSCREEN:
|
||||
{
|
||||
gboolean was_showing;
|
||||
|
||||
if (priv->is_offscreen == g_value_get_boolean (value))
|
||||
return;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
{
|
||||
was_showing = CLUTTER_ACTOR_IS_VISIBLE (actor);
|
||||
|
||||
/* Backend needs to check this prop and handle accordingly
|
||||
* in realise.
|
||||
* FIXME: More 'obvious' implementation needed?
|
||||
*/
|
||||
clutter_actor_unrealize (actor);
|
||||
priv->is_offscreen = g_value_get_boolean (value);
|
||||
clutter_actor_realize (actor);
|
||||
_clutter_actor_rerealize (actor,
|
||||
set_offscreen_while_unrealized,
|
||||
GINT_TO_POINTER (g_value_get_boolean (value)));
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
if (was_showing &&
|
||||
!CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
priv->is_offscreen = ~g_value_get_boolean (value);
|
||||
}
|
||||
else
|
||||
priv->is_offscreen = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_FULLSCREEN:
|
||||
@ -534,7 +536,7 @@ clutter_stage_dispose (GObject *object)
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (object));
|
||||
clutter_actor_hide (CLUTTER_ACTOR (object));
|
||||
|
||||
if (priv->update_idle)
|
||||
{
|
||||
|
@ -335,19 +335,15 @@ clutter_texture_realize (ClutterActor *actor)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_READ_PIXELS))
|
||||
{
|
||||
/* Dont allow realization with no data - note set_data
|
||||
* will set realize flags.
|
||||
/* If we have no data, then realization is a no-op but
|
||||
* we still want to be in REALIZED state to maintain
|
||||
* invariants. We may have already created the texture
|
||||
* if someone set some data earlier, or we may create it
|
||||
* later if someone sets some data later. The fact that
|
||||
* we may have created it earlier is really a bug, since
|
||||
* it means ClutterTexture can have GL resources without
|
||||
* being realized.
|
||||
*/
|
||||
CLUTTER_NOTE (TEXTURE,
|
||||
"Texture has no image data cannot realize");
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "Texture realized");
|
||||
@ -539,9 +535,6 @@ clutter_texture_paint (ClutterActor *self)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR(texture)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR(texture));
|
||||
|
||||
if (priv->fbo_handle != COGL_INVALID_HANDLE)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
@ -1392,6 +1385,12 @@ clutter_texture_get_cogl_texture (ClutterTexture *texture)
|
||||
* @cogl_tex. A reference to the texture is taken so if the handle is
|
||||
* no longer needed it should be deref'd with cogl_handle_unref.
|
||||
*
|
||||
* This should not be called on an unrealizable texture (one that
|
||||
* isn't inside a stage). (Currently the ClutterTexture
|
||||
* implementation relies on being able to have a GL texture while
|
||||
* unrealized, which means you can get away with it, but it's
|
||||
* not correct and may change in the future.)
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
@ -1405,6 +1404,12 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
g_return_if_fail (CLUTTER_IS_TEXTURE (texture));
|
||||
g_return_if_fail (cogl_is_texture (cogl_tex));
|
||||
|
||||
/* FIXME this implementation should realize the actor if it's in a
|
||||
* stage, and warn and return if not in a stage yet. However, right
|
||||
* now everything would break if we did that, so we just fudge it
|
||||
* and we're broken: we can have a texture without being realized.
|
||||
*/
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
width = cogl_texture_get_width (cogl_tex);
|
||||
@ -1420,6 +1425,14 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
|
||||
/* Remove old texture */
|
||||
texture_free_gl_resources (texture);
|
||||
|
||||
/* Free any saved data so realization doesn't resend it to GL */
|
||||
if (priv->local_data)
|
||||
{
|
||||
g_free (priv->local_data);
|
||||
priv->local_data = NULL;
|
||||
}
|
||||
|
||||
/* Use the new texture */
|
||||
|
||||
cogl_material_set_layer (priv->material, 0, cogl_tex);
|
||||
@ -1436,8 +1449,6 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
priv->width,
|
||||
priv->height);
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
if (size_change)
|
||||
{
|
||||
g_signal_emit (texture, texture_signals[SIZE_CHANGE], 0,
|
||||
@ -1480,6 +1491,10 @@ clutter_texture_set_from_data (ClutterTexture *texture,
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
|
||||
/* FIXME if we are not realized, we should store the data
|
||||
* for future use, instead of creating the texture.
|
||||
*/
|
||||
|
||||
new_texture = cogl_texture_new_from_data (width, height,
|
||||
max_waste, flags,
|
||||
source_format,
|
||||
@ -2004,15 +2019,8 @@ clutter_texture_set_filter_quality (ClutterTexture *texture,
|
||||
filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) &&
|
||||
CLUTTER_ACTOR_IS_REALIZED (texture))
|
||||
{
|
||||
gboolean was_visible;
|
||||
|
||||
was_visible = CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (texture));
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (texture));
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
|
||||
if (was_visible)
|
||||
clutter_actor_show (CLUTTER_ACTOR (texture));
|
||||
_clutter_actor_rerealize (CLUTTER_ACTOR (texture),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (texture), "filter-quality");
|
||||
@ -2172,9 +2180,13 @@ clutter_texture_get_base_size (ClutterTexture *texture,
|
||||
|
||||
/* Attempt to realize, mainly for subclasses ( such as labels )
|
||||
* which may not create pixbuf data and thus base size until
|
||||
* realization happens.
|
||||
* realization happens. If we aren't in a stage we can't realize
|
||||
* though. Doing this here is probably just broken; instead
|
||||
* we could virtualize get_base_size, or have the subclasses
|
||||
* create the pixbufs sooner, or something better.
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture))
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture) &&
|
||||
clutter_actor_get_stage (CLUTTER_ACTOR (texture)) != NULL)
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
|
||||
if (width)
|
||||
@ -2251,8 +2263,15 @@ clutter_texture_set_area_from_rgb_data (ClutterTexture *texture,
|
||||
if ((flags & CLUTTER_TEXTURE_RGB_FLAG_PREMULT))
|
||||
source_format |= COGL_PREMULT_BIT;
|
||||
|
||||
/* attempt to realize ... */
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture) &&
|
||||
clutter_actor_get_stage (CLUTTER_ACTOR (texture)) != NULL)
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
|
||||
/* due to the fudging of clutter_texture_set_cogl_texture()
|
||||
* which allows setting a texture pre-realize, we may end
|
||||
* up having a texture even if we couldn't realize yet.
|
||||
*/
|
||||
cogl_texture = clutter_texture_get_cogl_texture (texture);
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
@ -2329,8 +2348,6 @@ on_fbo_source_size_change (GObject *object,
|
||||
if (priv->fbo_handle == COGL_INVALID_HANDLE)
|
||||
{
|
||||
g_warning ("%s: Offscreen texture creation failed", G_STRLOC);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (CLUTTER_ACTOR (texture),
|
||||
CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_MARK();
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
@ -253,8 +254,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
@ -275,9 +276,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
if (stage_x11->xwin)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -393,6 +393,10 @@ typedef struct {
|
||||
stage_fruity = CLUTTER_STAGE_EGL(backend_fruity->stage);
|
||||
|
||||
alive = FALSE;
|
||||
/* FIXME why is this unrealize here? is the intent to destroy the stage?
|
||||
* or hide it? Trying to clean up all manual unrealization so
|
||||
* clutter_actor_unrealize() can be made private to clutter-actor.c
|
||||
*/
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_fruity));
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_MARK();
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
@ -222,8 +223,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -67,9 +67,7 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
/* Chain up so all children get unrealized, needed to move texture data
|
||||
* across contexts
|
||||
*/
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize (actor);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
@ -310,12 +308,6 @@ fail:
|
||||
static void
|
||||
clutter_stage_glx_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (gobject);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
if (stage_x11->xwin)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_glx));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_glx_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -199,8 +199,6 @@ clutter_stage_sdl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (gobject);
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_sdl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_sdl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -574,9 +574,7 @@ clutter_stage_win32_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Unrealizing stage");
|
||||
|
||||
/* Chain up so all children get unrealized, needed to move texture
|
||||
* data across contexts
|
||||
*/
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)->unrealize (actor);
|
||||
|
||||
if (stage_win32->client_dc)
|
||||
@ -602,9 +600,6 @@ clutter_stage_win32_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (gobject);
|
||||
|
||||
if (stage_win32->hwnd)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (gobject));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_win32_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -749,6 +744,12 @@ clutter_win32_set_stage_foreign (ClutterStage *stage,
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
stage_win32 = CLUTTER_STAGE_WIN32 (impl);
|
||||
|
||||
/* FIXME this needs updating to use _clutter_actor_rerealize(),
|
||||
* see the analogous code in x11 backend. Probably best if
|
||||
* win32 maintainer does it so they can be sure it compiles
|
||||
* and works.
|
||||
*/
|
||||
|
||||
clutter_actor_unrealize (actor);
|
||||
|
||||
if (!GetClientRect (hwnd, &client_rect))
|
||||
|
@ -297,8 +297,7 @@ clutter_stage_x11_allocate (ClutterActor *self,
|
||||
if (stage_x11->xpixmap != None)
|
||||
{
|
||||
/* Need to recreate to resize */
|
||||
clutter_actor_unrealize (self);
|
||||
clutter_actor_realize (self);
|
||||
_clutter_actor_rerealize (self, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,11 +528,6 @@ clutter_stage_x11_finalize (GObject *gobject)
|
||||
static void
|
||||
clutter_stage_x11_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
if (stage_x11->xwin)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_x11));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_x11_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -671,6 +665,29 @@ clutter_x11_get_stage_visual (ClutterStage *stage)
|
||||
return CLUTTER_STAGE_X11 (impl)->xvisinfo;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterGeometry geom;
|
||||
Window xwindow;
|
||||
} ForeignWindowData;
|
||||
|
||||
static void
|
||||
set_foreign_window_callback (ClutterActor *actor,
|
||||
void *data)
|
||||
{
|
||||
ForeignWindowData *fwd = data;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", (int) fwd->xwindow);
|
||||
|
||||
fwd->stage_x11->xwin = fwd->xwindow;
|
||||
fwd->stage_x11->is_foreign_xwin = TRUE;
|
||||
|
||||
fwd->stage_x11->xwin_width = fwd->geom.width;
|
||||
fwd->stage_x11->xwin_height = fwd->geom.height;
|
||||
|
||||
clutter_actor_set_geometry (actor, &fwd->geom);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_x11_set_stage_foreign:
|
||||
* @stage: a #ClutterStage
|
||||
@ -693,7 +710,7 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
guint width, height, border, depth;
|
||||
Window root_return;
|
||||
Status status;
|
||||
ClutterGeometry geom;
|
||||
ForeignWindowData fwd;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
@ -721,20 +738,16 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clutter_actor_unrealize (actor);
|
||||
fwd.stage_x11 = stage_x11;
|
||||
fwd.xwindow = xwindow;
|
||||
fwd.geom.x = x;
|
||||
fwd.geom.y = y;
|
||||
fwd.geom.width = width;
|
||||
fwd.geom.height = height;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", (int) xwindow);
|
||||
|
||||
stage_x11->xwin = xwindow;
|
||||
stage_x11->is_foreign_xwin = TRUE;
|
||||
|
||||
geom.x = x;
|
||||
geom.y = y;
|
||||
geom.width = stage_x11->xwin_width = width;
|
||||
geom.height = stage_x11->xwin_height = height;
|
||||
|
||||
clutter_actor_set_geometry (actor, &geom);
|
||||
clutter_actor_realize (actor);
|
||||
_clutter_actor_rerealize (actor,
|
||||
set_foreign_window_callback,
|
||||
&fwd);
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
|
||||
@ -744,11 +757,11 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
void
|
||||
clutter_stage_x11_map (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
/* set the mapped flag on the implementation */
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
||||
/* set the mapped state on the wrapper */
|
||||
clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper));
|
||||
|
||||
/* and on the wrapper itself */
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
||||
/* and on the implementation second */
|
||||
clutter_actor_map (CLUTTER_ACTOR (stage_x11));
|
||||
|
||||
if (stage_x11->fullscreen_on_map)
|
||||
clutter_stage_fullscreen (CLUTTER_STAGE (stage_x11->wrapper));
|
||||
@ -762,8 +775,8 @@ void
|
||||
clutter_stage_x11_unmap (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
/* like above, unset the MAPPED stage on both the implementation and
|
||||
* the wrapper
|
||||
* the wrapper, but unmap in reverse order from map
|
||||
*/
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
||||
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11));
|
||||
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper));
|
||||
}
|
||||
|
@ -28,20 +28,56 @@ ClutterActor.
|
||||
a. Public ClutterActor Flags
|
||||
|
||||
CLUTTER_ACTOR_REALIZED
|
||||
Set by clutter_actor_realize(), unset by clutter_actor_unrealize().
|
||||
Means: the actor has GPU resources associated to its paint cycle.
|
||||
Once realized an actor needs to be explicitly unrealized unless
|
||||
being destroyed. Hide, reparent etc will not unrealize.
|
||||
Means: the actor has GPU resources associated to its paint
|
||||
cycle.
|
||||
|
||||
Set by clutter_actor_realize(), unset by
|
||||
clutter_actor_unrealize(). Generally set implicitly when the
|
||||
actor becomes MAPPED (see below).
|
||||
|
||||
May only be set if one of the actor's ancestors is a toplevel.
|
||||
May only be set if all of the actor's ancestors are realized.
|
||||
|
||||
Once realized an actor remains realized until removed from the
|
||||
toplevel. Hide, reparent will not unrealize; but unparent or
|
||||
destroy will unrealize since they remove the actor from the
|
||||
toplevel.
|
||||
|
||||
CLUTTER_ACTOR_MAPPED
|
||||
Set by clutter_actor_show(), unset by clutter_actor_hide()
|
||||
May only be set if CLUTTER_ACTOR_IS_REALIZED (actor).
|
||||
Means: the actor has been set as visible
|
||||
Means: the actor will be painted if the stage is mapped.
|
||||
|
||||
On non-toplevels, will be set if all of the following are
|
||||
true, and unset otherwise:
|
||||
* the actor's VISIBLE flag is set
|
||||
* all of the actor's non-toplevel ancestors have the MAPPED
|
||||
flag set
|
||||
* the actor has a toplevel ancestor
|
||||
* the toplevel ancestor's VISIBLE flag is set
|
||||
* the toplevel ancestor's REALIZED flag is set
|
||||
|
||||
On toplevels, MAPPED is set asynchronously when the window
|
||||
system notifies Clutter that the toplevel has been made
|
||||
visible on the screen.
|
||||
|
||||
The MAPPED flag requires that an actor is REALIZED. When
|
||||
Clutter sets the MAPPED flag, it forces realization; this is
|
||||
the "normal" way for realization to occur, though explicit
|
||||
realization with clutter_actor_realize() is permitted.
|
||||
|
||||
CLUTTER_ACTOR_VISIBLE
|
||||
Implies: CLUTTER_ACTOR_IS_REALIZED (actor)
|
||||
&&
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor)
|
||||
Means: the actor's "visible" property was set to true by
|
||||
the application programmer.
|
||||
|
||||
Set by clutter_actor_show(), unset by clutter_actor_hide().
|
||||
|
||||
This is an application-controlled property, while MAPPED and
|
||||
REALIZED are usually managed by Clutter (with the exception
|
||||
that applications can "realize early" with
|
||||
clutter_actor_realize()).
|
||||
|
||||
If VISIBLE is unset, the actor (and any children) must
|
||||
be immediately unmapped, to maintain the invariants for
|
||||
the MAPPED flag.
|
||||
|
||||
CLUTTER_ACTOR_REACTIVE
|
||||
Set and unset by clutter_actor_set_reactive()
|
||||
@ -63,7 +99,18 @@ CLUTTER_ACTOR_IS_TOPLEVEL
|
||||
Set internally by the initialization of ClutterStage
|
||||
|
||||
CLUTTER_ACTOR_IN_REPARENT
|
||||
Set internally by clutter_actor_reparent()
|
||||
Set internally by clutter_actor_reparent(). This flag
|
||||
optimizes the reparent process by avoiding the need
|
||||
to pass through an unrealized state when the actor is
|
||||
removed from the old parent.
|
||||
|
||||
CLUTTER_ACTOR_ABOUT_TO_UNPARENT
|
||||
Set internally during part of clutter_actor_unparent().
|
||||
Causes the actor to pretend it has no parent, then
|
||||
update invariants; which effectively forces the actor
|
||||
to unrealize. The purpose of this is to unrealize _before_ the
|
||||
actor is removed from the stage, so unrealize implementations
|
||||
can use clutter_actor_get_stage().
|
||||
|
||||
CLUTTER_ACTOR_SYNC_MATRICES
|
||||
Set internally by ClutterStage implementations
|
||||
@ -101,59 +148,106 @@ In the following
|
||||
1) CLUTTER_ACTOR_IN_DESTRUCTION => !CLUTTER_ACTOR_IS_MAPPED (actor) &&
|
||||
!CLUTTER_ACTOR_IS_REALIZED (actor)
|
||||
|
||||
clutter_actor_destroy() will cause an actor to be hidden
|
||||
and unrealized.
|
||||
clutter_actor_destroy() will cause an actor to be unparented,
|
||||
which means the actor must be unmapped and unrealized as
|
||||
well.
|
||||
|
||||
2) CLUTTER_ACTOR_IS_MAPPED (actor) => CLUTTER_ACTOR_IS_REALIZED (actor)
|
||||
|
||||
calling clutter_actor_show() on an unrealized actor will cause
|
||||
a realization to happen.
|
||||
when an actor is mapped, it must first be realized.
|
||||
|
||||
This is the most common way an actor becomes realized.
|
||||
|
||||
3) if clutter_actor_set_parent (actor, parent):
|
||||
CLUTTER_ACTOR_IS_REALIZED (parent) => CLUTTER_ACTOR_IS_REALIZED (actor)
|
||||
((parent_is_not_toplevel && CLUTTER_ACTOR_IS_MAPPED (parent)) ||
|
||||
(parent_is_toplevel && CLUTTER_ACTOR_IS_VISIBLE(parent))) &&
|
||||
CLUTTER_ACTOR_IS_VISIBLE (actor)
|
||||
=> CLUTTER_ACTOR_IS_MAPPED (actor)
|
||||
|
||||
calling clutter_actor_set_parent() on an actor and a realized
|
||||
parent will cause a realization on the actor.
|
||||
calling clutter_actor_set_parent() on an actor and a mapped
|
||||
parent will map the actor if it has been shown.
|
||||
|
||||
4) if clutter_actor_unparent (actor):
|
||||
CLUTTER_ACTOR_IS_MAPPED (actor) <=> CLUTTER_ACTOR_IN_REPARENT
|
||||
|
||||
calling clutter_actor_unparent() on an actor will hide the actor;
|
||||
calling clutter_actor_reparent() on an actor will leave the actor
|
||||
in the same state.
|
||||
calling clutter_actor_unparent() on an actor will unmap and
|
||||
unrealize the actor since it no longer has a toplevel.
|
||||
|
||||
Neither will unrealize.
|
||||
calling clutter_actor_reparent() on an actor will leave the
|
||||
actor mapped and realized (if it was before) until it has a
|
||||
new parent, at which point the invariants implied by the new
|
||||
parent's state are applied.
|
||||
|
||||
5) CLUTTER_ACTOR_IS_REALIZED(actor) => CLUTTER_ACTOR_IS_REALIZED(parent)
|
||||
|
||||
Actors may only be realized if their parent is realized.
|
||||
However, they may be unrealized even though their parent
|
||||
is realized.
|
||||
|
||||
This implies that an actor may not be realized unless
|
||||
it has a parent, or is a toplevel.
|
||||
|
||||
Since only toplevels can realize without a parent, no actor
|
||||
can be realized unless it either is a toplevel or has a
|
||||
toplevel ancestor.
|
||||
|
||||
As long as they are unmapped, actors may be unrealized. This
|
||||
will force all children of the actor to be unrealized, since
|
||||
children may not be realized while parents are unrealized.
|
||||
|
||||
6) CLUTTER_ACTOR_IS_MAPPED(actor) <=>
|
||||
( ( (CLUTTER_ACTOR_IS_VISIBLE(toplevel_parent) &&
|
||||
CLUTTER_ACTOR_IS_REALIZED(toplevel_parent)) ||
|
||||
CLUTTER_ACTOR_IS_MAPPED(non_toplevel_parent) ) ) &&
|
||||
CLUTTER_ACTOR_IS_VISIBLE(actor)
|
||||
|
||||
Actors _must_ be mapped if and only if they are visible and
|
||||
their parent is mapped, or they are visible and their
|
||||
parent is a toplevel that's realized and visible.
|
||||
|
||||
This invariant enables us to track whether an actor will
|
||||
be painted (whether it's MAPPED) without ever traversing
|
||||
the actor graph.
|
||||
|
||||
iii. State changes
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
clutter_actor_show:
|
||||
1. if !CLUTTER_ACTOR_REALIZED calls clutter_actor_realize
|
||||
2. sets CLUTTER_ACTOR_MAPPED
|
||||
1. sets VISIBLE
|
||||
2. sets MAPPED if invariants are met; mapping in turn sets
|
||||
REALIZED
|
||||
|
||||
clutter_actor_hide:
|
||||
1. sets !CLUTTER_ACTOR_MAPPED
|
||||
1. sets !VISIBLE
|
||||
2. unsets MAPPED if actor was mapped previously
|
||||
3. does not affect REALIZED
|
||||
|
||||
clutter_actor_destroy:
|
||||
1. sets CLUTTER_ACTOR_IN_DESTRUCTION
|
||||
2. unparents the actor, which in turn implies unmap and unrealize
|
||||
|
||||
clutter_actor_realize:
|
||||
sets CLUTTER_ACTOR_REALIZED
|
||||
1. attempts to set REALIZED on all parents, failing if
|
||||
invariants are not met, e.g. not in a toplevel yet
|
||||
2. sets REALIZED on actor if parent was successfully realized
|
||||
|
||||
clutter_actor_unrealized:
|
||||
1. if CLUTTER_ACTOR_MAPPED calls clutter_actor_hide
|
||||
2. sets !CLUTTER_ACTOR_REALIZED
|
||||
clutter_actor_unrealize:
|
||||
1. sets !VISIBLE which forces !MAPPED
|
||||
2. sets !REALIZED
|
||||
3. !MAPPED and !REALIZED forces unmap and unrealize of all
|
||||
children
|
||||
|
||||
clutter_actor_set_parent:
|
||||
1. sets actor->parent
|
||||
2. if parent is CLUTTER_ACTOR_REALIZED calls clutter_actor_realize
|
||||
3. if actor->show_on_set_parent is TRUE calls clutter_actor_show
|
||||
2. if actor->show_on_set_parent is TRUE calls clutter_actor_show
|
||||
3. sets MAPPED if all prerequisites are now met for map
|
||||
4. if !CLUTTER_ACTOR_IN_REPARENT emits ::parent-set with
|
||||
old_parent set to NULL
|
||||
|
||||
clutter_actor_unset_parent:
|
||||
clutter_actor_unparent:
|
||||
1. unsets actor->parent
|
||||
2. if !CLUTTER_ACTOR_IN_REPARENT calls clutter_actor_hide
|
||||
2. if !CLUTTER_ACTOR_IN_REPARENT, sets !MAPPED and !REALIZED
|
||||
since the invariants for those flags are no longer met
|
||||
3. if !CLUTTER_ACTOR_IN_REPARENT emits ::parent-set with
|
||||
old_parent set to the previous parent
|
||||
|
||||
@ -163,6 +257,9 @@ clutter_actor_reparent:
|
||||
equivalent to:
|
||||
clutter_actor_unparent
|
||||
clutter_actor_set_parent
|
||||
3. updates state of the actor to match invariants
|
||||
(may change MAPPED or REALIZED in either direction,
|
||||
depending on state of the new parent)
|
||||
|
||||
|
||||
iv. Responsibilities of a ClutterActor
|
||||
@ -173,22 +270,25 @@ clutter_actor_reparent:
|
||||
When adding an actor to a container, the container must:
|
||||
|
||||
1. call clutter_actor_set_parent (actor, container)
|
||||
2. call clutter_actor_queue_relayout (container)
|
||||
2. call clutter_actor_queue_relayout (container) if
|
||||
adding the actor changes the container's preferred
|
||||
size
|
||||
|
||||
b. Removing from a container
|
||||
|
||||
When removing an actor from a container, the container must:
|
||||
|
||||
1. call clutter_actor_unparent (actor)
|
||||
2. call clutter_actor_queue_relayout (container)
|
||||
2. call clutter_actor_queue_relayout (container) if removing
|
||||
the actor changes the container's preferred size
|
||||
|
||||
Notes:
|
||||
|
||||
* here a container actor is any actor that contains children actors; it
|
||||
does not imply the implementation of the ClutterContainer interface.
|
||||
|
||||
* clutter_actor_unparent() will hide the actor except in the special case
|
||||
when CLUTTER_ACTOR_IN_REPARENT is set.
|
||||
* clutter_actor_unparent() will unmap and unrealize the actor except
|
||||
in the special case when CLUTTER_ACTOR_IN_REPARENT is set.
|
||||
|
||||
* 'Composite' Clutter actors need to pass down any allocations to children.
|
||||
|
||||
|
@ -21,15 +21,38 @@ test_initial_state (TestConformSimpleFixture *fixture,
|
||||
}
|
||||
|
||||
void
|
||||
test_realized (TestConformSimpleFixture *fixture,
|
||||
test_shown_not_parented (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
|
||||
clutter_actor_show (actor);
|
||||
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
}
|
||||
|
||||
void
|
||||
test_realized (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
|
||||
clutter_actor_hide (actor); /* don't show, so won't map */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
actor);
|
||||
clutter_actor_realize (actor);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
@ -45,33 +68,130 @@ test_mapped (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
|
||||
clutter_actor_show (actor);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
actor);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
}
|
||||
|
||||
void
|
||||
test_realize_not_recursive (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
group = clutter_group_new ();
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
|
||||
clutter_actor_hide (group); /* don't show, so won't map */
|
||||
clutter_actor_hide (actor); /* don't show, so won't map */
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
group);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group),
|
||||
actor);
|
||||
|
||||
clutter_actor_realize (group);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (group));
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
|
||||
/* realizing group did not realize the child */
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
clutter_actor_destroy (group);
|
||||
}
|
||||
|
||||
void
|
||||
test_map_recursive (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
group = clutter_group_new ();
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
|
||||
clutter_actor_hide (group); /* hide at first */
|
||||
clutter_actor_show (actor); /* show at first */
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
group);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (group),
|
||||
actor);
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor)));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
|
||||
/* show group, which should map and realize both
|
||||
* group and child.
|
||||
*/
|
||||
clutter_actor_show (group);
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (group));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
|
||||
clutter_actor_destroy (group);
|
||||
}
|
||||
|
||||
void
|
||||
test_show_on_set_parent (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
ClutterActor *actor, *group;
|
||||
gboolean show_on_set_parent;
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
group = clutter_group_new ();
|
||||
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group)));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
||||
group);
|
||||
|
||||
actor = clutter_rectangle_new ();
|
||||
g_object_get (G_OBJECT (actor),
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
@ -94,8 +214,9 @@ test_show_on_set_parent (TestConformSimpleFixture *fixture,
|
||||
"show-on-set-parent", &show_on_set_parent,
|
||||
NULL);
|
||||
|
||||
g_assert (CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor)));
|
||||
g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor));
|
||||
g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor));
|
||||
g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor));
|
||||
g_assert (show_on_set_parent == TRUE);
|
||||
|
||||
clutter_actor_destroy (actor);
|
||||
|
@ -116,7 +116,10 @@ main (int argc, char **argv)
|
||||
TEST_CONFORM_SIMPLE ("/fixed", test_fixed_constants);
|
||||
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_initial_state);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_shown_not_parented);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_realized);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_realize_not_recursive);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_map_recursive);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_mapped);
|
||||
TEST_CONFORM_SIMPLE ("/invariants", test_show_on_set_parent);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user