Пример #1
0
static void
meta_window_group_cull_out (MetaWindowGroup *group,
                            ClutterActor    *unredirected_window,
                            gboolean         has_unredirected_window,
                            cairo_region_t  *unobscured_region,
                            cairo_region_t  *clip_region)
{
  ClutterActor *actor = CLUTTER_ACTOR (group);
  ClutterActor *child;
  ClutterActorIter iter;

  /* We walk the list from top to bottom (opposite of painting order),
   * and subtract the opaque area of each window out of the visible
   * region that we pass to the windows below.
   */
  clutter_actor_iter_init (&iter, actor);
  while (clutter_actor_iter_prev (&iter, &child))
    {
      if (!CLUTTER_ACTOR_IS_VISIBLE (child))
        continue;

      if (has_unredirected_window && child == unredirected_window)
        continue;

      /* If an actor has effects applied, then that can change the area
       * it paints and the opacity, so we no longer can figure out what
       * portion of the actor is obscured and what portion of the screen
       * it obscures, so we skip the actor.
       *
       * This has a secondary beneficial effect: if a ClutterOffscreenEffect
       * is applied to an actor, then our clipped redraws interfere with the
       * caching of the FBO - even if we only need to draw a small portion
       * of the window right now, ClutterOffscreenEffect may use other portions
       * of the FBO later. So, skipping actors with effects applied also
       * prevents these bugs.
       *
       * Theoretically, we should check clutter_actor_get_offscreen_redirect()
       * as well for the same reason, but omitted for simplicity in the
       * hopes that no-one will do that.
       */
      if (clutter_actor_has_effects (child))
        continue;

      if (META_IS_WINDOW_ACTOR (child))
        {
          MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
          int x, y;

          if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
            continue;

          /* Temporarily move to the coordinate system of the actor */
          cairo_region_translate (unobscured_region, - x, - y);
          cairo_region_translate (clip_region, - x, - y);

          meta_window_actor_set_unobscured_region (window_actor, unobscured_region);
          meta_window_actor_set_visible_region (window_actor, clip_region);

          if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
            {
              cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
              if (obscured_region)
                {
                  cairo_region_subtract (unobscured_region, obscured_region);
                  cairo_region_subtract (clip_region, obscured_region);
                }
            }

          meta_window_actor_set_visible_region_beneath (window_actor, clip_region);

          cairo_region_translate (unobscured_region, x, y);
          cairo_region_translate (clip_region, x, y);
        }
      else if (META_IS_BACKGROUND_ACTOR (child))
        {
          int x, y;

          if (!meta_actor_is_untransformed (child, &x, &y))
            continue;

          cairo_region_translate (clip_region, - x, - y);

          meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), clip_region);

          cairo_region_translate (clip_region, x, y);
        }
    }
}
Пример #2
0
/**
 * meta_cullable_cull_out_children:
 * @cullable: The #MetaCullable
 * @unobscured_region: The unobscured region, as passed into cull_out()
 * @clip_region: The clip region, as passed into cull_out()
 *
 * This is a helper method for actors that want to recurse over their
 * child actors, and cull them out.
 *
 * See #MetaCullable and meta_cullable_cull_out() for more details.
 */
void
meta_cullable_cull_out_children (MetaCullable   *cullable,
                                 cairo_region_t *unobscured_region,
                                 cairo_region_t *clip_region)
{
  ClutterActor *actor = CLUTTER_ACTOR (cullable);
  ClutterActor *child;
  ClutterActorIter iter;

  clutter_actor_iter_init (&iter, actor);
  while (clutter_actor_iter_prev (&iter, &child))
    {
      float x, y;
      gboolean needs_culling;

      if (!META_IS_CULLABLE (child))
        continue;

      needs_culling = (unobscured_region != NULL && clip_region != NULL);

      if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child))
        needs_culling = FALSE;

      /* If an actor has effects applied, then that can change the area
       * it paints and the opacity, so we no longer can figure out what
       * portion of the actor is obscured and what portion of the screen
       * it obscures, so we skip the actor.
       *
       * This has a secondary beneficial effect: if a ClutterOffscreenEffect
       * is applied to an actor, then our clipped redraws interfere with the
       * caching of the FBO - even if we only need to draw a small portion
       * of the window right now, ClutterOffscreenEffect may use other portions
       * of the FBO later. So, skipping actors with effects applied also
       * prevents these bugs.
       *
       * Theoretically, we should check clutter_actor_get_offscreen_redirect()
       * as well for the same reason, but omitted for simplicity in the
       * hopes that no-one will do that.
       */
      if (needs_culling && clutter_actor_has_effects (child))
        needs_culling = FALSE;

      if (needs_culling && !meta_actor_is_untransformed (child, NULL, NULL))
        needs_culling = FALSE;

      if (needs_culling)
        {
          clutter_actor_get_position (child, &x, &y);

          /* Temporarily move to the coordinate system of the actor */
          cairo_region_translate (unobscured_region, - x, - y);
          cairo_region_translate (clip_region, - x, - y);

          meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);

          cairo_region_translate (unobscured_region, x, y);
          cairo_region_translate (clip_region, x, y);
        }
      else
        {
          meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL);
        }
    }
}