// 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_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/gfx/geometry/safe_integer_conversions.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;

// 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 aura::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;
}

// 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(
    aura::Window* window,
    const gfx::Transform& parent_transform_relative_to_root) {
  if (window->IsRootWindow())
    return gfx::Transform();

  // Concatenate |parent_transform_relative_to_root| to the result of
  // GetTargetTransformRelativeTo(parent_layer) rather than simply calling
  // GetTargetTransformRelativeTo(window->GetRootWindow()->layer()) to avoid
  // doing the same computations multiple times when traversing a window
  // hierarchy.
  ui::Layer* parent_layer = window->parent()->layer();
  gfx::Transform transform_relative_to_root;
  bool success = window->layer()->GetTargetTransformRelativeTo(
      parent_layer, &transform_relative_to_root);
  DCHECK(success);
  transform_relative_to_root.ConcatTransform(parent_transform_relative_to_root);
  return transform_relative_to_root;
}

// 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(
    aura::Window* window,
    const gfx::Transform& transform_relative_to_root,
    const SkIRect* clipped_bounds) {
  DCHECK(transform_relative_to_root.Preserves2dAxisAlignment());
  // Compute the unclipped bounds of |window|.
  gfx::RectF bounds(0.0f, 0.0f, static_cast<float>(window->bounds().width()),
                    static_cast<float>(window->bounds().height()));
  transform_relative_to_root.TransformRect(&bounds);
  SkIRect skirect_bounds = SkIRect::MakeXYWH(
      gfx::ToFlooredInt(bounds.x()), gfx::ToFlooredInt(bounds.y()),
      gfx::ToFlooredInt(bounds.width()), gfx::ToFlooredInt(bounds.height()));
  // If necessary, clip the bounds.
  if (clipped_bounds && !skirect_bounds.intersect(*clipped_bounds))
    return SkIRect::MakeEmpty();
  return skirect_bounds;
}

}  // namespace

WindowOcclusionTracker::ScopedPause::ScopedPause(Env* env) : env_(env) {
  env_->PauseWindowOcclusionTracking();
}

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

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

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

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

void WindowOcclusionTracker::ScopedExclude::Shutdown() {
  if (window_) {
    window_->RemoveObserver(this);
    window_->env()->GetWindowOcclusionTracker()->Unexclude(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::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) {
          SkRegion occluded_region;
          RecomputeOcclusionImpl(root_window_pair.first, gfx::Transform(),
                                 nullptr, &occluded_region);
        }
      }
    }

    if (!found_dirty_root)
      break;

    ++num_times_occlusion_recomputed_;
    ++num_times_occlusion_recomputed_in_current_step_;

    // Call Window::SetOcclusionInfo() on tracked windows. A WindowDelegate may
    // change the window tree in response to this.
    WindowTracker tracked_windows_list;
    for (const auto& tracked_window : tracked_windows_)
      tracked_windows_list.Add(tracked_window.first);

    while (!tracked_windows_list.windows().empty()) {
      Window* window = tracked_windows_list.Pop();
      auto it = tracked_windows_.find(window);
      if (it != tracked_windows_.end() &&
          it->second.occlusion_state != Window::OcclusionState::UNKNOWN) {
        // 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 (window->IsVisible()) {
            it->second.occlusion_state = Window::OcclusionState::VISIBLE;
          } else {
            it->second.occlusion_state = Window::OcclusionState::HIDDEN;
          }
          it->second.occluded_region = SkRegion();
        }

        window->SetOcclusionInfo(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);

  if (!window->IsVisible()) {
    SetWindowAndDescendantsAreOccluded(window, true);
    return false;
  }

  if (WindowIsAnimated(window) || WindowIsExcluded(window)) {
    SetWindowAndDescendantsAreOccluded(window, false);
    return true;
  }

  // Compute window bounds.
  const gfx::Transform transform_relative_to_root =
      GetWindowTransformRelativeToRoot(window,
                                       parent_transform_relative_to_root);
  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, false);
    return true;
  }
  const SkIRect window_bounds = GetWindowBoundsInRootWindow(
      window, transform_relative_to_root, clipped_bounds);

  // 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;
  for (auto* child : base::Reversed(window->children())) {
    has_visible_child |=
        RecomputeOcclusionImpl(child, transform_relative_to_root,
                               clipped_bounds_for_children, occluded_region);
  }

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

  // Window is partially occluded or unoccluded.
  SetOccluded(window, false, occluded_region_before_traversing_children);

  if (VisibleWindowIsOpaque(window))
    occluded_region->op(window_bounds, SkRegion::kUnion_Op);
  return true;
}

bool WindowOcclusionTracker::VisibleWindowIsOpaque(Window* window) const {
  DCHECK(window->IsVisible());
  DCHECK(window->layer());
  return !window->transparent() && WindowHasContent(window) &&
         window->layer()->GetCombinedOpacity() == 1.0f &&
         // For simplicity, a shaped window is not considered opaque.
         !WindowOrParentHasShape(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(kSkipWindowWhenPropertiesAnimated))
      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(kSkipWindowWhenPropertiesAnimated)) {
    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) {
  SetOccluded(window, is_occluded, SkRegion());
  for (Window* child_window : window->children())
    SetWindowAndDescendantsAreOccluded(child_window, is_occluded);
}

void WindowOcclusionTracker::SetOccluded(Window* window,
                                         bool is_occluded,
                                         const SkRegion& occluded_region) {
  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;

  if (!window->IsVisible())
    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::ContainsKey(tracked_windows_, window);
}

bool WindowOcclusionTracker::WindowIsAnimated(Window* window) const {
  return base::ContainsKey(animated_windows_, window);
}

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

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(aura::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 (!window->IsVisible())
    return false;
  if (WindowIsTracked(window))
    return true;
  for (Window* child_window : window->children()) {
    if (WindowOrDescendantIsTrackedAndVisible(child_window))
      return true;
  }
  return false;
}

bool WindowOcclusionTracker::WindowOrDescendantIsOpaque(
    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 (!window->IsVisible() || !window->layer() || !window_is_opaque ||
      WindowIsAnimated(window)) {
    return false;
  }
  if (!window->transparent() && WindowHasContent(window))
    return true;
  for (Window* child_window : window->children()) {
    if (WindowOrDescendantIsOpaque(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 window->IsVisible() && !WindowOrParentIsAnimated(window) &&
         !WindowIsExcluded(window);
}

bool WindowOcclusionTracker::WindowMoveMayAffectOcclusionStates(
    Window* window) const {
  return !WindowOrParentIsAnimated(window) && !WindowIsExcluded(window) &&
         (WindowOrDescendantIsOpaque(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 (window->IsVisible()) {
    if (MarkRootWindowAsDirty(window->GetRootWindow()))
      MaybeComputeOcclusion();
  }
}

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

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::ContainsKey(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) &&
           WindowOrDescendantIsOpaque(window);
  });
}

void WindowOcclusionTracker::OnWindowVisibilityChanged(Window* window,
                                                       bool visible) {
  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() || window->parent()->IsVisible()) &&
           !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::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(
      kSkipWindowWhenPropertiesAnimated));
  // |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(kSkipWindowWhenPropertiesAnimated))
    return;

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

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

void WindowOcclusionTracker::OnOcclusionStateChanged(
    WindowTreeHost* host,
    aura::Window::OcclusionState new_state) {
  UMA_HISTOGRAM_ENUMERATION("WindowOcclusionChanged", new_state);
}

}  // namespace aura
