Commit 8dccc2d4 authored by Eliot Courtney's avatar Eliot Courtney Committed by Commit Bot

Track occluded region in WindowOcclusionTracker.

We would like to automatically trigger Picture-in-Picture when a certain amount
of the window is occluded. To do this, we need a way to know how much of a
window is occluded by other windows. This occlusion could come from multiple
windows, and an occlusion tracker for aura already exists. This CL extends the
existing occlusion tracking functionality to also track an occluded region for
tracked windows.


Bug: 883157
Bug: 841886
Bug: b/112668686
Bug: b/110011377
Test: unit test
Change-Id: I0d6618ab05109cc46af0cfd72ecc5cbca2f200d4
Reviewed-on: https://chromium-review.googlesource.com/c/1179433
Commit-Queue: Eliot Courtney <edcourtney@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604532}
parent b5f31e6c
...@@ -1127,7 +1127,8 @@ void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) { ...@@ -1127,7 +1127,8 @@ void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
} }
void WebContentsViewAura::OnWindowOcclusionChanged( void WebContentsViewAura::OnWindowOcclusionChanged(
aura::Window::OcclusionState occlusion_state) { aura::Window::OcclusionState occlusion_state,
const SkRegion&) {
UpdateWebContentsVisibility(); UpdateWebContentsVisibility();
} }
......
...@@ -185,8 +185,8 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -185,8 +185,8 @@ class CONTENT_EXPORT WebContentsViewAura
void OnWindowDestroying(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override;
void OnWindowDestroyed(aura::Window* window) override; void OnWindowDestroyed(aura::Window* window) override;
void OnWindowTargetVisibilityChanged(bool visible) override; void OnWindowTargetVisibilityChanged(bool visible) override;
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(aura::Window::OcclusionState occlusion_state,
aura::Window::OcclusionState occlusion_state) override; const SkRegion&) override;
bool HasHitTestMask() const override; bool HasHitTestMask() const override;
void GetHitTestMask(gfx::Path* mask) const override; void GetHitTestMask(gfx::Path* mask) const override;
......
...@@ -88,8 +88,10 @@ void WindowDelegateImpl::OnWindowDestroyed(aura::Window* window) { ...@@ -88,8 +88,10 @@ void WindowDelegateImpl::OnWindowDestroyed(aura::Window* window) {
void WindowDelegateImpl::OnWindowTargetVisibilityChanged(bool visible) {} void WindowDelegateImpl::OnWindowTargetVisibilityChanged(bool visible) {}
void WindowDelegateImpl::OnWindowOcclusionChanged( void WindowDelegateImpl::OnWindowOcclusionChanged(
aura::Window::OcclusionState occlusion_state) { aura::Window::OcclusionState occlusion_state,
const SkRegion&) {
ServerWindow* const server_window = ServerWindow::GetMayBeNull(window_); ServerWindow* const server_window = ServerWindow::GetMayBeNull(window_);
// TODO: Send occluded region.
if (server_window) if (server_window)
server_window->owning_window_tree()->SendOcclusionState(window_); server_window->owning_window_tree()->SendOcclusionState(window_);
} }
......
...@@ -43,8 +43,8 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowDelegateImpl ...@@ -43,8 +43,8 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowDelegateImpl
void OnWindowDestroying(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override;
void OnWindowDestroyed(aura::Window* window) override; void OnWindowDestroyed(aura::Window* window) override;
void OnWindowTargetVisibilityChanged(bool visible) override; void OnWindowTargetVisibilityChanged(bool visible) override;
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(aura::Window::OcclusionState occlusion_state,
aura::Window::OcclusionState occlusion_state) override; const SkRegion& occluded_region) override;
bool HasHitTestMask() const override; bool HasHitTestMask() const override;
void GetHitTestMask(gfx::Path* mask) const override; void GetHitTestMask(gfx::Path* mask) const override;
......
...@@ -791,7 +791,8 @@ void WindowPortMus::UpdateOcclusionState(Window::OcclusionState new_state) { ...@@ -791,7 +791,8 @@ void WindowPortMus::UpdateOcclusionState(Window::OcclusionState new_state) {
occlusion_state_before_hidden_.reset(); occlusion_state_before_hidden_.reset();
} }
window_->SetOcclusionState(new_state); // TODO: Support occlusion region tracking. See crbug.com/900568.
window_->SetOcclusionInfo(new_state, SkRegion());
} }
void WindowPortMus::UpdateOcclusionStateAfterVisiblityChange(bool visible) { void WindowPortMus::UpdateOcclusionStateAfterVisiblityChange(bool visible) {
......
...@@ -887,11 +887,14 @@ void Window::SetVisible(bool visible) { ...@@ -887,11 +887,14 @@ void Window::SetVisible(bool visible) {
NotifyWindowVisibilityChanged(this, visible); NotifyWindowVisibilityChanged(this, visible);
} }
void Window::SetOcclusionState(OcclusionState occlusion_state) { void Window::SetOcclusionInfo(OcclusionState occlusion_state,
if (occlusion_state != occlusion_state_) { const SkRegion& occluded_region) {
if (occlusion_state != occlusion_state_ ||
occluded_region_ != occluded_region) {
occlusion_state_ = occlusion_state; occlusion_state_ = occlusion_state;
occluded_region_ = occluded_region;
if (delegate_) if (delegate_)
delegate_->OnWindowOcclusionChanged(occlusion_state); delegate_->OnWindowOcclusionChanged(occlusion_state, occluded_region);
} }
} }
......
...@@ -202,6 +202,18 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -202,6 +202,18 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// WindowOcclusionTracker::ScopedPause. // WindowOcclusionTracker::ScopedPause.
OcclusionState occlusion_state() const { return occlusion_state_; } OcclusionState occlusion_state() const { return occlusion_state_; }
// Returns the currently occluded region. This will be empty unless
// the window is tracked and has a VISIBLE occlusion state. That is,
// this is only maintained when the window is partially occluded. Further,
// this region may extend outside the window bounds. For performance reasons,
// the actual intersection with the window is not computed. The occluded
// region is the set of window rectangles that may occlude this window.
// Note that this means that the occluded region may be updated if one of
// those windows moves, even if the actual intersection of the occluded
// region with this window does not change. Clients may compute the actual
// intersection region if necessary.
const SkRegion& occluded_region() const { return occluded_region_; }
// Returns the window's bounds in root window's coordinates. // Returns the window's bounds in root window's coordinates.
gfx::Rect GetBoundsInRootWindow() const; gfx::Rect GetBoundsInRootWindow() const;
...@@ -487,8 +499,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -487,8 +499,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// specific changes. Called from Show()/Hide(). // specific changes. Called from Show()/Hide().
void SetVisible(bool visible); void SetVisible(bool visible);
// Updates the occlusion state of the window. // Updates the occlusion info of the window.
void SetOcclusionState(OcclusionState occlusion_state); void SetOcclusionInfo(OcclusionState occlusion_state,
const SkRegion& occluded_region);
// Schedules a paint for the Window's entire bounds. // Schedules a paint for the Window's entire bounds.
void SchedulePaint(); void SchedulePaint();
...@@ -624,6 +637,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ...@@ -624,6 +637,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Occlusion state of the window. // Occlusion state of the window.
OcclusionState occlusion_state_; OcclusionState occlusion_state_;
// Occluded region of the window.
SkRegion occluded_region_;
int id_; int id_;
// The FrameSinkId associated with this window. If this window is embedding // The FrameSinkId associated with this window. If this window is embedding
......
...@@ -86,11 +86,12 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler { ...@@ -86,11 +86,12 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler {
// Window::TargetVisibility() for details. // Window::TargetVisibility() for details.
virtual void OnWindowTargetVisibilityChanged(bool visible) = 0; virtual void OnWindowTargetVisibilityChanged(bool visible) = 0;
// Called when the occlusion state of the Window changes while tracked (see // Called when the occlusion state or occluded region of the Window changes
// WindowOcclusionTracker::Track). |occlusion_state| is the new occlusion // while tracked (see WindowOcclusionTracker::Track). |occlusion_state| is
// state of the Window. // the new occlusion state of the Window. |occluded_region| is the new
virtual void OnWindowOcclusionChanged( // occluded region of the Window.
Window::OcclusionState occlusion_state) {} virtual void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
const SkRegion& occluded_region) {}
// Called from Window::HitTest to check if the window has a custom hit test // Called from Window::HitTest to check if the window has a custom hit test
// mask. It works similar to the views counterparts. That is, if the function // mask. It works similar to the views counterparts. That is, if the function
......
...@@ -85,17 +85,6 @@ SkIRect GetWindowBoundsInRootWindow( ...@@ -85,17 +85,6 @@ SkIRect GetWindowBoundsInRootWindow(
return skirect_bounds; return skirect_bounds;
} }
// Returns true iff the occlusion states in |tracked_windows| match those
// returned by Window::occlusion_state().
bool OcclusionStatesMatch(
const base::flat_map<Window*, Window::OcclusionState>& tracked_windows) {
for (const auto& tracked_window : tracked_windows) {
if (tracked_window.second != tracked_window.first->occlusion_state())
return false;
}
return true;
}
} // namespace } // namespace
WindowOcclusionTracker::ScopedPause::ScopedPause(Env* env) : env_(env) { WindowOcclusionTracker::ScopedPause::ScopedPause(Env* env) : env_(env) {
...@@ -110,8 +99,7 @@ void WindowOcclusionTracker::Track(Window* window) { ...@@ -110,8 +99,7 @@ void WindowOcclusionTracker::Track(Window* window) {
DCHECK(window); DCHECK(window);
DCHECK(window != window->GetRootWindow()); DCHECK(window != window->GetRootWindow());
auto insert_result = auto insert_result = tracked_windows_.insert({window, {}});
tracked_windows_.insert({window, Window::OcclusionState::UNKNOWN});
DCHECK(insert_result.second); DCHECK(insert_result.second);
if (!window_observer_.IsObserving(window)) if (!window_observer_.IsObserving(window))
window_observer_.Add(window); window_observer_.Add(window);
...@@ -123,6 +111,16 @@ WindowOcclusionTracker::WindowOcclusionTracker() = default; ...@@ -123,6 +111,16 @@ WindowOcclusionTracker::WindowOcclusionTracker() = default;
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() { void WindowOcclusionTracker::MaybeComputeOcclusion() {
if (num_pause_occlusion_tracking_ || if (num_pause_occlusion_tracking_ ||
num_times_occlusion_recomputed_in_current_step_ != 0) { num_times_occlusion_recomputed_in_current_step_ != 0) {
...@@ -133,7 +131,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { ...@@ -133,7 +131,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() {
&num_times_occlusion_recomputed_in_current_step_, 0); &num_times_occlusion_recomputed_in_current_step_, 0);
// Recompute occlusion states until either: // Recompute occlusion states until either:
// - They are stable, i.e. calling Window::SetOcclusionState() on all tracked // - They are stable, i.e. calling Window::SetOcclusionInfo() on all tracked
// windows does not provoke changes that could affect occlusion. // windows does not provoke changes that could affect occlusion.
// - Occlusion states have been recomputed // - Occlusion states have been recomputed
// |kMaxComputeOcclusionIterationsBeforeStable| // |kMaxComputeOcclusionIterationsBeforeStable|
...@@ -150,7 +148,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { ...@@ -150,7 +148,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() {
bool found_dirty_root = false; bool found_dirty_root = false;
// Compute occlusion states and store them in |tracked_windows_|. Do not // Compute occlusion states and store them in |tracked_windows_|. Do not
// call Window::SetOcclusionState() in this phase to prevent changes to the // call Window::SetOcclusionInfo() in this phase to prevent changes to the
// window tree while it is being traversed. // window tree while it is being traversed.
for (auto& root_window_pair : root_windows_) { for (auto& root_window_pair : root_windows_) {
if (root_window_pair.second.dirty) { if (root_window_pair.second.dirty) {
...@@ -170,7 +168,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { ...@@ -170,7 +168,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() {
++num_times_occlusion_recomputed_; ++num_times_occlusion_recomputed_;
++num_times_occlusion_recomputed_in_current_step_; ++num_times_occlusion_recomputed_in_current_step_;
// Call Window::SetOcclusionState() on tracked windows. A WindowDelegate may // Call Window::SetOcclusionInfo() on tracked windows. A WindowDelegate may
// change the window tree in response to this. // change the window tree in response to this.
WindowTracker tracked_windows_list; WindowTracker tracked_windows_list;
for (const auto& tracked_window : tracked_windows_) for (const auto& tracked_window : tracked_windows_)
...@@ -180,15 +178,20 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { ...@@ -180,15 +178,20 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() {
Window* window = tracked_windows_list.Pop(); Window* window = tracked_windows_list.Pop();
auto it = tracked_windows_.find(window); auto it = tracked_windows_.find(window);
if (it != tracked_windows_.end() && if (it != tracked_windows_.end() &&
it->second != Window::OcclusionState::UNKNOWN) { it->second.occlusion_state != Window::OcclusionState::UNKNOWN) {
// Fallback to VISIBLE/HIDDEN if the maximum number of times that // Fallback to VISIBLE/HIDDEN if the maximum number of times that
// occlusion can be recomputed was exceeded. // occlusion can be recomputed was exceeded.
if (exceeded_max_num_times_occlusion_recomputed) { if (exceeded_max_num_times_occlusion_recomputed) {
it->second = window->IsVisible() ? Window::OcclusionState::VISIBLE if (window->IsVisible()) {
: Window::OcclusionState::HIDDEN; it->second.occlusion_state = Window::OcclusionState::VISIBLE;
} else {
it->second.occlusion_state = Window::OcclusionState::HIDDEN;
}
it->second.occluded_region = SkRegion();
} }
window->SetOcclusionState(it->second); window->SetOcclusionInfo(it->second.occlusion_state,
it->second.occluded_region);
} }
} }
} }
...@@ -232,19 +235,22 @@ bool WindowOcclusionTracker::RecomputeOcclusionImpl( ...@@ -232,19 +235,22 @@ bool WindowOcclusionTracker::RecomputeOcclusionImpl(
const SkIRect* clipped_bounds_for_children = const SkIRect* clipped_bounds_for_children =
window->layer()->GetMasksToBounds() ? &window_bounds : clipped_bounds; window->layer()->GetMasksToBounds() ? &window_bounds : clipped_bounds;
bool has_visible_child = false; bool has_visible_child = false;
SkRegion occluded_region_before_traversing_children = *occluded_region;
for (auto* child : base::Reversed(window->children())) { for (auto* child : base::Reversed(window->children())) {
has_visible_child |= has_visible_child |=
RecomputeOcclusionImpl(child, transform_relative_to_root, RecomputeOcclusionImpl(child, transform_relative_to_root,
clipped_bounds_for_children, occluded_region); clipped_bounds_for_children, occluded_region);
} }
// Compute window occlusion state. // Window is fully occluded.
if (occluded_region->contains(window_bounds)) { if (occluded_region->contains(window_bounds) && !has_visible_child) {
SetOccluded(window, !has_visible_child); SetOccluded(window, true, SkRegion());
return has_visible_child; return false;
} }
SetOccluded(window, false); // Window is partially occluded or unoccluded.
SetOccluded(window, false, occluded_region_before_traversing_children);
if (VisibleWindowIsOpaque(window)) if (VisibleWindowIsOpaque(window))
occluded_region->op(window_bounds, SkRegion::kUnion_Op); occluded_region->op(window_bounds, SkRegion::kUnion_Op);
return true; return true;
...@@ -303,22 +309,31 @@ bool WindowOcclusionTracker::MaybeObserveAnimatedWindow(Window* window) { ...@@ -303,22 +309,31 @@ bool WindowOcclusionTracker::MaybeObserveAnimatedWindow(Window* window) {
void WindowOcclusionTracker::SetWindowAndDescendantsAreOccluded( void WindowOcclusionTracker::SetWindowAndDescendantsAreOccluded(
Window* window, Window* window,
bool is_occluded) { bool is_occluded) {
SetOccluded(window, is_occluded); SetOccluded(window, is_occluded, SkRegion());
for (Window* child_window : window->children()) for (Window* child_window : window->children())
SetWindowAndDescendantsAreOccluded(child_window, is_occluded); SetWindowAndDescendantsAreOccluded(child_window, is_occluded);
} }
void WindowOcclusionTracker::SetOccluded(Window* window, bool is_occluded) { void WindowOcclusionTracker::SetOccluded(Window* window,
bool is_occluded,
const SkRegion& occluded_region) {
auto tracked_window = tracked_windows_.find(window); auto tracked_window = tracked_windows_.find(window);
if (tracked_window == tracked_windows_.end()) if (tracked_window == tracked_windows_.end())
return; return;
// Set the occluded region of the window.
tracked_window->second.occluded_region = occluded_region;
if (!window->IsVisible()) if (!window->IsVisible())
tracked_window->second = Window::OcclusionState::HIDDEN; tracked_window->second.occlusion_state = Window::OcclusionState::HIDDEN;
else if (is_occluded) else if (is_occluded)
tracked_window->second = Window::OcclusionState::OCCLUDED; tracked_window->second.occlusion_state = Window::OcclusionState::OCCLUDED;
else else
tracked_window->second = Window::OcclusionState::VISIBLE; 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 { bool WindowOcclusionTracker::WindowIsTracked(Window* window) const {
......
...@@ -87,9 +87,22 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, ...@@ -87,9 +87,22 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
bool dirty = false; bool dirty = false;
}; };
// Holds occlusion related information for tracked windows.
struct OcclusionData {
// Occlusion state for a tracked window.
Window::OcclusionState occlusion_state = Window::OcclusionState::UNKNOWN;
// Region in root window coordinates that is occluded.
SkRegion occluded_region;
};
WindowOcclusionTracker(); WindowOcclusionTracker();
~WindowOcclusionTracker() override; ~WindowOcclusionTracker() override;
// Returns true iff the occlusion states in |tracked_windows| match those
// returned by Window::occlusion_state().
static bool OcclusionStatesMatch(
const base::flat_map<Window*, OcclusionData>& tracked_windows);
// Recomputes the occlusion state of tracked windows under roots marked as // Recomputes the occlusion state of tracked windows under roots marked as
// dirty in |root_windows_| if there are no active ScopedPause instance. // dirty in |root_windows_| if there are no active ScopedPause instance.
void MaybeComputeOcclusion(); void MaybeComputeOcclusion();
...@@ -126,9 +139,12 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, ...@@ -126,9 +139,12 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
void SetWindowAndDescendantsAreOccluded(Window* window, bool is_occluded); void SetWindowAndDescendantsAreOccluded(Window* window, bool is_occluded);
// Updates the occlusion state of |window| in |tracked_windows_|, based on // Updates the occlusion state of |window| in |tracked_windows_|, based on
// |is_occluded| and window->IsVisible(). No-op if |window| is not in // |is_occluded| and window->IsVisible(). Updates the occluded region of
// |window| using |occluded_region|. No-op if |window| is not in
// |tracked_windows_|. // |tracked_windows_|.
void SetOccluded(Window* window, bool is_occluded); void SetOccluded(Window* window,
bool is_occluded,
const SkRegion& occluded_region);
// Returns true if |window| is in |tracked_windows_|. // Returns true if |window| is in |tracked_windows_|.
bool WindowIsTracked(Window* window) const; bool WindowIsTracked(Window* window) const;
...@@ -214,8 +230,8 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, ...@@ -214,8 +230,8 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
Window* new_root) override; Window* new_root) override;
void OnWindowLayerRecreated(Window* window) override; void OnWindowLayerRecreated(Window* window) override;
// Windows whose occlusion state is tracked. // Windows whose occlusion data is tracked.
base::flat_map<Window*, Window::OcclusionState> tracked_windows_; base::flat_map<Window*, OcclusionData> tracked_windows_;
// Windows whose bounds or transform are animated. // Windows whose bounds or transform are animated.
// //
......
...@@ -37,24 +37,30 @@ class MockWindowDelegate : public test::ColorTestWindowDelegate { ...@@ -37,24 +37,30 @@ class MockWindowDelegate : public test::ColorTestWindowDelegate {
void set_window(Window* window) { window_ = window; } void set_window(Window* window) { window_ = window; }
void set_expectation(Window::OcclusionState expectation) { void set_expectation(Window::OcclusionState occlusion_state,
expectation_ = expectation; const SkRegion& occluded_region) {
expected_occlusion_state_ = occlusion_state;
expected_occluded_region_ = occluded_region;
} }
bool is_expecting_call() const { bool is_expecting_call() const {
return expectation_ != Window::OcclusionState::UNKNOWN; return expected_occlusion_state_ != Window::OcclusionState::UNKNOWN;
} }
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
ASSERT_TRUE(window_); ASSERT_TRUE(window_);
EXPECT_NE(occlusion_state, Window::OcclusionState::UNKNOWN); EXPECT_NE(occlusion_state, Window::OcclusionState::UNKNOWN);
EXPECT_EQ(occlusion_state, expectation_); EXPECT_EQ(occlusion_state, expected_occlusion_state_);
expectation_ = Window::OcclusionState::UNKNOWN; EXPECT_EQ(occluded_region, expected_occluded_region_);
expected_occlusion_state_ = Window::OcclusionState::UNKNOWN;
expected_occluded_region_ = SkRegion();
} }
private: private:
Window::OcclusionState expectation_ = Window::OcclusionState::UNKNOWN; Window::OcclusionState expected_occlusion_state_ =
Window::OcclusionState::UNKNOWN;
SkRegion expected_occluded_region_ = SkRegion();
Window* window_ = nullptr; Window* window_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(MockWindowDelegate); DISALLOW_COPY_AND_ASSIGN(MockWindowDelegate);
...@@ -92,6 +98,12 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase { ...@@ -92,6 +98,12 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase {
DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTrackerTest); DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTrackerTest);
}; };
SkRegion SkRegionFromSkIRects(std::initializer_list<SkIRect> rects) {
SkRegion r;
r.setRects(rects.begin(), rects.size());
return r;
}
} // namespace } // namespace
// Verify that non-overlapping windows have a VISIBLE occlusion state. // Verify that non-overlapping windows have a VISIBLE occlusion state.
...@@ -100,13 +112,16 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase { ...@@ -100,13 +112,16 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase {
// |____| |____| // |____| |____|
TEST_F(WindowOcclusionTrackerTest, NonOverlappingWindows) { TEST_F(WindowOcclusionTrackerTest, NonOverlappingWindows) {
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(15, 0, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(15, 0, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(15, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
} }
...@@ -116,13 +131,16 @@ TEST_F(WindowOcclusionTrackerTest, NonOverlappingWindows) { ...@@ -116,13 +131,16 @@ TEST_F(WindowOcclusionTrackerTest, NonOverlappingWindows) {
// |_____| // |_____|
TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) { TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) {
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeWH(5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
} }
...@@ -135,31 +153,31 @@ TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) { ...@@ -135,31 +153,31 @@ TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) {
TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. Expect it to be non-occluded and expect window a to be // Create window b. Expect it to be non-occluded and expect window a to be
// occluded. // occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Hide window b. Expect window a to be non-occluded and window b to be // Hide window b. Expect window a to be non-occluded and window b to be
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::HIDDEN); delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_b->Hide(); window_b->Hide();
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Show window b. Expect window a to be occluded and window b to be non- // Show window b. Expect window a to be occluded and window b to be non-
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->Show(); window_b->Show();
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -174,15 +192,15 @@ TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) { ...@@ -174,15 +192,15 @@ TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) {
TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. Expect it to be non-occluded and expect window a to be // Create window b. Expect it to be non-occluded and expect window a to be
// occluded. // occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -190,13 +208,13 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { ...@@ -190,13 +208,13 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) {
// Change the opacity of window b to 0.5f. Expect both windows to be non- // Change the opacity of window b to 0.5f. Expect both windows to be non-
// occluded. // occluded.
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->layer()->SetOpacity(0.5f); window_b->layer()->SetOpacity(0.5f);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Change the opacity of window b back to 1.0f. Expect window a to be // Change the opacity of window b back to 1.0f. Expect window a to be
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->layer()->SetOpacity(1.0f); window_b->layer()->SetOpacity(1.0f);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -206,24 +224,24 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { ...@@ -206,24 +224,24 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) {
TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create untracked window b. Expect window a to be occluded. // Create untracked window b. Expect window a to be occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 15, 15)); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 15, 15));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Change the opacity of window b to 0.5f. Expect both windows to be non- // Change the opacity of window b to 0.5f. Expect both windows to be non-
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->layer()->SetOpacity(0.5f); window_b->layer()->SetOpacity(0.5f);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Change the opacity of window b back to 1.0f. Expect window a to be // Change the opacity of window b back to 1.0f. Expect window a to be
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->layer()->SetOpacity(1.0f); window_b->layer()->SetOpacity(1.0f);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -236,25 +254,31 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) { ...@@ -236,25 +254,31 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) {
TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) { TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b with bounds that partially cover window a. Expect both // Create window b with bounds that partially cover window a. Expect both
// windows to be non-occluded. // windows to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeWH(5, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create window c with bounds that cover the portion of window a that isn't // Create window c with bounds that cover the portion of window a that isn't
// already covered by window b. Expect window a to be occluded and window a/b // already covered by window b. Expect window a to be occluded and window a/b
// to be non-occluded. // to be non-occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(5, 0, 5, 10)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(5, 0, 5, 10)); CreateTrackedWindow(delegate_c, gfx::Rect(5, 0, 5, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
} }
...@@ -263,23 +287,23 @@ TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) { ...@@ -263,23 +287,23 @@ TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) {
TEST_F(WindowOcclusionTrackerTest, SiblingOccludesWindowAndChild) { TEST_F(WindowOcclusionTrackerTest, SiblingOccludesWindowAndChild) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b, with bounds that occlude half of its parent window a. // Create window b, with bounds that occlude half of its parent window a.
// Expect it to be non-occluded. // Expect it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create window c, with bounds that occlude window a and window b. Expect it // Create window c, with bounds that occlude window a and window b. Expect it
// to be non-occluded, and window a and b to be occluded. // to be non-occluded, and window a and b to be occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 20, 20)); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -291,23 +315,28 @@ TEST_F(WindowOcclusionTrackerTest, SiblingOccludesWindowAndChild) { ...@@ -291,23 +315,28 @@ TEST_F(WindowOcclusionTrackerTest, SiblingOccludesWindowAndChild) {
TEST_F(WindowOcclusionTrackerTest, ChildAndSiblingOccludeOneWindow) { TEST_F(WindowOcclusionTrackerTest, ChildAndSiblingOccludeOneWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b, with bounds that occlude half of its parent window a. // Create window b, with bounds that occlude half of its parent window a.
// Expect it to be non-occluded. // Expect it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create window c, with bounds that occlude the other half of window a. // Create window c, with bounds that occlude the other half of window a.
// Expect it to be non-occluded and expect window a to remain non-occluded. // Expect it to be non-occluded and expect window a to remain non-occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 20)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 20)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20)); CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
} }
...@@ -315,22 +344,26 @@ TEST_F(WindowOcclusionTrackerTest, ChildAndSiblingOccludeOneWindow) { ...@@ -315,22 +344,26 @@ TEST_F(WindowOcclusionTrackerTest, ChildAndSiblingOccludeOneWindow) {
TEST_F(WindowOcclusionTrackerTest, ChildrenOccludeOneWindow) { TEST_F(WindowOcclusionTrackerTest, ChildrenOccludeOneWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b, with bounds that cover half of its parent window a. Expect // Create window b, with bounds that cover half of its parent window a. Expect
// it to be non-occluded. // it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window c, with bounds that cover the other half of its parent window // Create window c, with bounds that cover the other half of its parent window
// a. Expect it to be non-occluded. Expect window a to remain non-occluded. // a. Expect it to be non-occluded. Expect window a to remain non-occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 20)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20), window_a); CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20), window_a);
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
} }
...@@ -339,27 +372,35 @@ TEST_F(WindowOcclusionTrackerTest, ChildrenOccludeOneWindow) { ...@@ -339,27 +372,35 @@ TEST_F(WindowOcclusionTrackerTest, ChildrenOccludeOneWindow) {
TEST_F(WindowOcclusionTrackerTest, ChildDoesNotOccludeParent) { TEST_F(WindowOcclusionTrackerTest, ChildDoesNotOccludeParent) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b with window a as parent. The bounds of window b fully cover // Create window b with window a as parent. The bounds of window b fully cover
// window a. Expect both windows to be non-occluded. // window a. Expect both windows to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = Window* window_b =
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create window c whose bounds don't overlap existing windows. // Create window c whose bounds don't overlap existing windows.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(15, 0, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(15, 0, 10, 10)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(15, 0, 10, 10)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(15, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Change the parent of window b from window a to window c. Expect all windows // Change the parent of window b from window a to window c. Expect all windows
// to remain non-occluded. // to remain non-occluded.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_c->AddChild(window_b); window_c->AddChild(window_b);
EXPECT_FALSE(delegate_b->is_expecting_call());
} }
// Verify that when the stacking order of windows change, occlusion states are // Verify that when the stacking order of windows change, occlusion states are
...@@ -368,28 +409,28 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) { ...@@ -368,28 +409,28 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) {
// Create three windows that have the same bounds. Expect window on top of the // Create three windows that have the same bounds. Expect window on top of the
// stack to be non-occluded and other windows to be occluded. // stack to be non-occluded and other windows to be occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Move window a on top of the stack. Expect it to be non-occluded and expect // Move window a on top of the stack. Expect it to be non-occluded and expect
// window c to be occluded. // window c to be occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); delegate_c->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
root_window()->StackChildAtTop(window_a); root_window()->StackChildAtTop(window_a);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -402,7 +443,7 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) { ...@@ -402,7 +443,7 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) {
TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) { TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) {
// Create window a which is transparent. Expect it to be non-occluded. // Create window a which is transparent. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10), Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10),
root_window(), true); root_window(), true);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
...@@ -410,14 +451,14 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) { ...@@ -410,14 +451,14 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) {
// Create window b which has the same bounds as its parent window a. Expect it // Create window b which has the same bounds as its parent window a. Expect it
// to be non-occluded. // to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create window c which is transparent and has the same bounds as window a // Create window c which is transparent and has the same bounds as window a
// and window b. Expect it to be non-occluded. // and window b. Expect it to be non-occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10), Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10),
root_window(), true); root_window(), true);
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -425,9 +466,9 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) { ...@@ -425,9 +466,9 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) {
// Create window d which has the same bounds as its parent window c. Expect // Create window d which has the same bounds as its parent window c. Expect
// window d to be non-occluded and window a and b to be occluded. // window d to be non-occluded and window a and b to be occluded.
MockWindowDelegate* delegate_d = new MockWindowDelegate(); MockWindowDelegate* delegate_d = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_d->set_expectation(Window::OcclusionState::VISIBLE); delegate_d->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_d, gfx::Rect(0, 0, 10, 10), window_c); CreateTrackedWindow(delegate_d, gfx::Rect(0, 0, 10, 10), window_c);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -435,10 +476,10 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) { ...@@ -435,10 +476,10 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) {
// Move window a on top of the stack. Expect window a and b to be non-occluded // Move window a on top of the stack. Expect window a and b to be non-occluded
// and window c and d to be occluded. // and window c and d to be occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); delegate_c->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_d->set_expectation(Window::OcclusionState::OCCLUDED); delegate_d->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
root_window()->StackChildAtTop(window_a); root_window()->StackChildAtTop(window_a);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -453,12 +494,12 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) { ...@@ -453,12 +494,12 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) {
// Create window b. Expect it to be non-occluded. // Create window b. Expect it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Stack window a on top of window b. Expect window b to be occluded. // Stack window a on top of window b. Expect window b to be occluded.
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
root_window()->StackChildAtTop(window_a); root_window()->StackChildAtTop(window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
} }
...@@ -467,17 +508,20 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) { ...@@ -467,17 +508,20 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) {
TEST_F(WindowOcclusionTrackerTest, BoundsChanged) { TEST_F(WindowOcclusionTrackerTest, BoundsChanged) {
// Create two non-overlapping windows. Expect them to be non-occluded. // Create two non-overlapping windows. Expect them to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Move window b on top of window a. Expect window a to be occluded. // Move window b on top of window a. Expect window a to be occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -498,26 +542,29 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) { ...@@ -498,26 +542,29 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) {
// Create 3 windows. Window a is unoccluded. Window c occludes window b. // Create 3 windows. Window a is unoccluded. Window c occludes window b.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
window_b->layer()->SetAnimator(test_controller.animator()); window_b->layer()->SetAnimator(test_controller.animator());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10)); CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Start animating the bounds of window b so that it moves on top of window a. // Start animating the bounds of window b so that it moves on top of window a.
// Window b should be non-occluded when the animation starts. // Window b should be non-occluded when the animation starts.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -526,9 +573,13 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) { ...@@ -526,9 +573,13 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) {
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
// Window b should occlude window a at the end of the animation. // Window b should occlude window a at the end of the animation.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
// Window b should have window c in its potential occlusion region.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 10, 10)));
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
window_b->layer()->SetAnimator(nullptr); window_b->layer()->SetAnimator(nullptr);
} }
...@@ -545,18 +596,21 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { ...@@ -545,18 +596,21 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) {
// Create 3 windows. Window a is unoccluded. Window c occludes window b. // Create 3 windows. Window a is unoccluded. Window c occludes window b.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -564,7 +618,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { ...@@ -564,7 +618,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) {
// Start animating the bounds of window c so that it moves on top of window a. // Start animating the bounds of window c so that it moves on top of window a.
// Window b should be non-occluded when the animation starts. // Window b should be non-occluded when the animation starts.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_c->SetBounds(window_a->bounds()); window_c->SetBounds(window_a->bounds());
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -573,9 +627,13 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { ...@@ -573,9 +627,13 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) {
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
// Window c should occlude window a at the end of the animation. // Window c should occlude window a at the end of the animation.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); // Window b should have a potentially occluded region including window c.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 0, 10, 10)));
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
window_c->layer()->SetAnimator(nullptr); window_c->layer()->SetAnimator(nullptr);
} }
...@@ -585,14 +643,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { ...@@ -585,14 +643,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) {
TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which doesn't overlap window a and is transparent. Expect // Create window b which doesn't overlap window a and is transparent. Expect
// it to be non-occluded. // it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10),
root_window(), true); root_window(), true);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -600,13 +658,16 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { ...@@ -600,13 +658,16 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) {
// Create window c which has window b as parent and doesn't occlude any // Create window c which has window b as parent and doesn't occlude any
// window. // window.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b);
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Move window b so that window c occludes window a. Expect window a to be // Move window b so that window c occludes window a. Expect window a to be
// occluded and other windows to be non-occluded. // occluded and other windows to be non-occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->SetBounds(gfx::Rect(0, 0, 10, 10)); window_b->SetBounds(gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -616,15 +677,18 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { ...@@ -616,15 +677,18 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) {
TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) { TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. It should not occlude window a. // Create window b. It should not occlude window a.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
// Move window b on top of window a. Expect window a to be occluded. // Move window b on top of window a. Expect window a to be occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -634,18 +698,21 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) { ...@@ -634,18 +698,21 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) {
TEST_F(WindowOcclusionTrackerTest, TransformChanged) { TEST_F(WindowOcclusionTrackerTest, TransformChanged) {
// Create two non-overlapping windows. Expect them to be non-occluded. // Create two non-overlapping windows. Expect them to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Scale and translate window b so that it covers window a. Expect window a to // Scale and translate window b so that it covers window a. Expect window a to
// be occluded. // be occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
gfx::Transform transform; gfx::Transform transform;
transform.Translate(0.0f, -10.0f); transform.Translate(0.0f, -10.0f);
transform.Scale(2.0f, 2.0f); transform.Scale(2.0f, 2.0f);
...@@ -669,26 +736,29 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) { ...@@ -669,26 +736,29 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) {
// Create 3 windows. Window a is unoccluded. Window c occludes window b. // Create 3 windows. Window a is unoccluded. Window c occludes window b.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
window_b->layer()->SetAnimator(test_controller.animator()); window_b->layer()->SetAnimator(test_controller.animator());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 5, 5)); CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Start animating the transform of window b so that it moves on top of window // Start animating the transform of window b so that it moves on top of window
// a. Window b should be non-occluded when the animation starts. // a. Window b should be non-occluded when the animation starts.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
auto transform = std::make_unique<ui::InterpolatedScale>( auto transform = std::make_unique<ui::InterpolatedScale>(
gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1)); gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1));
transform->SetChild(std::make_unique<ui::InterpolatedTranslation>( transform->SetChild(std::make_unique<ui::InterpolatedTranslation>(
...@@ -703,9 +773,13 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) { ...@@ -703,9 +773,13 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) {
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
// Window b should occlude window a at the end of the animation. // Window b should occlude window a at the end of the animation.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
// Window b should see window c as part of the potential occlusion region.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
window_b->layer()->SetAnimator(nullptr); window_b->layer()->SetAnimator(nullptr);
} }
...@@ -722,18 +796,21 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { ...@@ -722,18 +796,21 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) {
// Create 3 windows. Window a is unoccluded. Window c occludes window b. // Create 3 windows. Window a is unoccluded. Window c occludes window b.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 20, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 20, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 20, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); delegate_b->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10));
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -741,7 +818,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { ...@@ -741,7 +818,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) {
// Start animating the bounds of window c so that it moves on top of window a. // Start animating the bounds of window c so that it moves on top of window a.
// Window b should be non-occluded when the animation starts. // Window b should be non-occluded when the animation starts.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
auto transform = std::make_unique<ui::InterpolatedScale>( auto transform = std::make_unique<ui::InterpolatedScale>(
gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1)); gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1));
transform->SetChild(std::make_unique<ui::InterpolatedTranslation>( transform->SetChild(std::make_unique<ui::InterpolatedTranslation>(
...@@ -756,9 +833,13 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { ...@@ -756,9 +833,13 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) {
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
// Window c should occlude window a at the end of the animation. // Window c should occlude window a at the end of the animation.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
// Window b should now see window c in the potential occlusion region.
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeWH(20, 20)));
test_controller.Step(kTransitionDuration / 3); test_controller.Step(kTransitionDuration / 3);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
window_c->layer()->SetAnimator(nullptr); window_c->layer()->SetAnimator(nullptr);
} }
...@@ -768,14 +849,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { ...@@ -768,14 +849,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) {
TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which doesn't overlap window a and is transparent. Expect // Create window b which doesn't overlap window a and is transparent. Expect
// it to be non-occluded. // it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10),
root_window(), true); root_window(), true);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -783,13 +864,16 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { ...@@ -783,13 +864,16 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) {
// Create window c which has window b as parent and doesn't occlude any // Create window c which has window b as parent and doesn't occlude any
// window. // window.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b);
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Scale and translate window b so that window c occludes window a. Expect // Scale and translate window b so that window c occludes window a. Expect
// window a to be occluded and other windows to be non-occluded. // window a to be occluded and other windows to be non-occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
gfx::Transform transform; gfx::Transform transform;
transform.Translate(0.0f, -10.0f); transform.Translate(0.0f, -10.0f);
transform.Scale(2.0f, 2.0f); transform.Scale(2.0f, 2.0f);
...@@ -802,16 +886,19 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { ...@@ -802,16 +886,19 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) {
TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) { TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. It should not occlude window a. // Create window b. It should not occlude window a.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
// Scale and translate window b so that it occludes window a. Expect window a // Scale and translate window b so that it occludes window a. Expect window a
// to be occluded. // to be occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
gfx::Transform transform; gfx::Transform transform;
transform.Translate(0.0f, -10.0f); transform.Translate(0.0f, -10.0f);
transform.Scale(2.0f, 2.0f); transform.Scale(2.0f, 2.0f);
...@@ -824,17 +911,17 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) { ...@@ -824,17 +911,17 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) {
TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) { TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which occludes window a. // Create window b which occludes window a.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Delete window b. Expect a to be non-occluded. // Delete window b. Expect a to be non-occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delete window_b; delete window_b;
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -844,17 +931,17 @@ TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) { ...@@ -844,17 +931,17 @@ TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) {
TEST_F(WindowOcclusionTrackerTest, RemoveUntrackedWindow) { TEST_F(WindowOcclusionTrackerTest, RemoveUntrackedWindow) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which occludes window a. // Create window b which occludes window a.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Delete window b. Expect a to be non-occluded. // Delete window b. Expect a to be non-occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
root_window()->RemoveChild(window_b); root_window()->RemoveChild(window_b);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
delete window_b; delete window_b;
...@@ -864,7 +951,7 @@ TEST_F(WindowOcclusionTrackerTest, RemoveUntrackedWindow) { ...@@ -864,7 +951,7 @@ TEST_F(WindowOcclusionTrackerTest, RemoveUntrackedWindow) {
TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) { TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
...@@ -876,7 +963,7 @@ TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) { ...@@ -876,7 +963,7 @@ TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) {
window_b->Init(ui::LAYER_NOT_DRAWN); window_b->Init(ui::LAYER_NOT_DRAWN);
window_b->SetBounds(gfx::Rect(0, 0, 10, 10)); window_b->SetBounds(gfx::Rect(0, 0, 10, 10));
root_window()->AddChild(window_b); root_window()->AddChild(window_b);
delegate_b->set_expectation(Window::OcclusionState::HIDDEN); delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_b->TrackOcclusionState(); window_b->TrackOcclusionState();
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -887,8 +974,8 @@ TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) { ...@@ -887,8 +974,8 @@ TEST_F(WindowOcclusionTrackerTest, CustomizedWindowHasContent) {
})); }));
// Show window b to trigger a occlusion compute and window a is occluded. // Show window b to trigger a occlusion compute and window a is occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->Show(); window_b->Show();
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -905,7 +992,7 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) { ...@@ -905,7 +992,7 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) {
// Create window b. Expect it to be non-occluded. // Create window b. Expect it to be non-occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -917,19 +1004,20 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) { ...@@ -917,19 +1004,20 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) {
// Create untracked window d which covers window a. Expect window a to be // Create untracked window d which covers window a. Expect window a to be
// occluded. // occluded.
delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); delegate_c->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
Window* window_d = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); Window* window_d = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Move window d so that it doesn't cover window c. // Move window d so that it doesn't cover window c.
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
window_d->SetBounds(gfx::Rect(0, 10, 5, 5)); window_d->SetBounds(gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Stack window a on top of window c. Expect window c to be non-occluded. This // Stack window a on top of window c. Expect window c to be non-occluded. This
// won't work if WindowOcclusionTracked didn't register as an observer of // won't work if WindowOcclusionTracked didn't register as an observer of
// window a when window c was made a child of root_window(). // window a when window c was made a child of root_window().
delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); delegate_c->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
root_window()->StackChildAtTop(window_a); root_window()->StackChildAtTop(window_a);
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
} }
...@@ -952,7 +1040,6 @@ class ResizeWindowObserver : public WindowObserver { ...@@ -952,7 +1040,6 @@ class ResizeWindowObserver : public WindowObserver {
Window* const window_to_resize_; Window* const window_to_resize_;
DISALLOW_COPY_AND_ASSIGN(ResizeWindowObserver); DISALLOW_COPY_AND_ASSIGN(ResizeWindowObserver);
;
}; };
} // namespace } // namespace
...@@ -962,14 +1049,14 @@ class ResizeWindowObserver : public WindowObserver { ...@@ -962,14 +1049,14 @@ class ResizeWindowObserver : public WindowObserver {
TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. Expect it to be non-occluded and to occlude window a. // Create window b. Expect it to be non-occluded and to occlude window a.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -977,7 +1064,7 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { ...@@ -977,7 +1064,7 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) {
// Create window c, which is a child of window b. Expect it to be non- // Create window c, which is a child of window b. Expect it to be non-
// occluded. // occluded.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = Window* window_c =
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -998,15 +1085,18 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { ...@@ -998,15 +1085,18 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) {
TEST_F(WindowOcclusionTrackerTest, ScopedPause) { TEST_F(WindowOcclusionTrackerTest, ScopedPause) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which doesn't overlap window a. Expect it to be non- // Create window b which doesn't overlap window a. Expect it to be non
// occluded. // occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Change bounds multiple times. At the end of the scope, expect window a to // Change bounds multiple times. At the end of the scope, expect window a to
...@@ -1018,7 +1108,7 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPause) { ...@@ -1018,7 +1108,7 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPause) {
window_a->SetBounds(gfx::Rect(0, 10, 5, 5)); window_a->SetBounds(gfx::Rect(0, 10, 5, 5));
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
} }
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -1027,15 +1117,17 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPause) { ...@@ -1027,15 +1117,17 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPause) {
TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) { TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b which doesn't overlap window a. Expect it to be non- // Create window b which doesn't overlap window a. Expect it to be non-
// occluded. // occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Change bounds multiple times. At the end of the scope, expect window a to // Change bounds multiple times. At the end of the scope, expect window a to
...@@ -1060,7 +1152,7 @@ TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) { ...@@ -1060,7 +1152,7 @@ TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) {
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
} }
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
} }
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -1080,17 +1172,19 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) { ...@@ -1080,17 +1172,19 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) {
// Effective bounds: x = 34, y = 36, height = 8, width = 10 // Effective bounds: x = 34, y = 36, height = 8, width = 10
CreateUntrackedWindow(gfx::Rect(15, 16, 4, 5), window_b); CreateUntrackedWindow(gfx::Rect(15, 16, 4, 5), window_b);
MockWindowDelegate* delegate_d = new MockWindowDelegate(); MockWindowDelegate* delegate_d = new MockWindowDelegate();
delegate_d->set_expectation(Window::OcclusionState::VISIBLE); delegate_d->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(34, 36, 8, 10)); Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(34, 36, 8, 10));
EXPECT_FALSE(delegate_d->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call());
delegate_d->set_expectation(Window::OcclusionState::OCCLUDED); delegate_d->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
root_window()->StackChildAtBottom(window_d); root_window()->StackChildAtBottom(window_d);
EXPECT_FALSE(delegate_d->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call());
delegate_d->set_expectation(Window::OcclusionState::VISIBLE); SkRegion occluded_area = SkRegionFromSkIRects(
{SkIRect::MakeXYWH(2, 2, 10, 10), SkIRect::MakeXYWH(4, 4, 4, 4),
SkIRect::MakeXYWH(34, 36, 8, 10)});
delegate_d->set_expectation(Window::OcclusionState::VISIBLE, occluded_area);
window_d->SetBounds(gfx::Rect(35, 36, 8, 10)); window_d->SetBounds(gfx::Rect(35, 36, 8, 10));
EXPECT_FALSE(delegate_d->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call());
...@@ -1104,21 +1198,23 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) { ...@@ -1104,21 +1198,23 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) {
TEST_F(WindowOcclusionTrackerTest, Clipping) { TEST_F(WindowOcclusionTrackerTest, Clipping) {
// Create window a. Expect it to be non-occluded. // Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b. Expect it to be non-occluded. // Create window b. Expect it to be non-occluded.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeWH(5, 5)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
window_b->layer()->SetMasksToBounds(true); window_b->layer()->SetMasksToBounds(true);
// Create window c which has window b as parent. Don't expect it to occlude // Create window c which has window b as parent. Don't expect it to occlude
// window a since its bounds are clipped by window b. // window a since its bounds are clipped by window b.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10), window_b);
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
} }
...@@ -1138,7 +1234,7 @@ TEST_F(WindowOcclusionTrackerTest, DestroyWindowWithPendingAnimation) { ...@@ -1138,7 +1234,7 @@ TEST_F(WindowOcclusionTrackerTest, DestroyWindowWithPendingAnimation) {
layer_animation_settings.SetTransitionDuration(kTransitionDuration); layer_animation_settings.SetTransitionDuration(kTransitionDuration);
MockWindowDelegate* delegate = new MockWindowDelegate(); MockWindowDelegate* delegate = new MockWindowDelegate();
delegate->set_expectation(Window::OcclusionState::VISIBLE); delegate->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate->is_expecting_call()); EXPECT_FALSE(delegate->is_expecting_call());
window->layer()->SetAnimator(test_controller.animator()); window->layer()->SetAnimator(test_controller.animator());
...@@ -1166,28 +1262,29 @@ TEST_F(WindowOcclusionTrackerTest, RecreateLayerOfAnimatedWindow) { ...@@ -1166,28 +1262,29 @@ TEST_F(WindowOcclusionTrackerTest, RecreateLayerOfAnimatedWindow) {
// Create 2 windows. Window b occludes window a. // Create 2 windows. Window b occludes window a.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(2, 2, 1, 1)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(2, 2, 1, 1));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
window_a->layer()->SetAnimator(test_controller.animator()); window_a->layer()->SetAnimator(test_controller.animator());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Start animating the bounds of window a. Window a should be non-occluded // Start animating the bounds of window a. Window a should be non-occluded
// when the animation starts. // when the animation starts.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_a->SetBounds(gfx::Rect(6, 6, 1, 1)); window_a->SetBounds(gfx::Rect(6, 6, 1, 1));
test_controller.Step(kTransitionDuration / 2); test_controller.Step(kTransitionDuration / 2);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Recreate the layer of window b. Expect this to behave the same as if the // Recreate the layer of window b. Expect this to behave the same as if the
// animation was abandoned. // animation was abandoned. Occlusion region should be half way between the
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); // animation bounds.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
std::unique_ptr<ui::Layer> old_layer = window_a->RecreateLayer(); std::unique_ptr<ui::Layer> old_layer = window_a->RecreateLayer();
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
...@@ -1217,7 +1314,7 @@ class ObserverChangingWindowBounds : public WindowObserver { ...@@ -1217,7 +1314,7 @@ class ObserverChangingWindowBounds : public WindowObserver {
TEST_F(WindowOcclusionTrackerTest, ChangeTrackedWindowBeforeObserveAddToRoot) { TEST_F(WindowOcclusionTrackerTest, ChangeTrackedWindowBeforeObserveAddToRoot) {
// Create a window. Expect it to be non-occluded. // Create a window. Expect it to be non-occluded.
MockWindowDelegate* delegate = new MockWindowDelegate(); MockWindowDelegate* delegate = new MockWindowDelegate();
delegate->set_expectation(Window::OcclusionState::VISIBLE); delegate->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate->is_expecting_call()); EXPECT_FALSE(delegate->is_expecting_call());
...@@ -1279,7 +1376,7 @@ TEST_F(WindowOcclusionTrackerTest, ...@@ -1279,7 +1376,7 @@ TEST_F(WindowOcclusionTrackerTest,
// Create a window. Expect it to be non-occluded. // Create a window. Expect it to be non-occluded.
MockWindowDelegate* delegate = new MockWindowDelegate(); MockWindowDelegate* delegate = new MockWindowDelegate();
delegate->set_expectation(Window::OcclusionState::VISIBLE); delegate->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate->is_expecting_call()); EXPECT_FALSE(delegate->is_expecting_call());
window->layer()->SetAnimator(test_controller.animator()); window->layer()->SetAnimator(test_controller.animator());
...@@ -1311,20 +1408,27 @@ TEST_F(WindowOcclusionTrackerTest, ...@@ -1311,20 +1408,27 @@ TEST_F(WindowOcclusionTrackerTest,
// Create a tracked window. Expect it to be non-occluded. // Create a tracked window. Expect it to be non-occluded.
MockWindowDelegate* delegate = new MockWindowDelegate(); MockWindowDelegate* delegate = new MockWindowDelegate();
delegate->set_expectation(Window::OcclusionState::VISIBLE); delegate->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate->is_expecting_call()); EXPECT_FALSE(delegate->is_expecting_call());
// Create a non-tracked window and add an observer that deletes it when its // Create a non-tracked window and add an observer that deletes it when its
// stops being animated. // stops being animated.
delegate->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 10)));
Window* window = CreateUntrackedWindow(gfx::Rect(10, 0, 10, 10)); Window* window = CreateUntrackedWindow(gfx::Rect(10, 0, 10, 10));
EXPECT_FALSE(delegate->is_expecting_call());
window->layer()->SetAnimator(test_controller.animator()); window->layer()->SetAnimator(test_controller.animator());
ObserverDestroyingWindowOnAnimationEnded observer(window); ObserverDestroyingWindowOnAnimationEnded observer(window);
window->layer()->GetAnimator()->AddObserver(&observer); window->layer()->GetAnimator()->AddObserver(&observer);
// Animate the window. WindowOcclusionTracker should add itself as an observer // Animate the window. WindowOcclusionTracker should add itself as an observer
// of its LayerAnimator (after |observer|). // of its LayerAnimator (after |observer|). Upon beginning animation, the
// window should no longer affect the occluded region.
delegate->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window->layer()->SetOpacity(0.5f); window->layer()->SetOpacity(0.5f);
EXPECT_FALSE(delegate->is_expecting_call());
// Remove the non-tracked window from its root. WindowOcclusionTracker should // Remove the non-tracked window from its root. WindowOcclusionTracker should
// remove the window from its list of animated windows and stop observing it // remove the window from its list of animated windows and stop observing it
...@@ -1342,48 +1446,87 @@ namespace { ...@@ -1342,48 +1446,87 @@ namespace {
class WindowDelegateHidingWindowIfOccluded : public MockWindowDelegate { class WindowDelegateHidingWindowIfOccluded : public MockWindowDelegate {
public: public:
WindowDelegateHidingWindowIfOccluded(Window* other_window, WindowDelegateHidingWindowIfOccluded(Window* other_window)
MockWindowDelegate* other_delegate) : other_window_(other_window) {}
: other_window_(other_window), other_delegate_(other_delegate) {}
// MockWindowDelegate: // MockWindowDelegate:
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (occlusion_state == Window::OcclusionState::HIDDEN) { if (occlusion_state == Window::OcclusionState::HIDDEN) {
other_window_->Hide(); other_window_->Hide();
other_delegate_->set_expectation(Window::OcclusionState::HIDDEN);
} }
} }
private: private:
Window* other_window_; Window* other_window_;
MockWindowDelegate* other_delegate_;
DISALLOW_COPY_AND_ASSIGN(WindowDelegateHidingWindowIfOccluded); DISALLOW_COPY_AND_ASSIGN(WindowDelegateHidingWindowIfOccluded);
}; };
class WindowDelegateWithQueuedExpectation : public MockWindowDelegate {
public:
WindowDelegateWithQueuedExpectation() = default;
void set_queued_expectation(Window::OcclusionState occlusion_state,
const SkRegion& occluded_region) {
queued_expected_occlusion_state_ = occlusion_state;
queued_expected_occluded_region_ = occluded_region;
}
// MockWindowDelegate:
void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (queued_expected_occlusion_state_ != Window::OcclusionState::UNKNOWN) {
set_expectation(queued_expected_occlusion_state_,
queued_expected_occluded_region_);
queued_expected_occlusion_state_ = Window::OcclusionState::UNKNOWN;
queued_expected_occluded_region_ = SkRegion();
}
}
private:
Window::OcclusionState queued_expected_occlusion_state_ =
Window::OcclusionState::UNKNOWN;
SkRegion queued_expected_occluded_region_ = SkRegion();
DISALLOW_COPY_AND_ASSIGN(WindowDelegateWithQueuedExpectation);
};
} // namespace } // namespace
// Verify that a window delegate can change the visibility of another window // Verify that a window delegate can change the visibility of another window
// when it is notified that its occlusion changed. // when it is notified that its occlusion changed.
TEST_F(WindowOcclusionTrackerTest, HideFromOnWindowOcclusionChanged) { TEST_F(WindowOcclusionTrackerTest, HideFromOnWindowOcclusionChanged) {
// Create a tracked window. Expect it to be visible. // Create a tracked window. Expect it to be visible.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); WindowDelegateWithQueuedExpectation* delegate_a =
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); new WindowDelegateWithQueuedExpectation();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create a tracked window. Expect it to be visible. // Create a tracked window. Expect it to be visible.
MockWindowDelegate* delegate_b = MockWindowDelegate* delegate_b =
new WindowDelegateHidingWindowIfOccluded(window_a, delegate_a); new WindowDelegateHidingWindowIfOccluded(window_a);
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(5, 5, 10, 10)); SkRegion(SkIRect::MakeXYWH(10, 0, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(10, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Hide the tracked window. It should be able to hide |window_a|. // Hide the tracked window. It should be able to hide |window_a|. Before
delegate_b->set_expectation(Window::OcclusionState::HIDDEN); // |window_a| is hidden, it will notice that the occlusion region has changed
// now that |window_b| is hidden. Then, it will be hidden by |window_b|.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_a->set_queued_expectation(Window::OcclusionState::HIDDEN,
SkRegion());
delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_b->Hide(); window_b->Hide();
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(window_a->IsVisible()); EXPECT_FALSE(window_a->IsVisible());
...@@ -1399,9 +1542,10 @@ class WindowDelegateDeletingWindow : public MockWindowDelegate { ...@@ -1399,9 +1542,10 @@ class WindowDelegateDeletingWindow : public MockWindowDelegate {
void set_other_window(Window* other_window) { other_window_ = other_window; } void set_other_window(Window* other_window) { other_window_ = other_window; }
// MockWindowDelegate: // MockWindowDelegate:
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (occlusion_state == Window::OcclusionState::OCCLUDED) { if (occlusion_state == Window::OcclusionState::OCCLUDED) {
delete other_window_; delete other_window_;
other_window_ = nullptr; other_window_ = nullptr;
...@@ -1422,29 +1566,42 @@ class WindowDelegateDeletingWindow : public MockWindowDelegate { ...@@ -1422,29 +1566,42 @@ class WindowDelegateDeletingWindow : public MockWindowDelegate {
TEST_F(WindowOcclusionTrackerTest, DeleteFromOnWindowOcclusionChanged) { TEST_F(WindowOcclusionTrackerTest, DeleteFromOnWindowOcclusionChanged) {
// Create a tracked window. Expect it to be visible. // Create a tracked window. Expect it to be visible.
WindowDelegateDeletingWindow* delegate_a = new WindowDelegateDeletingWindow(); WindowDelegateDeletingWindow* delegate_a = new WindowDelegateDeletingWindow();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Create a tracked window. Expect it to be visible. // Create a tracked window. Expect it to be visible.
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(10, 0, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(10, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create a tracked window. Expect it to be visible. // Create a tracked window. Expect it to be visible.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(
Window::OcclusionState::VISIBLE,
SkRegionFromSkIRects({SkIRect::MakeXYWH(10, 0, 10, 10),
SkIRect::MakeXYWH(20, 0, 10, 10)}));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(20, 0, 10, 10)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(20, 0, 10, 10)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(20, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// |window_c| will be deleted when |window_a| is occluded. // |window_c| will be deleted when |window_a| is occluded.
delegate_a->set_other_window(window_c); delegate_a->set_other_window(window_c);
// Move |window_b| on top of |window_a|. // Move |window_b| on top of |window_a|.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->SetBounds(window_a->bounds()); window_b->SetBounds(window_a->bounds());
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
} }
namespace { namespace {
...@@ -1456,9 +1613,10 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate { ...@@ -1456,9 +1613,10 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate {
void set_window_to_update(Window* window) { window_to_update_ = window; } void set_window_to_update(Window* window) { window_to_update_ = window; }
// MockWindowDelegate: // MockWindowDelegate:
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (!window_to_update_) if (!window_to_update_)
return; return;
...@@ -1467,10 +1625,10 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate { ...@@ -1467,10 +1625,10 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate {
if (window_to_update_->IsVisible()) { if (window_to_update_->IsVisible()) {
window_to_update_->Hide(); window_to_update_->Hide();
if (num_occlusion_change_ <= 3) if (num_occlusion_change_ <= 3)
set_expectation(Window::OcclusionState::HIDDEN); set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
} else { } else {
window_to_update_->Show(); window_to_update_->Show();
set_expectation(Window::OcclusionState::VISIBLE); set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
} }
} }
...@@ -1491,30 +1649,36 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) { ...@@ -1491,30 +1649,36 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) {
// Create 2 superposed tracked windows. // Create 2 superposed tracked windows.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// Create a hidden tracked window. // Create a hidden tracked window.
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(10, 0, 10, 10)));
delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 10)); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 10));
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
delegate_c->set_expectation(Window::OcclusionState::HIDDEN); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_c->Hide(); window_c->Hide();
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Create a tracked window. Expect it to be non-occluded. // Create a tracked window. Expect it to be non-occluded.
auto* delegate_d = new WindowDelegateChangingWindowVisibility(); auto* delegate_d = new WindowDelegateChangingWindowVisibility();
delegate_d->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(20, 0, 10, 10)));
delegate_d->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(20, 0, 10, 10)); Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(20, 0, 10, 10));
EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_d->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call());
// Store a pointer to |window_d| in |delegate_d|. This will cause a call to // Store a pointer to |window_d| in |delegate_d|. This will cause a call to
...@@ -1526,8 +1690,9 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) { ...@@ -1526,8 +1690,9 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) {
// reached, the occlusion state of all IsVisible() windows should be set to // reached, the occlusion state of all IsVisible() windows should be set to
// VISIBLE. // VISIBLE.
EXPECT_DCHECK_DEATH({ EXPECT_DCHECK_DEATH({
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
delegate_d->set_expectation(Window::OcclusionState::HIDDEN); SkRegion(SkIRect::MakeXYWH(20, 0, 10, 10)));
delegate_d->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_d->Hide(); window_d->Hide();
}); });
} }
...@@ -1537,25 +1702,25 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) { ...@@ -1537,25 +1702,25 @@ TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) {
TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) { TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) {
// Create a branch of 3 tracked windows. Expect them to be visible. // Create a branch of 3 tracked windows. Expect them to be visible.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = Window* window_b =
CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), window_a); CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), window_a);
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10), window_b);
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
// Hide |window_b| (and hence |window_c|). Expect |window_b| and |window_c| to // Hide |window_b| (and hence |window_c|). Expect |window_b| and |window_c| to
// be hidden. // be hidden.
delegate_b->set_expectation(Window::OcclusionState::HIDDEN); delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::HIDDEN); delegate_c->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_b->Hide(); window_b->Hide();
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -1565,13 +1730,13 @@ TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) { ...@@ -1565,13 +1730,13 @@ TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) {
TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) { TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) {
// Create 2 superposed tracked windows. // Create 2 superposed tracked windows.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
...@@ -1580,13 +1745,14 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) { ...@@ -1580,13 +1745,14 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) {
// occluded. // occluded.
auto shape = std::make_unique<ui::Layer::ShapeRects>(); auto shape = std::make_unique<ui::Layer::ShapeRects>();
shape->emplace_back(0, 0, 5, 5); shape->emplace_back(0, 0, 5, 5);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); // Shaped windows are not considered opaque, so the occluded region is empty.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->layer()->SetAlphaShape(std::move(shape)); window_b->layer()->SetAlphaShape(std::move(shape));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Clear the shape for the top window. The window underneath should be // Clear the shape for the top window. The window underneath should be
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->layer()->SetAlphaShape(nullptr); window_b->layer()->SetAlphaShape(nullptr);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -1596,18 +1762,21 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) { ...@@ -1596,18 +1762,21 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithAlphaShape) {
TEST_F(WindowOcclusionTrackerTest, WindowWithParentAlphaShape) { TEST_F(WindowOcclusionTrackerTest, WindowWithParentAlphaShape) {
// Create a child and parent that cover another window. // Create a child and parent that cover another window.
MockWindowDelegate* delegate_a = new MockWindowDelegate(); MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
MockWindowDelegate* delegate_b = new MockWindowDelegate(); MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeWH(10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
MockWindowDelegate* delegate_c = new MockWindowDelegate(); MockWindowDelegate* delegate_c = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
delegate_c->set_expectation(Window::OcclusionState::VISIBLE); delegate_c->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 20, 20), window_b); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 20, 20), window_b);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call());
...@@ -1616,13 +1785,13 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithParentAlphaShape) { ...@@ -1616,13 +1785,13 @@ TEST_F(WindowOcclusionTrackerTest, WindowWithParentAlphaShape) {
// occluded. // occluded.
auto shape = std::make_unique<ui::Layer::ShapeRects>(); auto shape = std::make_unique<ui::Layer::ShapeRects>();
shape->emplace_back(0, 0, 5, 5); shape->emplace_back(0, 0, 5, 5);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->layer()->SetAlphaShape(std::move(shape)); window_b->layer()->SetAlphaShape(std::move(shape));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
// Clear the shape for |window_b|. |window_a| and |window_b| should be // Clear the shape for |window_b|. |window_a| and |window_b| should be
// occluded. // occluded.
delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion());
window_b->layer()->SetAlphaShape(nullptr); window_b->layer()->SetAlphaShape(nullptr);
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
} }
...@@ -1636,9 +1805,10 @@ class WindowDelegateHidingWindow : public MockWindowDelegate { ...@@ -1636,9 +1805,10 @@ class WindowDelegateHidingWindow : public MockWindowDelegate {
void set_window_to_update(Window* window) { window_to_update_ = window; } void set_window_to_update(Window* window) { window_to_update_ = window; }
// MockWindowDelegate: // MockWindowDelegate:
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (!window_to_update_) if (!window_to_update_)
return; return;
...@@ -1653,15 +1823,28 @@ class WindowDelegateHidingWindow : public MockWindowDelegate { ...@@ -1653,15 +1823,28 @@ class WindowDelegateHidingWindow : public MockWindowDelegate {
class WindowDelegateAddingAndHidingChild : public MockWindowDelegate { class WindowDelegateAddingAndHidingChild : public MockWindowDelegate {
public: public:
WindowDelegateAddingAndHidingChild(WindowOcclusionTrackerTest* test) explicit WindowDelegateAddingAndHidingChild(WindowOcclusionTrackerTest* test)
: test_(test) {} : test_(test) {}
void set_queued_expectation(Window::OcclusionState occlusion_state,
const SkRegion& occluded_region) {
queued_expected_occlusion_state_ = occlusion_state;
queued_expected_occluded_region_ = occluded_region;
}
void set_window_to_update(Window* window) { window_to_update_ = window; } void set_window_to_update(Window* window) { window_to_update_ = window; }
// MockWindowDelegate: // MockWindowDelegate:
void OnWindowOcclusionChanged( void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
Window::OcclusionState occlusion_state) override { const SkRegion& occluded_region) override {
MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state,
occluded_region);
if (queued_expected_occlusion_state_ != Window::OcclusionState::UNKNOWN) {
set_expectation(queued_expected_occlusion_state_,
queued_expected_occluded_region_);
queued_expected_occlusion_state_ = Window::OcclusionState::UNKNOWN;
queued_expected_occluded_region_ = SkRegion();
}
if (!window_to_update_) if (!window_to_update_)
return; return;
...@@ -1677,6 +1860,9 @@ class WindowDelegateAddingAndHidingChild : public MockWindowDelegate { ...@@ -1677,6 +1860,9 @@ class WindowDelegateAddingAndHidingChild : public MockWindowDelegate {
private: private:
WindowOcclusionTrackerTest* test_; WindowOcclusionTrackerTest* test_;
Window* window_to_update_ = nullptr; Window* window_to_update_ = nullptr;
Window::OcclusionState queued_expected_occlusion_state_ =
Window::OcclusionState::UNKNOWN;
SkRegion queued_expected_occluded_region_ = SkRegion();
DISALLOW_COPY_AND_ASSIGN(WindowDelegateAddingAndHidingChild); DISALLOW_COPY_AND_ASSIGN(WindowDelegateAddingAndHidingChild);
}; };
...@@ -1691,22 +1877,27 @@ TEST_F(WindowOcclusionTrackerTest, ...@@ -1691,22 +1877,27 @@ TEST_F(WindowOcclusionTrackerTest,
root_window()->env()->GetWindowOcclusionTracker()); root_window()->env()->GetWindowOcclusionTracker());
auto* delegate_a = new WindowDelegateAddingAndHidingChild(this); auto* delegate_a = new WindowDelegateAddingAndHidingChild(this);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_a->is_expecting_call());
auto* delegate_b = new WindowDelegateHidingWindow(); auto* delegate_b = new WindowDelegateHidingWindow();
delegate_b->set_expectation(Window::OcclusionState::VISIBLE); delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(0, 10, 10, 10)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
// When |window_b| is hidden, it will hide |window_a|. |window_a| will in turn // When |window_b| is hidden, it will hide |window_a|. |window_a| will in turn
// add a child to itself and hide it. // add a child to itself and hide it.
delegate_a->set_window_to_update(window_a); delegate_a->set_window_to_update(window_a);
delegate_b->set_window_to_update(window_a); delegate_b->set_window_to_update(window_a);
// Initially A is marked as visible with no potential occlusion.
delegate_a->set_expectation(Window::OcclusionState::HIDDEN); delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::HIDDEN); delegate_a->set_queued_expectation(Window::OcclusionState::HIDDEN,
SkRegion());
delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
// Hiding a child to |window_a| and hiding it shouldn't cause occlusion to be // Hiding a child to |window_a| and hiding it shouldn't cause occlusion to be
// recomputed too many times (i.e. the call below shouldn't DCHECK). // recomputed too many times (i.e. the call below shouldn't DCHECK).
window_b->Hide(); window_b->Hide();
...@@ -1714,4 +1905,116 @@ TEST_F(WindowOcclusionTrackerTest, ...@@ -1714,4 +1905,116 @@ TEST_F(WindowOcclusionTrackerTest,
EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call());
} }
// Verify that hiding a window changes the occlusion region to show that the
// window is fully occluded.
TEST_F(WindowOcclusionTrackerTest,
HideWindowChangesOcclusionRegionToBeFullyOccluded) {
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
delegate_a->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_a->Hide();
EXPECT_FALSE(delegate_a->is_expecting_call());
}
// Test partial occlusion, test partial occlusion changing hidden, alpha shape
// occlusion from multiple windows
// Verify that a window can occlude another one partially.
TEST_F(WindowOcclusionTrackerTest, WindowOccludesWindowPartially) {
// Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b, occluding window a partially.
MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(6, 7, 8, 9)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(6, 7, 8, 9));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
// Hiding window b should stop occluding window a partially.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
delegate_b->set_expectation(Window::OcclusionState::HIDDEN, SkRegion());
window_b->Hide();
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
}
// Verify that windows with alpha shape do not affect occlusion regions.
TEST_F(WindowOcclusionTrackerTest,
WindowWithAlphaShapeDoesNotPartiallyOccludeOtherWindows) {
// Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20));
EXPECT_FALSE(delegate_a->is_expecting_call());
// Create window b, occluding window a partially.
MockWindowDelegate* delegate_b = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(6, 7, 8, 9)));
delegate_b->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(6, 7, 8, 9));
EXPECT_FALSE(delegate_a->is_expecting_call());
EXPECT_FALSE(delegate_b->is_expecting_call());
// Set a shape for window b. The window underneath should no longer be
// partially occluded.
auto shape = std::make_unique<ui::Layer::ShapeRects>();
shape->emplace_back(0, 0, 5, 5);
// Shaped windows are not considered opaque, so the occluded region is empty.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
window_b->layer()->SetAlphaShape(std::move(shape));
EXPECT_FALSE(delegate_a->is_expecting_call());
// Clear the shape for the top window. The window underneath should be
// occluded.
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
SkRegion(SkIRect::MakeXYWH(6, 7, 8, 9)));
window_b->layer()->SetAlphaShape(nullptr);
EXPECT_FALSE(delegate_a->is_expecting_call());
}
// Verify that a window can be occluded by multiple other windows.
TEST_F(WindowOcclusionTrackerTest, WindowCanBeOccludedByMultipleWindows) {
// Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion());
CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
EXPECT_FALSE(delegate_a->is_expecting_call());
SkRegion window_a_occlusion = SkRegion(SkIRect::MakeXYWH(9, 9, 5, 5));
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
window_a_occlusion);
CreateUntrackedWindow(gfx::Rect(9, 9, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
window_a_occlusion.op(SkIRect::MakeXYWH(-4, -4, 5, 5),
SkRegion::Op::kUnion_Op);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
window_a_occlusion);
CreateUntrackedWindow(gfx::Rect(-4, -4, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
window_a_occlusion.op(SkIRect::MakeXYWH(9, -4, 5, 5),
SkRegion::Op::kUnion_Op);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
window_a_occlusion);
CreateUntrackedWindow(gfx::Rect(9, -4, 5, 5));
EXPECT_FALSE(delegate_a->is_expecting_call());
window_a_occlusion.op(SkIRect::MakeXYWH(5, 5, 2, 3), SkRegion::Op::kUnion_Op);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE,
window_a_occlusion);
CreateUntrackedWindow(gfx::Rect(5, 5, 2, 3));
EXPECT_FALSE(delegate_a->is_expecting_call());
}
} // namespace aura } // namespace aura
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment