blob: b972d5066f0e294b80260393561567221eb152c7 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/aura/window_occlusion_change_builder.h"
#include <memory>
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
namespace aura {
namespace {
// A delegate that remembers the occlusion info of its window.
class OcclusionTrackWindowDelegate : public test::TestWindowDelegate {
public:
OcclusionTrackWindowDelegate() = default;
~OcclusionTrackWindowDelegate() override = default;
bool occlusion_change_count() const { return occlusion_change_count_; }
Window::OcclusionState last_occlusion_state() const {
return last_occlusion_state_;
}
const SkRegion& last_occluded_region() const { return last_occluded_region_; }
private:
// test::TestWindowDelegate:
void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state,
const SkRegion& occluded_region) override {
++occlusion_change_count_;
last_occlusion_state_ = occlusion_state;
last_occluded_region_ = occluded_region;
}
int occlusion_change_count_ = 0;
Window::OcclusionState last_occlusion_state_ =
Window::OcclusionState::UNKNOWN;
SkRegion last_occluded_region_;
DISALLOW_COPY_AND_ASSIGN(OcclusionTrackWindowDelegate);
};
} // namespace
class WindowOcclusionChangeBuilderTest : public test::AuraTestBase {
public:
WindowOcclusionChangeBuilderTest() = default;
~WindowOcclusionChangeBuilderTest() override = default;
std::unique_ptr<Window> CreateTestWindow(
OcclusionTrackWindowDelegate* delegate) {
auto window = std::make_unique<Window>(delegate);
window->set_owned_by_parent(false);
window->SetType(client::WINDOW_TYPE_NORMAL);
window->Init(ui::LAYER_TEXTURED);
window->Show();
root_window()->AddChild(window.get());
return window;
}
private:
DISALLOW_COPY_AND_ASSIGN(WindowOcclusionChangeBuilderTest);
};
// Test that window occlusion info is updated after commit.
TEST_F(WindowOcclusionChangeBuilderTest, SingleWindow) {
SkRegion region;
region.setRect(1, 2, 3, 4);
for (const auto state :
{Window::OcclusionState::VISIBLE, Window::OcclusionState::OCCLUDED,
Window::OcclusionState::HIDDEN}) {
OcclusionTrackWindowDelegate delegate;
auto window = CreateTestWindow(&delegate);
auto builder = WindowOcclusionChangeBuilder::Create();
builder->Add(window.get(), state, region);
// Change should not be applied before Commit call.
EXPECT_EQ(0, delegate.occlusion_change_count());
// All changes are committed when builder is released.
builder.reset();
EXPECT_EQ(1, delegate.occlusion_change_count());
EXPECT_EQ(state, delegate.last_occlusion_state());
EXPECT_EQ(region, delegate.last_occluded_region());
}
}
// Test updating multiple windows.
TEST_F(WindowOcclusionChangeBuilderTest, MultipleWindow) {
auto builder = WindowOcclusionChangeBuilder::Create();
OcclusionTrackWindowDelegate delegate1;
auto window1 = CreateTestWindow(&delegate1);
const Window::OcclusionState state1 = Window::OcclusionState::VISIBLE;
SkRegion region1;
region1.setRect(1, 2, 3, 4);
builder->Add(window1.get(), state1, region1);
OcclusionTrackWindowDelegate delegate2;
auto window2 = CreateTestWindow(&delegate2);
const Window::OcclusionState state2 = Window::OcclusionState::OCCLUDED;
SkRegion region2;
region2.setRect(5, 6, 7, 8);
builder->Add(window2.get(), state2, region2);
// Changes should not be applied before Commit call.
EXPECT_EQ(0, delegate1.occlusion_change_count());
EXPECT_EQ(0, delegate2.occlusion_change_count());
// All changes are committed when builder is released.
builder.reset();
EXPECT_EQ(1, delegate1.occlusion_change_count());
EXPECT_EQ(state1, delegate1.last_occlusion_state());
EXPECT_EQ(region1, delegate1.last_occluded_region());
EXPECT_EQ(1, delegate2.occlusion_change_count());
EXPECT_EQ(state2, delegate2.last_occlusion_state());
EXPECT_EQ(region2, delegate2.last_occluded_region());
}
// Tests that the last change wins when there are multiple changes on the same
// window.
TEST_F(WindowOcclusionChangeBuilderTest, MultipleChanges) {
OcclusionTrackWindowDelegate delegate;
auto window = CreateTestWindow(&delegate);
auto builder = WindowOcclusionChangeBuilder::Create();
builder->Add(window.get(), Window::OcclusionState::VISIBLE, SkRegion());
builder->Add(window.get(), Window::OcclusionState::HIDDEN, SkRegion());
SkRegion region;
region.setRect(1, 2, 3, 4);
builder->Add(window.get(), Window::OcclusionState::OCCLUDED, region);
// All changes are committed when builder is released.
builder.reset();
EXPECT_EQ(1, delegate.occlusion_change_count());
EXPECT_EQ(Window::OcclusionState::OCCLUDED, delegate.last_occlusion_state());
EXPECT_EQ(region, delegate.last_occluded_region());
}
// Test that occlusion info is not updated if window is destroyed before commit.
TEST_F(WindowOcclusionChangeBuilderTest, DestroyBeforeCommit) {
OcclusionTrackWindowDelegate delegate;
auto window = CreateTestWindow(&delegate);
auto builder = WindowOcclusionChangeBuilder::Create();
builder->Add(window.get(), Window::OcclusionState::VISIBLE, SkRegion());
// Destroy window before applying the changes.
window.reset();
// All changes are committed when builder is released.
builder.reset();
// Occlusion info is not updated.
EXPECT_EQ(0, delegate.occlusion_change_count());
}
} // namespace aura