Commit 1c7d0cf8 authored by derat@chromium.org's avatar derat@chromium.org

aura: Make shadows be children of window layers.

They used to be children of the root.  This change makes
shadows track their windows' transforms and simplifies the
code (as we no longer need to track stacking or parenting
changes).  I am still slightly worried that shadows will
look strange if we scale windows up or down, but we can
figure out how to deal with that when we need to.

BUG=101977
TEST=added; also hacked up StackingController to rotate and scale windows and checked that shadows were drawn as expected

Review URL: http://codereview.chromium.org/8785005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112823 0039d316-1c4b-4281-b951-d872f2087c98
parent 1a930476
...@@ -32,24 +32,7 @@ ShadowController::~ShadowController() { ...@@ -32,24 +32,7 @@ ShadowController::~ShadowController() {
void ShadowController::OnWindowInitialized(aura::Window* window) { void ShadowController::OnWindowInitialized(aura::Window* window) {
window->AddObserver(this); window->AddObserver(this);
} HandlePossibleShadowVisibilityChange(window);
void ShadowController::OnWindowParentChanged(aura::Window* window,
aura::Window* parent) {
Shadow* shadow = GetShadowForWindow(window);
if (parent) {
if (shadow) {
parent->layer()->Add(shadow->layer());
StackShadowBelowWindow(shadow, window);
} else {
if (ShouldShowShadowForWindow(window))
CreateShadowForWindow(window);
}
} else {
if (shadow && shadow->layer()->parent())
shadow->layer()->parent()->Remove(shadow->layer());
}
} }
void ShadowController::OnWindowPropertyChanged(aura::Window* window, void ShadowController::OnWindowPropertyChanged(aura::Window* window,
...@@ -59,22 +42,11 @@ void ShadowController::OnWindowPropertyChanged(aura::Window* window, ...@@ -59,22 +42,11 @@ void ShadowController::OnWindowPropertyChanged(aura::Window* window,
HandlePossibleShadowVisibilityChange(window); HandlePossibleShadowVisibilityChange(window);
} }
void ShadowController::OnWindowVisibilityChanged(aura::Window* window,
bool visible) {
HandlePossibleShadowVisibilityChange(window);
}
void ShadowController::OnWindowBoundsChanged(aura::Window* window, void ShadowController::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& bounds) { const gfx::Rect& bounds) {
Shadow* shadow = GetShadowForWindow(window); Shadow* shadow = GetShadowForWindow(window);
if (shadow) if (shadow)
shadow->SetContentBounds(bounds); shadow->SetContentBounds(gfx::Rect(bounds.size()));
}
void ShadowController::OnWindowStackingChanged(aura::Window* window) {
Shadow* shadow = GetShadowForWindow(window);
if (shadow)
StackShadowBelowWindow(shadow, window);
} }
void ShadowController::OnWindowDestroyed(aura::Window* window) { void ShadowController::OnWindowDestroyed(aura::Window* window) {
...@@ -84,18 +56,15 @@ void ShadowController::OnWindowDestroyed(aura::Window* window) { ...@@ -84,18 +56,15 @@ void ShadowController::OnWindowDestroyed(aura::Window* window) {
bool ShadowController::ShouldShowShadowForWindow(aura::Window* window) const { bool ShadowController::ShouldShowShadowForWindow(aura::Window* window) const {
const aura::ShadowType type = static_cast<aura::ShadowType>( const aura::ShadowType type = static_cast<aura::ShadowType>(
window->GetIntProperty(aura::kShadowTypeKey)); window->GetIntProperty(aura::kShadowTypeKey));
bool requested = false;
switch (type) { switch (type) {
case aura::SHADOW_TYPE_NONE: case aura::SHADOW_TYPE_NONE:
break; return false;
case aura::SHADOW_TYPE_RECTANGULAR: case aura::SHADOW_TYPE_RECTANGULAR:
requested = true; return true;
break;
default: default:
NOTREACHED() << "Unknown shadow type " << type; NOTREACHED() << "Unknown shadow type " << type;
return false;
} }
return requested && window->layer()->visible();
} }
Shadow* ShadowController::GetShadowForWindow(aura::Window* window) { Shadow* ShadowController::GetShadowForWindow(aura::Window* window) {
...@@ -118,25 +87,9 @@ void ShadowController::CreateShadowForWindow(aura::Window* window) { ...@@ -118,25 +87,9 @@ void ShadowController::CreateShadowForWindow(aura::Window* window) {
window_shadows_.insert(make_pair(window, shadow)); window_shadows_.insert(make_pair(window, shadow));
shadow->Init(); shadow->Init();
shadow->SetContentBounds(window->bounds()); shadow->SetContentBounds(gfx::Rect(window->bounds().size()));
shadow->layer()->SetVisible(ShouldShowShadowForWindow(window)); shadow->layer()->SetVisible(ShouldShowShadowForWindow(window));
window->layer()->Add(shadow->layer());
if (window->parent()) {
window->parent()->layer()->Add(shadow->layer());
StackShadowBelowWindow(shadow.get(), window);
}
}
void ShadowController::StackShadowBelowWindow(Shadow* shadow,
aura::Window* window) {
ui::Layer* parent_layer = window->parent()->layer();
DCHECK_EQ(shadow->layer()->parent(), parent_layer);
// TODO(derat): Add a StackBelow() method and use that instead (although we
// then run the risk of other layers getting stacked between a window and its
// shadow).
parent_layer->StackAbove(shadow->layer(), window->layer());
parent_layer->StackAbove(window->layer(), shadow->layer());
} }
} // namespace internal } // namespace internal
......
...@@ -54,15 +54,10 @@ public: ...@@ -54,15 +54,10 @@ public:
virtual void OnWindowInitialized(aura::Window* window) OVERRIDE; virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
// aura::WindowObserver overrides: // aura::WindowObserver overrides:
virtual void OnWindowParentChanged(
aura::Window* window, aura::Window* parent) OVERRIDE;
virtual void OnWindowPropertyChanged( virtual void OnWindowPropertyChanged(
aura::Window* window, const char* name, void* old) OVERRIDE; aura::Window* window, const char* name, void* old) OVERRIDE;
virtual void OnWindowVisibilityChanged(
aura::Window* window, bool visible) OVERRIDE;
virtual void OnWindowBoundsChanged( virtual void OnWindowBoundsChanged(
aura::Window* window, const gfx::Rect& bounds) OVERRIDE; aura::Window* window, const gfx::Rect& bounds) OVERRIDE;
virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
private: private:
...@@ -80,12 +75,9 @@ public: ...@@ -80,12 +75,9 @@ public:
void HandlePossibleShadowVisibilityChange(aura::Window* window); void HandlePossibleShadowVisibilityChange(aura::Window* window);
// Creates a new shadow for |window| and stores it in |window_shadows_|. The // Creates a new shadow for |window| and stores it in |window_shadows_|. The
// shadow's visibility, bounds, and stacking are initialized appropriately. // shadow's bounds are initialized and it is added to the window's layer.
void CreateShadowForWindow(aura::Window* window); void CreateShadowForWindow(aura::Window* window);
// Stacks |shadow|'s layer directly beneath |window|'s layer.
void StackShadowBelowWindow(Shadow* shadow, aura::Window* window);
WindowShadowMap window_shadows_; WindowShadowMap window_shadows_;
DISALLOW_COPY_AND_ASSIGN(ShadowController); DISALLOW_COPY_AND_ASSIGN(ShadowController);
......
...@@ -30,34 +30,31 @@ TEST_F(ShadowControllerTest, Shadow) { ...@@ -30,34 +30,31 @@ TEST_F(ShadowControllerTest, Shadow) {
window->Init(ui::Layer::LAYER_HAS_TEXTURE); window->Init(ui::Layer::LAYER_HAS_TEXTURE);
window->SetParent(NULL); window->SetParent(NULL);
// We shouldn't create the shadow before the window is visible. // We should create the shadow before the window is visible (the shadow's
// layer won't get drawn yet since it's a child of the window's layer).
internal::ShadowController::TestApi api( internal::ShadowController::TestApi api(
aura_shell::Shell::GetInstance()->shadow_controller()); aura_shell::Shell::GetInstance()->shadow_controller());
EXPECT_TRUE(api.GetShadowForWindow(window.get()) == NULL);
// The shadow's visibility should be updated along with the window's.
window->Show();
const internal::Shadow* shadow = api.GetShadowForWindow(window.get()); const internal::Shadow* shadow = api.GetShadowForWindow(window.get());
ASSERT_TRUE(shadow != NULL); ASSERT_TRUE(shadow != NULL);
EXPECT_TRUE(shadow->layer()->visible()); EXPECT_TRUE(shadow->layer()->visible());
// The shadow should remain visible after window visibility changes.
window->Show();
EXPECT_TRUE(shadow->layer()->visible());
window->Hide(); window->Hide();
EXPECT_FALSE(shadow->layer()->visible()); EXPECT_TRUE(shadow->layer()->visible());
// If the shadow is disabled, it shouldn't be shown even when the window is. // If the shadow is disabled, it should be hidden.
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_NONE); window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_NONE);
window->Show(); window->Show();
EXPECT_FALSE(shadow->layer()->visible()); EXPECT_FALSE(shadow->layer()->visible());
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR); window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
EXPECT_TRUE(shadow->layer()->visible()); EXPECT_TRUE(shadow->layer()->visible());
// The shadow's layer should have the same parent as the window's. // The shadow's layer should be a child of the window's layer.
EXPECT_EQ(window->parent()->layer(), shadow->layer()->parent()); EXPECT_EQ(window->layer(), shadow->layer()->parent());
// When we remove the window from the hierarchy, its shadow should be removed
// too.
window->parent()->RemoveChild(window.get()); window->parent()->RemoveChild(window.get());
EXPECT_TRUE(shadow->layer()->parent() == NULL);
aura::Window* window_ptr = window.get(); aura::Window* window_ptr = window.get();
window.reset(); window.reset();
EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL); EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL);
...@@ -74,59 +71,21 @@ TEST_F(ShadowControllerTest, ShadowBounds) { ...@@ -74,59 +71,21 @@ TEST_F(ShadowControllerTest, ShadowBounds) {
const gfx::Rect kOldBounds(20, 30, 400, 300); const gfx::Rect kOldBounds(20, 30, 400, 300);
window->SetBounds(kOldBounds); window->SetBounds(kOldBounds);
// When the shadow is first created, it should use the window's bounds. // When the shadow is first created, it should use the window's size (but
// remain at the origin, since it's a child of the window's layer).
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR); window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
internal::ShadowController::TestApi api( internal::ShadowController::TestApi api(
aura_shell::Shell::GetInstance()->shadow_controller()); aura_shell::Shell::GetInstance()->shadow_controller());
const internal::Shadow* shadow = api.GetShadowForWindow(window.get()); const internal::Shadow* shadow = api.GetShadowForWindow(window.get());
ASSERT_TRUE(shadow != NULL); ASSERT_TRUE(shadow != NULL);
EXPECT_EQ(kOldBounds, shadow->content_bounds()); EXPECT_EQ(gfx::Rect(kOldBounds.size()).ToString(),
shadow->content_bounds().ToString());
// When we change the window's bounds, the shadow's should be updated too. // When we change the window's bounds, the shadow's should be updated too.
gfx::Rect kNewBounds(50, 60, 500, 400); gfx::Rect kNewBounds(50, 60, 500, 400);
window->SetBounds(kNewBounds); window->SetBounds(kNewBounds);
EXPECT_EQ(kNewBounds, shadow->content_bounds()); EXPECT_EQ(gfx::Rect(kNewBounds.size()).ToString(),
} shadow->content_bounds().ToString());
// Test that shadows are stacked correctly.
TEST_F(ShadowControllerTest, Stacking) {
scoped_ptr<aura::Window> window(new aura::Window(NULL));
window->SetType(aura::WINDOW_TYPE_NORMAL);
window->Init(ui::Layer::LAYER_HAS_TEXTURE);
window->SetParent(NULL);
window->Show();
// Create a second window. It will appear above the first window.
scoped_ptr<aura::Window> window2(new aura::Window(NULL));
window2->SetType(aura::WINDOW_TYPE_NORMAL);
window2->Init(ui::Layer::LAYER_HAS_TEXTURE);
window2->SetParent(NULL);
window2->Show();
// Enable a shadow on the first window.
window->SetIntProperty(aura::kShadowTypeKey, aura::SHADOW_TYPE_RECTANGULAR);
internal::ShadowController::TestApi api(
aura_shell::Shell::GetInstance()->shadow_controller());
const internal::Shadow* shadow = api.GetShadowForWindow(window.get());
ASSERT_TRUE(shadow != NULL);
// Check that the second window is above the first window and that the first
// window is above its shadow.
ui::Layer* parent_layer = window->layer()->parent();
ASSERT_EQ(parent_layer, shadow->layer()->parent());
ASSERT_EQ(parent_layer, window2->layer()->parent());
const std::vector<ui::Layer*>& layers = parent_layer->children();
EXPECT_GT(std::find(layers.begin(), layers.end(), window2->layer()),
std::find(layers.begin(), layers.end(), window->layer()));
EXPECT_GT(std::find(layers.begin(), layers.end(), window->layer()),
std::find(layers.begin(), layers.end(), shadow->layer()));
// Raise the first window to the top and check that its shadow comes with it.
window->parent()->StackChildAtTop(window.get());
EXPECT_GT(std::find(layers.begin(), layers.end(), window->layer()),
std::find(layers.begin(), layers.end(), shadow->layer()));
EXPECT_GT(std::find(layers.begin(), layers.end(), shadow->layer()),
std::find(layers.begin(), layers.end(), window2->layer()));
} }
} // namespace test } // namespace test
......
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