// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/aura/window_occlusion_tracker.h"

#include "base/auto_reset.h"
#include "base/containers/adapters.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/env.h"
#include "ui/aura/window_occlusion_change_builder.h"
#include "ui/aura/window_tree_host.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"

namespace aura {

namespace {

// When one of these properties is animated, a window is considered non-occluded
// and cannot occlude other windows.
constexpr ui::LayerAnimationElement::AnimatableProperties
    kSkipWindowWhenPropertiesAnimated =
        ui::LayerAnimationElement::TRANSFORM |
        ui::LayerAnimationElement::BOUNDS | ui::LayerAnimationElement::OPACITY;

// When an animation ends for one of these properties, occlusion states might
// be affected. The end of an animation for a property in
// |kSkipWindowWhenPropertiesAnimated| might affect occlusion states because
// a window suddenly stops being excluded from occlusion computations. The
// end of a visibility animation might affect occlusion states because a
// window is suddenly considered drawn/not drawn.
constexpr ui::LayerAnimationElement::AnimatableProperties
    kOcclusionCanChangeWhenPropertyAnimationEnds =
        kSkipWindowWhenPropertiesAnimated |
        ui::LayerAnimationElement::VISIBILITY;

// Maximum number of times that MaybeComputeOcclusion() should have to recompute
// occlusion states before they become stable.
//
// TODO(fdoray): This can be changed to 2 once showing/hiding a WebContents
// doesn't cause a call to Show()/Hide() on the Window of a
// RenderWidgetHostViewAura. https://crbug.com/827268
constexpr int kMaxRecomputeOcclusion = 3;

bool WindowOrParentHasShape(Window* window) {
  if (window->layer()->alpha_shape())
    return true;
  if (window->parent())
    return WindowOrParentHasShape(window->parent());
  return false;
}

bool WindowHasOpaqueRegionsForOcclusion(Window* window) {
  return !window->opaque_regions_for_occlusion().empty();
}

// Returns the transform of |window| relative to its root.
// |parent_transform_relative_to_root| is the transform of |window->parent()|
// relative to its root.
gfx::Transform GetWindowTransformRelativeToRoot(
    Window* window,
    const gfx::Transform& parent_transform_relative_to_root,
    bool use_target_values) {
  if (window->IsRootWindow())
    return gfx::Transform();

  // Compute the transform relative to root by concatenating the transform
  // of this layer and the transform of the parent relative to root.
  // If |use_target_values| is true, use the target bounds and transform instead
  // of the true values.
  gfx::Transform translation;
  gfx::Transform transform_relative_to_root;
  if (use_target_values) {
    translation.Translate(
        static_cast<float>(window->layer()->GetTargetBounds().x()),
        static_cast<float>(window->layer()->GetTargetBounds().y()));
    transform_relative_to_root = window->layer()->GetTargetTransform();
  } else {
    translation.Translate(static_cast<float>(window->layer()->bounds().x()),
                          static_cast<float>(window->layer()->bounds().y()));
    transform_relative_to_root = window->layer()->transform();
  }
  transform_relative_to_root.ConcatTransform(translation);
  transform_relative_to_root.ConcatTransform(parent_transform_relative_to_root);
  return transform_relative_to_root;
}

SkIRect ComputeClippedAndTransformedBounds(
    const gfx::Rect& bounds,
    const gfx::Transform& transform_relative_to_root,
    const SkIRect* clipped_bounds) {
  DCHECK(transform_relative_to_root.Preserves2dAxisAlignment());
  gfx::RectF transformed_bounds(bounds);
  transform_relative_to_root.TransformRect(&transformed_bounds);
  SkIRect skirect_bounds =
      gfx::RectToSkIRect(gfx::ToEnclosedRect(transformed_bounds));
  // If necessary, clip the bounds.
  if (clipped_bounds && !skirect_bounds.intersect(*clipped_bounds))
    return SkIRect::MakeEmpty();
  return skirect_bounds;
}

// Returns the bounds of |window| relative to its |root|.
// |transform_relative_to_root| is the transform of |window| relative to its
// root. If |clipped_bounds| is not null, the returned bounds are clipped by it.
SkIRect GetWindowBoundsInRootWindow(
    Window* window,
    const gfx::Transform& transform_relative_to_root,
    const SkIRect* clipped_bounds,
    bool use_target_values) {
  // Compute the unclipped bounds of |window|.
  const gfx::Rect src_bounds =
      use_target_values ? window->layer()->GetTargetBounds() : window->bounds();
  return ComputeClippedAndTransformedBounds(
      gfx::Rect(src_bounds.size()), transform_relative_to_root, clipped_bounds);
}

// Returns the bounds that |window| should contribute to be used for occluding
// other windows. This is different to the bounds of the window if |window|
// has opaque regions for occlusion set. We need to use different sets of bounds
// for computing the occlusion of a window itself versus what it should
// contribute to occluding other windows because a translucent region should
// not be considered to occlude other windows, but must be covered by something
// opaque for it itself to be occluded.
SkIRect GetOpaqueBoundsInRootWindow(
    Window* window,
    const gfx::Transform& transform_relative_to_root,
    const SkIRect* clipped_bounds) {
  DCHECK(WindowHasOpaqueRegionsForOcclusion(window));
  // TODO: Currently, we only support one Rect in the opaque region.
  DCHECK_EQ(1u, window->opaque_regions_for_occlusion().size());

  // Don't let clients mark regions outside their window bounds as opaque.
  gfx::Rect opaque_region = window->opaque_regions_for_occlusion()[0];
  opaque_region.Intersect(window->bounds());
  return ComputeClippedAndTransformedBounds(
      opaque_region, transform_relative_to_root, clipped_bounds);
}

float GetLayerCombinedTargetOpacity(const ui::Layer* layer) {
  float opacity = layer->GetTargetOpacity();
  const ui::Layer* current = layer->parent();
  while (current) {
    opacity *= current->GetTargetOpacity();
    current = current->parent();
  }
  return opacity;
}

}  // namespace

WindowOcclusionTracker::ScopedPause::ScopedPause() {
  Env::GetInstance()->PauseWindowOcclusionTracking();
}

WindowOcclusionTracker::ScopedPause::~ScopedPause() {
  Env::GetInstance()->UnpauseWindowOcclusionTracking();
}

WindowOcclusionTracker::ScopedExclude::ScopedExclude(Window* window)
    : window_(window) {
  window->AddObserver(this);
  Env::GetInstance()->GetWindowOcclusionTracker()->Exclude(window_);
}

WindowOcclusionTracker::ScopedExclude::~ScopedExclude() {
  Shutdown();
}

void WindowOcclusionTracker::ScopedExclude::OnWindowDestroying(Window* window) {
  DCHECK_EQ(window_, window);
  Shutdown();
}

void WindowOcclusionTracker::ScopedExclude::Shutdown() {
  if (window_) {
    window_->RemoveObserver(this);
    Env::GetInstance()->GetWindowOcclusionTracker()->Unexclude(window_);
    window_ = nullptr;
  }
}

WindowOcclusionTracker::ScopedForceVisible::ScopedForceVisible(Window* window)
    : window_(window) {
  window_->AddObserver(this);
  Env::GetInstance()->GetWindowOcclusionTracker()->ForceWindowVisible(window_);
}

WindowOcclusionTracker::ScopedForceVisible::~ScopedForceVisible() {
  Shutdown();
}

void WindowOcclusionTracker::ScopedForceVisible::OnWindowDestroying(
    Window* window) {
  DCHECK_EQ(window_, window);
  Shutdown();
}

void WindowOcclusionTracker::ScopedForceVisible::Shutdown() {
  if (window_) {
    window_->RemoveObserver(this);
    Env::GetInstance()->GetWindowOcclusionTracker()->RemoveForceWindowVisible(
        window_);
    window_ = nullptr;
  }
}

void WindowOcclusionTracker::Track(Window* window) {
  DCHECK(window);
  DCHECK(window != window->GetRootWindow());

  auto insert_result = tracked_windows_.insert({window, {}});
  if (!insert_result.second)
    return;

  if (!window_observer_.IsObserving(window))
    window_observer_.Add(window);
  if (window->GetRootWindow())
    TrackedWindowAddedToRoot(window);
}

WindowOcclusionTracker::OcclusionData
WindowOcclusionTracker::ComputeTargetOcclusionForWindow(Window* window) {
  // Compute the occlusion with target state, just for this window.
  // This doesn't update the occlusion states of any window, so we should only
  // require one pass.
  auto tracked_window_iter = tracked_windows_.find(window);
  DCHECK(tracked_window_iter != tracked_windows_.end());

  base::AutoReset<OcclusionData> auto_reset_occlusion_data(
      &tracked_window_iter->second, OcclusionData());
  DCHECK(!target_occlusion_window_);
  base::AutoReset<Window*> auto_reset_target_occlusion_window(
      &target_occlusion_window_, window);

  Window* root_window = window->GetRootWindow();
  SkRegion occluded_region;
  RecomputeOcclusionImpl(root_window, gfx::Transform(), nullptr,
                         &occluded_region);

  return tracked_window_iter->second;
}

WindowOcclusionTracker::WindowOcclusionTracker() = default;

WindowOcclusionTracker::~WindowOcclusionTracker() = default;

bool WindowOcclusionTracker::OcclusionStatesMatch(
    const base::flat_map<Window*, OcclusionData>& tracked_windows) {
  for (const auto& tracked_window : tracked_windows) {
    if (tracked_window.second.occlusion_state !=
        tracked_window.first->occlusion_state())
      return false;
  }
  return true;
}

void WindowOcclusionTracker::MaybeComputeOcclusion() {
  if (num_pause_occlusion_tracking_ ||
      num_times_occlusion_recomputed_in_current_step_ != 0) {
    return;
  }

  base::AutoReset<int> auto_reset(
      &num_times_occlusion_recomputed_in_current_step_, 0);

  // Recompute occlusion states until either:
  // - They are stable, i.e. calling Window::SetOcclusionInfo() on all tracked
  //   windows does not provoke changes that could affect occlusion.
  // - Occlusion states have been recomputed
  // |kMaxComputeOcclusionIterationsBeforeStable|
  //   times.
  // If occlusion states have been recomputed
  // |kMaxComputeOcclusionIterationsBeforeStable| times and are still not
  // stable, iterate one last time to set the occlusion state of all tracked
  // windows based on IsVisible().
  while (num_times_occlusion_recomputed_in_current_step_ <=
         kMaxRecomputeOcclusion) {
    const bool exceeded_max_num_times_occlusion_recomputed =
        num_times_occlusion_recomputed_in_current_step_ ==
        kMaxRecomputeOcclusion;
    bool found_dirty_root = false;

    // Compute occlusion states and store them in |tracked_windows_|. Do not
    // call Window::SetOcclusionInfo() in this phase to prevent changes to the
    // window tree while it is being traversed.
    for (auto& root_window_pair : root_windows_) {
      if (root_window_pair.second.dirty) {
        found_dirty_root = true;
        root_window_pair.second.dirty = false;
        if (!exceeded_max_num_times_occlusion_recomputed) {
          Window* root_window = root_window_pair.first;
          if (root_window_pair.second.occlusion_state ==
              Window::OcclusionState::OCCLUDED) {
            SetWindowAndDescendantsAreOccluded(
                root_window, /* is_occluded */ true, root_window->IsVisible());
          } else {
            SkRegion occluded_region;
            RecomputeOcclusionImpl(root_window, gfx::Transform(), nullptr,
                                   &occluded_region);
          }
        }
      }
    }

    if (!found_dirty_root)
      break;

    ++num_times_occlusion_recomputed_;
    ++num_times_occlusion_recomputed_in_current_step_;

    std::unique_ptr<WindowOcclusionChangeBuilder> change_builder =
        occlusion_change_builder_factory_
            ? occlusion_change_builder_factory_.Run()
            : WindowOcclusionChangeBuilder::Create();
    for (auto& it : tracked_windows_) {
      Window* window = it.first;
      if (it.second.occlusion_state == Window::OcclusionState::UNKNOWN)
        continue;

      // Fallback to VISIBLE/HIDDEN if the maximum number of times that
      // occlusion can be recomputed was exceeded.
      if (exceeded_max_num_times_occlusion_recomputed) {
        if (WindowIsVisible(window))
          it.second.occlusion_state = Window::OcclusionState::VISIBLE;
        else
          it.second.occlusion_state = Window::OcclusionState::HIDDEN;
        it.second.occluded_region = SkRegion();
      }

      change_builder->Add(window, it.second.occlusion_state,
                          it.second.occluded_region);
    }
  }

  // Sanity check: Occlusion states in |tracked_windows_| should match those
  // returned by Window::occlusion_state().
  DCHECK(OcclusionStatesMatch(tracked_windows_));
}

bool WindowOcclusionTracker::RecomputeOcclusionImpl(
    Window* window,
    const gfx::Transform& parent_transform_relative_to_root,
    const SkIRect* clipped_bounds,
    SkRegion* occluded_region) {
  DCHECK(window);

  const bool force_visible = WindowIsForcedVisible(window);
  // This does not use Window::IsVisible() as that returns the wrong thing for
  // any ancestors that are forced visible.
  const bool is_visible =
      force_visible ||
      (ShouldUseTargetValues() ? window->layer()->GetTargetVisibility()
                               : window->layer()->visible());
  if (!is_visible) {
    SetWindowAndDescendantsAreOccluded(window, /* is_occluded */ true,
                                       /* is_parent_visible */ true);
    return false;
  }

  if (WindowIsAnimated(window) || WindowIsExcluded(window)) {
    SetWindowAndDescendantsAreOccluded(window, /* is_occluded */ false,
                                       /* is_parent_visible */ true);
    return true;
  }

  // Compute window bounds.
  const gfx::Transform transform_relative_to_root =
      GetWindowTransformRelativeToRoot(
          window, parent_transform_relative_to_root, ShouldUseTargetValues());
  if (!transform_relative_to_root.Preserves2dAxisAlignment()) {
    // For simplicity, windows that are not axis-aligned are considered
    // unoccluded and do not occlude other windows.
    SetWindowAndDescendantsAreOccluded(window, /* is_occluded */ false,
                                       /* is_parent_visible */ true);
    return true;
  }

  const SkIRect window_bounds = GetWindowBoundsInRootWindow(
      window, transform_relative_to_root,
      force_visible ? nullptr : clipped_bounds, ShouldUseTargetValues());

  // Compute children occlusion states.
  const SkIRect* clipped_bounds_for_children =
      window->layer()->GetMasksToBounds() ? &window_bounds : clipped_bounds;
  bool has_visible_child = false;
  SkRegion occluded_region_before_traversing_children = *occluded_region;
  // Windows that are forced visible are always considered visible, so have no
  // clip.
  SkRegion region_for_forced_visible_windows;
  SkRegion* occluded_region_for_children =
      force_visible ? &region_for_forced_visible_windows : occluded_region;
  for (auto* child : base::Reversed(window->children())) {
    has_visible_child |= RecomputeOcclusionImpl(
        child, transform_relative_to_root, clipped_bounds_for_children,
        occluded_region_for_children);
  }

  // Window is fully occluded.
  if (!force_visible && occluded_region->contains(window_bounds) &&
      !has_visible_child) {
    SetOccluded(window, /* is_occluded */ true, /* is_parent_visible */ true,
                SkRegion());
    return false;
  }

  // Window is partially occluded or unoccluded. Windows that are forced visible
  // are considered completely visible (so they get an empty SkRegion()).
  SetOccluded(
      window, false, /* is_parent_visible */ true,
      force_visible ? SkRegion() : occluded_region_before_traversing_children);

  if (!force_visible && VisibleWindowCanOccludeOtherWindows(window)) {
    const SkIRect occlusion_bounds =
        WindowHasOpaqueRegionsForOcclusion(window)
            ? GetOpaqueBoundsInRootWindow(window, transform_relative_to_root,
                                          clipped_bounds)
            : window_bounds;
    occluded_region->op(occlusion_bounds, SkRegion::kUnion_Op);
  }
  return true;
}

bool WindowOcclusionTracker::VisibleWindowCanOccludeOtherWindows(
    Window* window) const {
  DCHECK(window->layer());
  const float combined_opacity =
      ShouldUseTargetValues() ? GetLayerCombinedTargetOpacity(window->layer())
                              : window->layer()->GetCombinedOpacity();
  return (!window->transparent() && WindowHasContent(window) &&
          combined_opacity == 1.0f &&
          // For simplicity, a shaped window is not considered opaque.
          !WindowOrParentHasShape(window)) ||
         WindowHasOpaqueRegionsForOcclusion(window);
}

bool WindowOcclusionTracker::WindowHasContent(Window* window) const {
  if (window->layer()->type() != ui::LAYER_NOT_DRAWN)
    return true;

  if (window_has_content_callback_)
    return window_has_content_callback_.Run(window);

  return false;
}

void WindowOcclusionTracker::CleanupAnimatedWindows() {
  base::EraseIf(animated_windows_, [=](Window* window) {
    ui::LayerAnimator* const animator = window->layer()->GetAnimator();
    if (animator->IsAnimatingOnePropertyOf(
            kOcclusionCanChangeWhenPropertyAnimationEnds))
      return false;
    animator->RemoveObserver(this);
    MarkRootWindowAsDirty(window->GetRootWindow());
    return true;
  });
}

bool WindowOcclusionTracker::MaybeObserveAnimatedWindow(Window* window) {
  // MaybeObserveAnimatedWindow() is called when OnWindowBoundsChanged(),
  // OnWindowTransformed() or OnWindowOpacitySet() is called with
  // ui::PropertyChangeReason::FROM_ANIMATION. Despite that, if the animation is
  // ending, the IsAnimatingOnePropertyOf() call below may return false. It is
  // important not to register an observer in that case because it would never
  // be notified.
  ui::LayerAnimator* const animator = window->layer()->GetAnimator();
  if (animator->IsAnimatingOnePropertyOf(
          kOcclusionCanChangeWhenPropertyAnimationEnds)) {
    const auto insert_result = animated_windows_.insert(window);
    if (insert_result.second) {
      animator->AddObserver(this);
      return true;
    }
  }
  return false;
}

void WindowOcclusionTracker::SetWindowAndDescendantsAreOccluded(
    Window* window,
    bool is_occluded,
    bool is_parent_visible) {
  const bool force_visible = WindowIsForcedVisible(window);
  const bool is_visible =
      force_visible || (is_parent_visible && window->layer()->visible());
  is_occluded = is_occluded && !force_visible;
  SetOccluded(window, is_occluded, is_visible, SkRegion());
  for (Window* child_window : window->children())
    SetWindowAndDescendantsAreOccluded(child_window, is_occluded, is_visible);
}

void WindowOcclusionTracker::SetOccluded(Window* window,
                                         bool is_occluded,
                                         bool is_parent_visible,
                                         const SkRegion& occluded_region) {
  // Don't modify occlusion state if we're just computing occlusion for one
  // window.
  if (target_occlusion_window_ != nullptr && target_occlusion_window_ != window)
    return;
  auto tracked_window = tracked_windows_.find(window);
  if (tracked_window == tracked_windows_.end())
    return;

  // Set the occluded region of the window.
  tracked_window->second.occluded_region = occluded_region;

  const bool is_visible = WindowIsForcedVisible(window) ||
                          (is_parent_visible && window->layer()->visible());
  if (!is_visible)
    tracked_window->second.occlusion_state = Window::OcclusionState::HIDDEN;
  else if (is_occluded)
    tracked_window->second.occlusion_state = Window::OcclusionState::OCCLUDED;
  else
    tracked_window->second.occlusion_state = Window::OcclusionState::VISIBLE;

  DCHECK(tracked_window->second.occlusion_state ==
             Window::OcclusionState::VISIBLE ||
         tracked_window->second.occluded_region.isEmpty());
}

bool WindowOcclusionTracker::WindowIsTracked(Window* window) const {
  return base::Contains(tracked_windows_, window);
}

bool WindowOcclusionTracker::WindowIsAnimated(Window* window) const {
  return !ShouldUseTargetValues() &&
         base::Contains(animated_windows_, window) &&
         window->layer()->GetAnimator()->IsAnimatingOnePropertyOf(
             kSkipWindowWhenPropertiesAnimated);
}

bool WindowOcclusionTracker::WindowIsExcluded(Window* window) const {
  return base::Contains(excluded_windows_, window);
}

bool WindowOcclusionTracker::WindowIsVisible(Window* window) const {
  if (forced_visible_count_map_.empty())
    return window->IsVisible();
  Window* w = window;
  Window* last = w;
  while (w) {
    if (!WindowIsForcedVisible(window)) {
      if (ShouldUseTargetValues() && !w->layer()->GetTargetVisibility())
        return false;
      if (!ShouldUseTargetValues() && !w->layer()->visible())
        return false;
    }
    last = w;
    w = w->parent();
  }
  return last->IsRootWindow();
}

bool WindowOcclusionTracker::WindowIsForcedVisible(Window* window) const {
  return forced_visible_count_map_.count(window) > 0;
}

template <typename Predicate>
void WindowOcclusionTracker::MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(
    Window* window,
    Predicate predicate) {
  Window* root_window = window->GetRootWindow();
  if (!root_window)
    return;
  auto root_window_state_it = root_windows_.find(root_window);

  // This may be called if a WindowObserver or a LayoutManager changes |window|
  // after Window::AddChild() has added it to a new root but before
  // OnWindowAddedToRootWindow() is called on |this|. In that case, do nothing
  // here and rely on OnWindowAddedToRootWindow() to mark the new root as dirty.
  if (root_window_state_it == root_windows_.end()) {
    DCHECK(WindowIsTracked(window));
    return;
  }

  if (root_window_state_it->second.dirty)
    return;
  if (predicate()) {
    MarkRootWindowStateAsDirty(&root_window_state_it->second);
    MaybeComputeOcclusion();
  }
}

void WindowOcclusionTracker::MarkRootWindowStateAsDirty(
    RootWindowState* root_window_state) {
  // If a root window is marked as dirty and occlusion states have already been
  // recomputed |kMaxRecomputeOcclusion| times, it means that they are not
  // stabilizing.
  DCHECK_LT(num_times_occlusion_recomputed_in_current_step_,
            kMaxRecomputeOcclusion);

  root_window_state->dirty = true;
}

bool WindowOcclusionTracker::MarkRootWindowAsDirty(Window* root_window) {
  auto root_window_state_it = root_windows_.find(root_window);
  if (root_window_state_it == root_windows_.end())
    return false;
  MarkRootWindowStateAsDirty(&root_window_state_it->second);
  return true;
}

bool WindowOcclusionTracker::WindowOrParentIsAnimated(Window* window) const {
  while (window && !WindowIsAnimated(window))
    window = window->parent();
  return window != nullptr;
}

bool WindowOcclusionTracker::WindowOrDescendantIsTrackedAndVisible(
    Window* window) const {
  if (!WindowIsVisible(window))
    return false;
  if (WindowIsTracked(window))
    return true;
  for (Window* child_window : window->children()) {
    if (WindowOrDescendantIsTrackedAndVisible(child_window))
      return true;
  }
  return false;
}

bool WindowOcclusionTracker::WindowOrDescendantCanOccludeOtherWindows(
    Window* window,
    bool assume_parent_opaque,
    bool assume_window_opaque) const {
  const bool parent_window_is_opaque =
      assume_parent_opaque || !window->parent() ||
      window->parent()->layer()->GetCombinedOpacity() == 1.0f;
  const bool window_is_opaque =
      parent_window_is_opaque &&
      (assume_window_opaque || window->layer()->opacity() == 1.0f);

  if (!WindowIsVisible(window) || !window->layer() || !window_is_opaque ||
      WindowIsAnimated(window)) {
    return false;
  }
  if ((!window->transparent() && WindowHasContent(window)) ||
      WindowHasOpaqueRegionsForOcclusion(window)) {
    return true;
  }
  for (Window* child_window : window->children()) {
    if (WindowOrDescendantCanOccludeOtherWindows(child_window, true))
      return true;
  }
  return false;
}

bool WindowOcclusionTracker::WindowOpacityChangeMayAffectOcclusionStates(
    Window* window) const {
  // Changing the opacity of a window has no effect on the occlusion state of
  // the window or its children. It can however affect the occlusion state of
  // other windows in the tree if it is visible and not animated (animated
  // windows aren't considered in occlusion computations), unless it is
  // excluded.
  return WindowIsVisible(window) && !WindowOrParentIsAnimated(window) &&
         !WindowIsExcluded(window);
}

bool WindowOcclusionTracker::WindowMoveMayAffectOcclusionStates(
    Window* window) const {
  return !WindowOrParentIsAnimated(window) && !WindowIsExcluded(window) &&
         (WindowOrDescendantCanOccludeOtherWindows(window) ||
          WindowOrDescendantIsTrackedAndVisible(window));
}

void WindowOcclusionTracker::TrackedWindowAddedToRoot(Window* window) {
  Window* const root_window = window->GetRootWindow();
  DCHECK(root_window);
  RootWindowState& root_window_state = root_windows_[root_window];
  ++root_window_state.num_tracked_windows;
  MarkRootWindowStateAsDirty(&root_window_state);

  // It's only useful to track the host if |window| is the first tracked window
  // under |root_window|.  All windows under the same root have the same host.
  if (root_window_state.num_tracked_windows == 1) {
    AddObserverToWindowAndDescendants(root_window);
    auto* host = root_window->GetHost();
    if (host) {
      host->AddObserver(this);
      host->EnableNativeWindowOcclusionTracking();
    }
  }
  MaybeComputeOcclusion();
}

void WindowOcclusionTracker::TrackedWindowRemovedFromRoot(Window* window) {
  Window* const root_window = window->GetRootWindow();
  DCHECK(root_window);
  auto root_window_state_it = root_windows_.find(root_window);
  DCHECK(root_window_state_it != root_windows_.end());
  --root_window_state_it->second.num_tracked_windows;
  if (root_window_state_it->second.num_tracked_windows == 0) {
    RemoveObserverFromWindowAndDescendants(root_window);
    root_windows_.erase(root_window_state_it);
    root_window->GetHost()->RemoveObserver(this);
    root_window->GetHost()->DisableNativeWindowOcclusionTracking();
  }
}

void WindowOcclusionTracker::RemoveObserverFromWindowAndDescendants(
    Window* window) {
  if (WindowIsTracked(window)) {
    DCHECK(window_observer_.IsObserving(window));
  } else {
    if (window_observer_.IsObserving(window))
      window_observer_.Remove(window);
    window->layer()->GetAnimator()->RemoveObserver(this);
    animated_windows_.erase(window);
  }
  for (Window* child_window : window->children())
    RemoveObserverFromWindowAndDescendants(child_window);
}

void WindowOcclusionTracker::AddObserverToWindowAndDescendants(Window* window) {
  if (WindowIsTracked(window)) {
    DCHECK(window_observer_.IsObserving(window));
  } else {
    DCHECK(!window_observer_.IsObserving(window));
    window_observer_.Add(window);
  }
  for (Window* child_window : window->children())
    AddObserverToWindowAndDescendants(child_window);
}

void WindowOcclusionTracker::Pause() {
  ++num_pause_occlusion_tracking_;
}

void WindowOcclusionTracker::Unpause() {
  --num_pause_occlusion_tracking_;
  DCHECK_GE(num_pause_occlusion_tracking_, 0);
  MaybeComputeOcclusion();
}

void WindowOcclusionTracker::Exclude(Window* window) {
  // If threre is a valid use case to exclude the same window twice
  // (e.g. independent clients may try to exclude the same window),
  // introduce the count.
  DCHECK(!WindowIsExcluded(window));
  excluded_windows_.insert(window);
  if (WindowIsVisible(window)) {
    if (MarkRootWindowAsDirty(window->GetRootWindow()))
      MaybeComputeOcclusion();
  }
}

void WindowOcclusionTracker::Unexclude(Window* window) {
  DCHECK(WindowIsExcluded(window));
  excluded_windows_.erase(window);
  if (WindowIsVisible(window)) {
    if (MarkRootWindowAsDirty(window->GetRootWindow()))
      MaybeComputeOcclusion();
  }
}

void WindowOcclusionTracker::ForceWindowVisible(Window* window) {
  if (forced_visible_count_map_[window]++ == 0) {
    Window* root_window = window->GetRootWindow();
    if (root_window && MarkRootWindowAsDirty(root_window))
      MaybeComputeOcclusion();
  }
}

void WindowOcclusionTracker::RemoveForceWindowVisible(Window* window) {
  auto iter = forced_visible_count_map_.find(window);
  DCHECK(iter != forced_visible_count_map_.end());
  if (--iter->second == 0u) {
    forced_visible_count_map_.erase(iter);
    Window* root_window = window->GetRootWindow();
    if (root_window && MarkRootWindowAsDirty(root_window))
      MaybeComputeOcclusion();
  }
}

bool WindowOcclusionTracker::ShouldUseTargetValues() const {
  return target_occlusion_window_;
}

void WindowOcclusionTracker::OnLayerAnimationEnded(
    ui::LayerAnimationSequence* sequence) {
  CleanupAnimatedWindows();
  MaybeComputeOcclusion();
}

void WindowOcclusionTracker::OnLayerAnimationAborted(
    ui::LayerAnimationSequence* sequence) {
  CleanupAnimatedWindows();
  MaybeComputeOcclusion();
}

void WindowOcclusionTracker::OnLayerAnimationScheduled(
    ui::LayerAnimationSequence* sequence) {}

void WindowOcclusionTracker::OnWindowHierarchyChanged(
    const HierarchyChangeParams& params) {
  Window* const window = params.target;
  Window* const root_window = window->GetRootWindow();
  if (root_window && base::Contains(root_windows_, root_window) &&
      !window_observer_.IsObserving(window)) {
    AddObserverToWindowAndDescendants(window);
  }
}

void WindowOcclusionTracker::OnWindowAdded(Window* window) {
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(
      window, [=]() { return WindowMoveMayAffectOcclusionStates(window); });
}

void WindowOcclusionTracker::OnWillRemoveWindow(Window* window) {
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return !WindowOrParentIsAnimated(window) &&
           WindowOrDescendantCanOccludeOtherWindows(window);
  });
}

void WindowOcclusionTracker::OnWindowVisibilityChanged(Window* window,
                                                       bool visible) {
  MaybeObserveAnimatedWindow(window);
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    // A child isn't visible when its parent isn't IsVisible(). Therefore, there
    // is no need to compute occlusion when Show() or Hide() is called on a
    // window with a hidden parent.
    return (!window->parent() || WindowIsVisible(window->parent())) &&
           !WindowOrParentIsAnimated(window);
  });
}

void WindowOcclusionTracker::OnWindowBoundsChanged(
    Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds,
    ui::PropertyChangeReason reason) {
  // Call MaybeObserveAnimatedWindow() outside the lambda so that the window can
  // be marked as animated even when its root is dirty.
  const bool animation_started =
      (reason == ui::PropertyChangeReason::FROM_ANIMATION) &&
      MaybeObserveAnimatedWindow(window);
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return animation_started || WindowMoveMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnWindowOpacitySet(
    Window* window,
    ui::PropertyChangeReason reason) {
  // Call MaybeObserveAnimatedWindow() outside the lambda so that the window can
  // be marked as animated even when its root is dirty.
  const bool animation_started =
      (reason == ui::PropertyChangeReason::FROM_ANIMATION) &&
      MaybeObserveAnimatedWindow(window);
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return animation_started ||
           WindowOpacityChangeMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnWindowAlphaShapeSet(Window* window) {
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return WindowOpacityChangeMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnWindowTransparentChanged(Window* window) {
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return WindowOpacityChangeMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnWindowTransformed(
    Window* window,
    ui::PropertyChangeReason reason) {
  // Call MaybeObserveAnimatedWindow() outside the lambda so that the window can
  // be marked as animated even when its root is dirty.
  const bool animation_started =
      (reason == ui::PropertyChangeReason::FROM_ANIMATION) &&
      MaybeObserveAnimatedWindow(window);
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return animation_started || WindowMoveMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnWindowStackingChanged(Window* window) {
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(
      window, [=]() { return WindowMoveMayAffectOcclusionStates(window); });
}

void WindowOcclusionTracker::OnWindowDestroyed(Window* window) {
  DCHECK(!window->GetRootWindow() || (window == window->GetRootWindow()));
  tracked_windows_.erase(window);
  window_observer_.Remove(window);
  // Animations should be completed or aborted before a window is destroyed.
  DCHECK(!window->layer()->GetAnimator()->IsAnimatingOnePropertyOf(
      kOcclusionCanChangeWhenPropertyAnimationEnds));
  // |window| must be removed from |animated_windows_| to prevent an invalid
  // access in CleanupAnimatedWindows() if |window| is being destroyed from a
  // LayerAnimationObserver after an animation has ended but before |this| has
  // been notified.
  animated_windows_.erase(window);
}

void WindowOcclusionTracker::OnWindowAddedToRootWindow(Window* window) {
  DCHECK(window->GetRootWindow());
  if (WindowIsTracked(window))
    TrackedWindowAddedToRoot(window);
}

void WindowOcclusionTracker::OnWindowRemovingFromRootWindow(Window* window,
                                                            Window* new_root) {
  DCHECK(window->GetRootWindow());
  if (WindowIsTracked(window))
    TrackedWindowRemovedFromRoot(window);
  RemoveObserverFromWindowAndDescendants(window);
}

void WindowOcclusionTracker::OnWindowLayerRecreated(Window* window) {
  ui::LayerAnimator* animator = window->layer()->GetAnimator();

  // Recreating the layer may have stopped animations.
  if (animator->IsAnimatingOnePropertyOf(
          kOcclusionCanChangeWhenPropertyAnimationEnds))
    return;

  size_t num_removed = animated_windows_.erase(window);
  if (num_removed == 0)
    return;

  animator->RemoveObserver(this);
  if (MarkRootWindowAsDirty(window->GetRootWindow()))
    MaybeComputeOcclusion();
}

void WindowOcclusionTracker::OnWindowOpaqueRegionsForOcclusionChanged(
    Window* window) {
  // If the opaque regions for occlusion change, the occlusion state may be
  // affected if the effective opacity of the window changes (e.g. clearing the
  // regions for occlusion), or if their bounds change.
  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
    return WindowOpacityChangeMayAffectOcclusionStates(window) ||
           WindowMoveMayAffectOcclusionStates(window);
  });
}

void WindowOcclusionTracker::OnOcclusionStateChanged(
    WindowTreeHost* host,
    Window::OcclusionState new_state) {
  UMA_HISTOGRAM_ENUMERATION("WindowOcclusionChanged", new_state);
  Window* root_window = host->window();
  auto root_window_state_it = root_windows_.find(root_window);
  if (root_window_state_it != root_windows_.end())
    root_window_state_it->second.occlusion_state = new_state;

  MarkRootWindowAsDirty(root_window);
  MaybeComputeOcclusion();
}

}  // namespace aura
