Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / wm / core / shadow_controller_unittest.cc
blob477e3ace9bae9d137bdff74f88e63355847621a7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/wm/core/shadow_controller.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/memory/scoped_ptr.h"
11 #include "ui/aura/client/window_tree_client.h"
12 #include "ui/aura/test/aura_test_base.h"
13 #include "ui/aura/window.h"
14 #include "ui/aura/window_event_dispatcher.h"
15 #include "ui/compositor/layer.h"
16 #include "ui/wm/core/default_activation_client.h"
17 #include "ui/wm/core/shadow.h"
18 #include "ui/wm/core/shadow_types.h"
19 #include "ui/wm/core/window_util.h"
20 #include "ui/wm/core/wm_state.h"
21 #include "ui/wm/public/activation_client.h"
23 namespace wm {
25 class ShadowControllerTest : public aura::test::AuraTestBase {
26 public:
27 ShadowControllerTest() {}
28 virtual ~ShadowControllerTest() {}
30 virtual void SetUp() OVERRIDE {
31 wm_state_.reset(new wm::WMState);
32 AuraTestBase::SetUp();
33 new wm::DefaultActivationClient(root_window());
34 aura::client::ActivationClient* activation_client =
35 aura::client::GetActivationClient(root_window());
36 shadow_controller_.reset(new ShadowController(activation_client));
38 virtual void TearDown() OVERRIDE {
39 shadow_controller_.reset();
40 AuraTestBase::TearDown();
41 wm_state_.reset();
44 protected:
45 ShadowController* shadow_controller() { return shadow_controller_.get(); }
47 void ActivateWindow(aura::Window* window) {
48 DCHECK(window);
49 DCHECK(window->GetRootWindow());
50 aura::client::GetActivationClient(window->GetRootWindow())->ActivateWindow(
51 window);
54 private:
55 scoped_ptr<ShadowController> shadow_controller_;
56 scoped_ptr<wm::WMState> wm_state_;
58 DISALLOW_COPY_AND_ASSIGN(ShadowControllerTest);
61 // Tests that various methods in Window update the Shadow object as expected.
62 TEST_F(ShadowControllerTest, Shadow) {
63 scoped_ptr<aura::Window> window(new aura::Window(NULL));
64 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
65 window->Init(aura::WINDOW_LAYER_TEXTURED);
66 ParentWindow(window.get());
68 // We should create the shadow before the window is visible (the shadow's
69 // layer won't get drawn yet since it's a child of the window's layer).
70 ShadowController::TestApi api(shadow_controller());
71 const Shadow* shadow = api.GetShadowForWindow(window.get());
72 ASSERT_TRUE(shadow != NULL);
73 EXPECT_TRUE(shadow->layer()->visible());
75 // The shadow should remain visible after window visibility changes.
76 window->Show();
77 EXPECT_TRUE(shadow->layer()->visible());
78 window->Hide();
79 EXPECT_TRUE(shadow->layer()->visible());
81 // If the shadow is disabled, it should be hidden.
82 SetShadowType(window.get(), SHADOW_TYPE_NONE);
83 window->Show();
84 EXPECT_FALSE(shadow->layer()->visible());
85 SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR);
86 EXPECT_TRUE(shadow->layer()->visible());
88 // The shadow's layer should be a child of the window's layer.
89 EXPECT_EQ(window->layer(), shadow->layer()->parent());
91 window->parent()->RemoveChild(window.get());
92 aura::Window* window_ptr = window.get();
93 window.reset();
94 EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL);
97 // Tests that the window's shadow's bounds are updated correctly.
98 TEST_F(ShadowControllerTest, ShadowBounds) {
99 scoped_ptr<aura::Window> window(new aura::Window(NULL));
100 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
101 window->Init(aura::WINDOW_LAYER_TEXTURED);
102 ParentWindow(window.get());
103 window->Show();
105 const gfx::Rect kOldBounds(20, 30, 400, 300);
106 window->SetBounds(kOldBounds);
108 // When the shadow is first created, it should use the window's size (but
109 // remain at the origin, since it's a child of the window's layer).
110 SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR);
111 ShadowController::TestApi api(shadow_controller());
112 const Shadow* shadow = api.GetShadowForWindow(window.get());
113 ASSERT_TRUE(shadow != NULL);
114 EXPECT_EQ(gfx::Rect(kOldBounds.size()).ToString(),
115 shadow->content_bounds().ToString());
117 // When we change the window's bounds, the shadow's should be updated too.
118 gfx::Rect kNewBounds(50, 60, 500, 400);
119 window->SetBounds(kNewBounds);
120 EXPECT_EQ(gfx::Rect(kNewBounds.size()).ToString(),
121 shadow->content_bounds().ToString());
124 // Tests that activating a window changes the shadow style.
125 TEST_F(ShadowControllerTest, ShadowStyle) {
126 ShadowController::TestApi api(shadow_controller());
128 scoped_ptr<aura::Window> window1(new aura::Window(NULL));
129 window1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
130 window1->Init(aura::WINDOW_LAYER_TEXTURED);
131 ParentWindow(window1.get());
132 window1->SetBounds(gfx::Rect(10, 20, 300, 400));
133 window1->Show();
134 ActivateWindow(window1.get());
136 // window1 is active, so style should have active appearance.
137 Shadow* shadow1 = api.GetShadowForWindow(window1.get());
138 ASSERT_TRUE(shadow1 != NULL);
139 EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
141 // Create another window and activate it.
142 scoped_ptr<aura::Window> window2(new aura::Window(NULL));
143 window2->SetType(ui::wm::WINDOW_TYPE_NORMAL);
144 window2->Init(aura::WINDOW_LAYER_TEXTURED);
145 ParentWindow(window2.get());
146 window2->SetBounds(gfx::Rect(11, 21, 301, 401));
147 window2->Show();
148 ActivateWindow(window2.get());
150 // window1 is now inactive, so shadow should go inactive.
151 Shadow* shadow2 = api.GetShadowForWindow(window2.get());
152 ASSERT_TRUE(shadow2 != NULL);
153 EXPECT_EQ(Shadow::STYLE_INACTIVE, shadow1->style());
154 EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow2->style());
157 // Tests that we use smaller shadows for tooltips and menus.
158 TEST_F(ShadowControllerTest, SmallShadowsForTooltipsAndMenus) {
159 ShadowController::TestApi api(shadow_controller());
161 scoped_ptr<aura::Window> tooltip_window(new aura::Window(NULL));
162 tooltip_window->SetType(ui::wm::WINDOW_TYPE_TOOLTIP);
163 tooltip_window->Init(aura::WINDOW_LAYER_TEXTURED);
164 ParentWindow(tooltip_window.get());
165 tooltip_window->SetBounds(gfx::Rect(10, 20, 300, 400));
166 tooltip_window->Show();
168 Shadow* tooltip_shadow = api.GetShadowForWindow(tooltip_window.get());
169 ASSERT_TRUE(tooltip_shadow != NULL);
170 EXPECT_EQ(Shadow::STYLE_SMALL, tooltip_shadow->style());
172 scoped_ptr<aura::Window> menu_window(new aura::Window(NULL));
173 menu_window->SetType(ui::wm::WINDOW_TYPE_MENU);
174 menu_window->Init(aura::WINDOW_LAYER_TEXTURED);
175 ParentWindow(menu_window.get());
176 menu_window->SetBounds(gfx::Rect(10, 20, 300, 400));
177 menu_window->Show();
179 Shadow* menu_shadow = api.GetShadowForWindow(tooltip_window.get());
180 ASSERT_TRUE(menu_shadow != NULL);
181 EXPECT_EQ(Shadow::STYLE_SMALL, menu_shadow->style());
184 // http://crbug.com/120210 - transient parents of certain types of transients
185 // should not lose their shadow when they lose activation to the transient.
186 TEST_F(ShadowControllerTest, TransientParentKeepsActiveShadow) {
187 ShadowController::TestApi api(shadow_controller());
189 scoped_ptr<aura::Window> window1(new aura::Window(NULL));
190 window1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
191 window1->Init(aura::WINDOW_LAYER_TEXTURED);
192 ParentWindow(window1.get());
193 window1->SetBounds(gfx::Rect(10, 20, 300, 400));
194 window1->Show();
195 ActivateWindow(window1.get());
197 // window1 is active, so style should have active appearance.
198 Shadow* shadow1 = api.GetShadowForWindow(window1.get());
199 ASSERT_TRUE(shadow1 != NULL);
200 EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
202 // Create a window that is transient to window1, and that has the 'hide on
203 // deactivate' property set. Upon activation, window1 should still have an
204 // active shadow.
205 scoped_ptr<aura::Window> window2(new aura::Window(NULL));
206 window2->SetType(ui::wm::WINDOW_TYPE_NORMAL);
207 window2->Init(aura::WINDOW_LAYER_TEXTURED);
208 ParentWindow(window2.get());
209 window2->SetBounds(gfx::Rect(11, 21, 301, 401));
210 AddTransientChild(window1.get(), window2.get());
211 aura::client::SetHideOnDeactivate(window2.get(), true);
212 window2->Show();
213 ActivateWindow(window2.get());
215 // window1 is now inactive, but its shadow should still appear active.
216 EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
219 TEST_F(ShadowControllerTest, AlwaysActive) {
220 ShadowController::TestApi api(shadow_controller());
222 scoped_ptr<aura::Window> window1(new aura::Window(NULL));
223 window1->SetType(ui::wm::WINDOW_TYPE_NORMAL);
224 window1->Init(aura::WINDOW_LAYER_TEXTURED);
225 ParentWindow(window1.get());
226 window1->SetBounds(gfx::Rect(10, 20, 300, 400));
227 SetShadowType(window1.get(), SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE);
228 window1->Show();
230 // Showing the window with SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE should
231 // have active shadow.
232 EXPECT_EQ(Shadow::STYLE_ACTIVE,
233 api.GetShadowForWindow(window1.get())->style());
235 scoped_ptr<aura::Window> window2(new aura::Window(NULL));
236 window2->SetType(ui::wm::WINDOW_TYPE_NORMAL);
237 window2->Init(aura::WINDOW_LAYER_TEXTURED);
238 ParentWindow(window2.get());
239 window2->SetBounds(gfx::Rect(11, 21, 301, 401));
240 window2->Show();
242 // Setting SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE to the visible window
243 // should set the active shadow.
244 EXPECT_EQ(Shadow::STYLE_INACTIVE,
245 api.GetShadowForWindow(window2.get())->style());
246 SetShadowType(window2.get(), SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE);
247 EXPECT_EQ(Shadow::STYLE_ACTIVE,
248 api.GetShadowForWindow(window2.get())->style());
250 // Activation should not change the shadow style.
251 ActivateWindow(window2.get());
252 EXPECT_EQ(Shadow::STYLE_ACTIVE,
253 api.GetShadowForWindow(window1.get())->style());
254 EXPECT_EQ(Shadow::STYLE_ACTIVE,
255 api.GetShadowForWindow(window2.get())->style());
257 ActivateWindow(window1.get());
258 EXPECT_EQ(Shadow::STYLE_ACTIVE,
259 api.GetShadowForWindow(window1.get())->style());
260 EXPECT_EQ(Shadow::STYLE_ACTIVE,
261 api.GetShadowForWindow(window2.get())->style());
263 // Restore the style to plain RECTANGULAR and make sure the inactive window
264 // gets the inactive shadow.
265 SetShadowType(window1.get(), SHADOW_TYPE_RECTANGULAR);
266 SetShadowType(window2.get(), SHADOW_TYPE_RECTANGULAR);
267 EXPECT_EQ(Shadow::STYLE_ACTIVE,
268 api.GetShadowForWindow(window1.get())->style());
269 EXPECT_EQ(Shadow::STYLE_INACTIVE,
270 api.GetShadowForWindow(window2.get())->style());
273 } // namespace wm