diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 05d90196283979e7cd3d9642671d2863b934988f..f71103804873b8532d8b0528b82136738816480b 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -2560,6 +2560,22 @@ clutter_actor_notify_if_geometry_changed (ClutterActor *self, g_object_thaw_notify (obj); } +static void +absolute_allocation_changed (ClutterActor *actor) +{ + actor->priv->needs_compute_resource_scale = TRUE; +} + +static ClutterActorTraverseVisitFlags +absolute_allocation_changed_cb (ClutterActor *actor, + int depth, + gpointer user_data) +{ + absolute_allocation_changed (actor); + + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + /*< private > * clutter_actor_set_allocation_internal: * @self: a #ClutterActor @@ -2603,6 +2619,11 @@ clutter_actor_set_allocation_internal (ClutterActor *self, priv->needs_height_request = FALSE; priv->needs_allocation = FALSE; + priv->absolute_origin_changed |= x1_changed || y1_changed; + + if (priv->absolute_origin_changed || x2_changed || y2_changed) + absolute_allocation_changed (self); + if (x1_changed || y1_changed || x2_changed || @@ -10094,7 +10115,6 @@ clutter_actor_allocate (ClutterActor *self, { ClutterActorBox old_allocation, real_allocation; gboolean origin_changed, size_changed; - gboolean stage_allocation_changed; ClutterActorPrivate *priv; g_return_if_fail (CLUTTER_IS_ACTOR (self)); @@ -10106,11 +10126,26 @@ clutter_actor_allocate (ClutterActor *self, return; } - if (!clutter_actor_is_visible (self)) - return; - priv = self->priv; + priv->absolute_origin_changed = priv->parent + ? priv->parent->priv->absolute_origin_changed + : FALSE; + + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + { + if (priv->absolute_origin_changed) + { + _clutter_actor_traverse (self, + CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST, + absolute_allocation_changed_cb, + NULL, + NULL); + } + + goto out; + } + old_allocation = priv->allocation; real_allocation = *box; @@ -10142,49 +10177,46 @@ clutter_actor_allocate (ClutterActor *self, size_changed = (real_allocation.x2 != old_allocation.x2 || real_allocation.y2 != old_allocation.y2); - priv->absolute_origin_changed = priv->parent - ? priv->parent->priv->absolute_origin_changed - : FALSE; - - priv->absolute_origin_changed |= origin_changed; - - stage_allocation_changed = priv->absolute_origin_changed || size_changed; - - /* If we get an allocation "out of the blue" - * (we did not queue relayout), then we want to - * ignore it. But if we have needs_allocation set, - * we want to guarantee that allocate() virtual - * method is always called, i.e. that queue_relayout() - * always results in an allocate() invocation on - * an actor. + /* When needs_allocation is set but we didn't move nor resize, we still + * want to call the allocate() vfunc because a child probably called + * queue_relayout() and needs a new allocation. * - * The optimization here is to avoid re-allocating - * actors that did not queue relayout and were - * not moved. + * In case needs_allocation isn't set and we didn't move nor resize, we + * can safely stop allocating, but we need to notify the sub-tree in case + * our absolute origin changed. */ - if (!priv->needs_allocation && !stage_allocation_changed) + if (!priv->needs_allocation && !origin_changed && !size_changed) { + if (priv->absolute_origin_changed) + { + _clutter_actor_traverse (self, + CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST, + absolute_allocation_changed_cb, + NULL, + NULL); + } + CLUTTER_NOTE (LAYOUT, "No allocation needed"); - return; + goto out; } if (CLUTTER_ACTOR_IS_MAPPED (self)) self->priv->needs_paint_volume_update = TRUE; - if (stage_allocation_changed) - priv->needs_compute_resource_scale = TRUE; - - if (!stage_allocation_changed) + if (!origin_changed && !size_changed) { /* If the actor didn't move but needs_allocation is set, we just - * need to allocate the children */ + * need to allocate the children (see comment above) */ clutter_actor_allocate_internal (self, &real_allocation); - return; + goto out; } _clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION], &priv->allocation, &real_allocation); + +out: + priv->absolute_origin_changed = FALSE; } /** diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h index 2c5a2a50ee1afd6fac8ea298eb7a49c942ba3ae0..9f018ab84d8bd9fd8be642f7595cd14bcff13436 100644 --- a/clutter/clutter/clutter-stage-private.h +++ b/clutter/clutter/clutter-stage-private.h @@ -50,11 +50,6 @@ ClutterStageWindow *_clutter_stage_get_window (ClutterStage void _clutter_stage_get_projection_matrix (ClutterStage *stage, CoglMatrix *projection); void _clutter_stage_dirty_projection (ClutterStage *stage); -void _clutter_stage_set_viewport (ClutterStage *stage, - float x, - float y, - float width, - float height); void _clutter_stage_get_viewport (ClutterStage *stage, float *x, float *y, diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 540f9a1b78ad7c5bcdfd4f9d887be87a20194752..4ed580945309363ee14f1f88d784aa39a27cf71c 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -189,6 +189,9 @@ static void capture_view_into (ClutterStage *stage, uint8_t *data, int stride); static void clutter_stage_update_view_perspective (ClutterStage *stage); +static void clutter_stage_set_viewport (ClutterStage *stage, + float width, + float height); static void clutter_container_iface_init (ClutterContainerIface *iface); @@ -619,7 +622,6 @@ clutter_stage_allocate (ClutterActor *self, { ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; ClutterActorBox alloc = CLUTTER_ACTOR_BOX_INIT_ZERO; - float old_width, old_height; float new_width, new_height; float width, height; cairo_rectangle_int_t window_size; @@ -628,10 +630,6 @@ clutter_stage_allocate (ClutterActor *self, if (priv->impl == NULL) return; - /* our old allocation */ - clutter_actor_get_allocation_box (self, &alloc); - clutter_actor_box_get_size (&alloc, &old_width, &old_height); - /* the current allocation */ clutter_actor_box_get_size (box, &width, &height); @@ -719,27 +717,11 @@ clutter_stage_allocate (ClutterActor *self, &override); } - /* reset the viewport if the allocation effectively changed */ + /* set the viewport to the new allocation */ clutter_actor_get_allocation_box (self, &alloc); clutter_actor_box_get_size (&alloc, &new_width, &new_height); - if (CLUTTER_NEARBYINT (old_width) != CLUTTER_NEARBYINT (new_width) || - CLUTTER_NEARBYINT (old_height) != CLUTTER_NEARBYINT (new_height)) - { - int real_width = CLUTTER_NEARBYINT (new_width); - int real_height = CLUTTER_NEARBYINT (new_height); - - _clutter_stage_set_viewport (CLUTTER_STAGE (self), - 0, 0, - real_width, - real_height); - - /* Note: we don't assume that set_viewport will queue a full redraw - * since it may bail-out early if something preemptively set the - * viewport before the stage was really allocated its new size. - */ - queue_full_redraw (CLUTTER_STAGE (self)); - } + clutter_stage_set_viewport (CLUTTER_STAGE (self), new_width, new_height); } typedef struct _Vector4 @@ -2257,10 +2239,7 @@ clutter_stage_init (ClutterStage *self) g_signal_connect (self, "notify::min-height", G_CALLBACK (clutter_stage_notify_min_size), NULL); - _clutter_stage_set_viewport (self, - 0, 0, - geom.width, - geom.height); + clutter_stage_set_viewport (self, geom.width, geom.height); priv->paint_volume_stack = g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume)); @@ -2447,8 +2426,6 @@ _clutter_stage_dirty_projection (ClutterStage *stage) /* * clutter_stage_set_viewport: * @stage: A #ClutterStage - * @x: The X postition to render the stage at, in window coordinates - * @y: The Y position to render the stage at, in window coordinates * @width: The width to render the stage at, in window coordinates * @height: The height to render the stage at, in window coordinates * @@ -2481,19 +2458,22 @@ _clutter_stage_dirty_projection (ClutterStage *stage) * * Since: 1.6 */ -void -_clutter_stage_set_viewport (ClutterStage *stage, - float x, - float y, - float width, - float height) +static void +clutter_stage_set_viewport (ClutterStage *stage, + float width, + float height) { ClutterStagePrivate *priv; + float x, y; g_return_if_fail (CLUTTER_IS_STAGE (stage)); priv = stage->priv; + x = 0.f; + y = 0.f; + width = roundf (width); + height = roundf (height); if (x == priv->viewport[0] && y == priv->viewport[1] &&