1 // Copyright 2014 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.
8 #include "athena/screen/screen_manager_impl.h"
9 #include "athena/test/base/athena_test_base.h"
10 #include "athena/test/base/test_windows.h"
11 #include "athena/util/container_priorities.h"
12 #include "ui/aura/test/test_window_delegate.h"
13 #include "ui/aura/window.h"
14 #include "ui/aura/window_targeter.h"
15 #include "ui/events/test/event_generator.h"
16 #include "ui/wm/core/window_util.h"
18 using ScreenManagerTest
= athena::test::AthenaTestBase
;
19 using AthenaFocusRuleTest
= athena::test::AthenaTestBase
;
24 const int kTestZOrderPriority
= 10;
26 aura::Window
* Create(const std::string
& name
, int z_order_priority
) {
27 ScreenManager::ContainerParams
params(name
, z_order_priority
);
28 return ScreenManager::Get()->CreateContainer(params
);
31 aura::Window
* CreateWindow(aura::Window
* container
,
32 aura::WindowDelegate
* delegate
,
33 const gfx::Rect
& bounds
) {
34 aura::Window
* window
= new aura::Window(delegate
);
35 window
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
36 window
->Init(aura::WINDOW_LAYER_TEXTURED
);
37 container
->AddChild(window
);
39 window
->SetBounds(bounds
);
43 void CheckZOrder(aura::Window
* w1
, aura::Window
* w2
) {
44 aura::Window
* parent
= w1
->parent();
45 const aura::Window::Windows
& children
= parent
->children();
46 aura::Window::Windows::const_iterator begin_iter
= children
.begin();
47 aura::Window::Windows::const_iterator end_iter
= children
.end();
49 aura::Window::Windows::const_iterator w1_iter
=
50 std::find(begin_iter
, end_iter
, w1
);
51 aura::Window::Windows::const_iterator w2_iter
=
52 std::find(begin_iter
, end_iter
, w2
);
53 EXPECT_NE(end_iter
, w1_iter
);
54 EXPECT_NE(end_iter
, w2_iter
);
55 EXPECT_TRUE(w1_iter
< w2_iter
);
60 TEST_F(ScreenManagerTest
, CreateContainer
) {
61 size_t num_containers
= root_window()->children().size();
63 aura::Window
* container
= Create("test", kTestZOrderPriority
);
64 EXPECT_EQ("test", container
->name());
66 const aura::Window::Windows
& containers
= root_window()->children();
67 EXPECT_EQ(num_containers
+ 1, containers
.size());
68 EXPECT_NE(containers
.end(),
69 std::find(containers
.begin(), containers
.end(), container
));
72 TEST_F(ScreenManagerTest
, Zorder
) {
73 aura::Window
* window_10
= Create("test10", 10);
74 aura::Window
* window_11
= Create("test11", 11);
75 aura::Window
* window_12
= Create("test12", 12);
79 CheckZOrder(window_10
, window_11
);
80 CheckZOrder(window_11
, window_12
);
83 SCOPED_TRACE("Delete");
85 CheckZOrder(window_10
, window_12
);
88 SCOPED_TRACE("Insert");
89 window_11
= Create("test11", 11);
90 CheckZOrder(window_10
, window_11
);
91 CheckZOrder(window_11
, window_12
);
95 TEST_F(ScreenManagerTest
, NonActivatableContainer
) {
96 ScreenManager::ContainerParams
non_activatable(
97 "non_activatable", kTestZOrderPriority
);
98 non_activatable
.can_activate_children
= false;
99 aura::Window
* no_activatable_container
=
100 ScreenManager::Get()->CreateContainer(non_activatable
);
102 ScreenManager::ContainerParams
activatable(
103 "activatable", kTestZOrderPriority
+ 1);
104 activatable
.can_activate_children
= true;
105 aura::Window
* activatable_container
=
106 ScreenManager::Get()->CreateContainer(activatable
);
108 scoped_ptr
<aura::Window
> window(CreateWindow(
109 no_activatable_container
, nullptr, gfx::Rect(0, 0, 100, 100)));
110 EXPECT_FALSE(wm::CanActivateWindow(window
.get()));
112 activatable_container
->AddChild(window
.get());
113 EXPECT_TRUE(wm::CanActivateWindow(window
.get()));
116 TEST_F(ScreenManagerTest
, BlockInputsShouldNotBlockVirtualKeyboard
) {
117 ScreenManager::ContainerParams
block_params("blocking", kTestZOrderPriority
);
118 block_params
.can_activate_children
= true;
119 block_params
.block_events
= true;
120 aura::Window
* block_container
=
121 ScreenManager::Get()->CreateContainer(block_params
);
123 aura::test::EventCountDelegate block_delegate
;
124 scoped_ptr
<aura::Window
> block_window(CreateWindow(
125 block_container
, &block_delegate
, gfx::Rect(0, 0, 100, 100)));
126 EXPECT_TRUE(wm::CanActivateWindow(block_window
.get()));
128 // Create a normal container appearing over the |block_container|. This is
129 // essentially the case of virtual keyboard.
130 ScreenManager::ContainerParams
vk_params("virtual keyboard",
131 kTestZOrderPriority
+ 1);
132 vk_params
.can_activate_children
= true;
133 aura::Window
* vk_container
= ScreenManager::Get()->CreateContainer(vk_params
);
135 aura::test::EventCountDelegate vk_delegate
;
136 scoped_ptr
<aura::Window
> vk_window(
137 CreateWindow(vk_container
, &vk_delegate
, gfx::Rect(0, 20, 100, 80)));
138 EXPECT_TRUE(wm::CanActivateWindow(vk_window
.get()));
140 ui::test::EventGenerator
event_generator(root_window());
141 event_generator
.MoveMouseTo(10, 25);
142 event_generator
.ClickLeftButton();
143 EXPECT_EQ("0 0", block_delegate
.GetMouseButtonCountsAndReset());
144 EXPECT_EQ("1 1", vk_delegate
.GetMouseButtonCountsAndReset());
147 TEST_F(ScreenManagerTest
, DefaultContainer
) {
148 ScreenManagerImpl
* impl
=
149 static_cast<ScreenManagerImpl
*>(ScreenManager::Get());
150 aura::Window
* original_default
= impl
->FindContainerByPriority(CP_DEFAULT
);
151 aura::Window
* parent
= original_default
->parent();
152 // Temporarily remove the original default container from tree.
153 parent
->RemoveChild(original_default
);
155 ScreenManager::ContainerParams
params("new_default", CP_END
+ 1);
156 params
.default_parent
= true;
157 params
.modal_container_priority
= CP_END
+ 2;
158 aura::Window
* new_default
= ScreenManager::Get()->CreateContainer(params
);
159 aura::Window
* w
= test::CreateNormalWindow(nullptr, nullptr).release();
160 EXPECT_EQ(new_default
, w
->parent());
163 // Add the original back to shutdown properly.
164 parent
->AddChild(original_default
);
167 TEST_F(AthenaFocusRuleTest
, FocusTravarsalFromSameContainer
) {
168 ScreenManager::ContainerParams
params("contaier", kTestZOrderPriority
);
169 params
.can_activate_children
= true;
170 scoped_ptr
<aura::Window
>
171 container(ScreenManager::Get()->CreateContainer(params
));
173 scoped_ptr
<aura::Window
> w1(CreateWindow(
174 container
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
175 wm::ActivateWindow(w1
.get());
176 EXPECT_TRUE(wm::IsActiveWindow(w1
.get()));
178 scoped_ptr
<aura::Window
> w2(CreateWindow(
179 container
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
180 EXPECT_TRUE(wm::IsActiveWindow(w1
.get()));
182 container
->RemoveChild(w1
.get());
183 EXPECT_TRUE(wm::IsActiveWindow(w2
.get()));
186 TEST_F(AthenaFocusRuleTest
, FocusTravarsalFromOtherContainer
) {
187 ScreenManager::ContainerParams
params2("contaier2", kTestZOrderPriority
+ 1);
188 params2
.can_activate_children
= true;
189 scoped_ptr
<aura::Window
>
190 container2(ScreenManager::Get()->CreateContainer(params2
));
191 scoped_ptr
<aura::Window
> w2(CreateWindow(
192 container2
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
193 wm::ActivateWindow(w2
.get());
194 EXPECT_TRUE(wm::IsActiveWindow(w2
.get()));
196 ScreenManager::ContainerParams
params1("contaier1", kTestZOrderPriority
);
197 params1
.can_activate_children
= true;
198 scoped_ptr
<aura::Window
>
199 container1(ScreenManager::Get()->CreateContainer(params1
));
200 ScreenManager::ContainerParams
params3("contaier3", kTestZOrderPriority
+ 2);
201 params3
.can_activate_children
= true;
202 scoped_ptr
<aura::Window
>
203 container3(ScreenManager::Get()->CreateContainer(params3
));
204 scoped_ptr
<aura::Window
> w1(CreateWindow(
205 container1
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
206 scoped_ptr
<aura::Window
> w3(CreateWindow(
207 container3
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
209 EXPECT_TRUE(wm::IsActiveWindow(w2
.get()));
211 container2
->RemoveChild(w2
.get());
212 // Focus moves to a window in the front contaier.
213 EXPECT_TRUE(wm::IsActiveWindow(w3
.get()));
215 container3
->RemoveChild(w3
.get());
216 // Focus moves to a window in the back contaier.
217 EXPECT_TRUE(wm::IsActiveWindow(w1
.get()));
220 TEST_F(AthenaFocusRuleTest
, FocusTravarsalFromEventBlockedContainer
) {
221 ScreenManager::ContainerParams
params1("contaier1", kTestZOrderPriority
+ 1);
222 params1
.can_activate_children
= true;
223 scoped_ptr
<aura::Window
>
224 container1(ScreenManager::Get()->CreateContainer(params1
));
226 ScreenManager::ContainerParams
params2("contaier2", kTestZOrderPriority
+ 2);
227 params2
.can_activate_children
= true;
228 params2
.block_events
= true;
229 scoped_ptr
<aura::Window
>
230 container2(ScreenManager::Get()->CreateContainer(params2
));
232 scoped_ptr
<aura::Window
> w1(CreateWindow(
233 container1
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
234 scoped_ptr
<aura::Window
> w2(CreateWindow(
235 container2
.get(), nullptr, gfx::Rect(0, 0, 100, 100)));
237 wm::ActivateWindow(w2
.get());
238 EXPECT_TRUE(wm::IsActiveWindow(w2
.get()));
240 // Confirm that w1 can't get the focus.
241 wm::ActivateWindow(w1
.get());
242 EXPECT_FALSE(wm::IsActiveWindow(w1
.get()));
243 EXPECT_TRUE(wm::IsActiveWindow(w2
.get()));
249 EXPECT_TRUE(wm::IsActiveWindow(w1
.get()));
254 class ScreenManagerTargeterTest
255 : public athena::test::AthenaTestBase
,
256 public testing::WithParamInterface
<bool> {
258 ScreenManagerTargeterTest()
259 : targeter_(GetParam() ? nullptr : new aura::WindowTargeter
) {}
260 ~ScreenManagerTargeterTest() override
{}
263 scoped_ptr
<ui::EventTargeter
> targeter_
;
266 DISALLOW_COPY_AND_ASSIGN(ScreenManagerTargeterTest
);
271 TEST_P(ScreenManagerTargeterTest
, BlockContainer
) {
272 ScreenManager::ContainerParams
normal_params(
273 "normal", kTestZOrderPriority
);
274 normal_params
.can_activate_children
= true;
275 aura::Window
* normal_container
=
276 ScreenManager::Get()->CreateContainer(normal_params
);
277 normal_container
->SetEventTargeter(targeter_
.Pass());
279 aura::test::EventCountDelegate normal_delegate
;
280 scoped_ptr
<aura::Window
> normal_window(CreateWindow(
281 normal_container
, &normal_delegate
, gfx::Rect(0, 0, 100, 100)));
283 EXPECT_TRUE(wm::CanActivateWindow(normal_window
.get()));
284 wm::ActivateWindow(normal_window
.get());
285 ui::test::EventGenerator
event_generator(root_window());
286 event_generator
.MoveMouseTo(0, 0);
287 event_generator
.ClickLeftButton();
288 EXPECT_EQ("1 1", normal_delegate
.GetMouseButtonCountsAndReset());
289 event_generator
.PressKey(ui::VKEY_A
, ui::EF_NONE
);
290 event_generator
.ReleaseKey(ui::VKEY_A
, ui::EF_NONE
);
291 EXPECT_EQ("1 1", normal_delegate
.GetKeyCountsAndReset());
293 ScreenManager::ContainerParams
block_params("blocking",
294 kTestZOrderPriority
+ 1);
295 block_params
.can_activate_children
= true;
296 block_params
.block_events
= true;
297 aura::Window
* block_container
=
298 ScreenManager::Get()->CreateContainer(block_params
);
300 EXPECT_FALSE(wm::CanActivateWindow(normal_window
.get()));
302 aura::test::EventCountDelegate block_delegate
;
303 scoped_ptr
<aura::Window
> block_window(CreateWindow(
304 block_container
, &block_delegate
, gfx::Rect(10, 10, 100, 100)));
305 EXPECT_TRUE(wm::CanActivateWindow(block_window
.get()));
307 wm::ActivateWindow(block_window
.get());
309 // (0, 0) is still on normal_window, but the event should not go there
310 // because blockbing_container prevents it.
311 event_generator
.MoveMouseTo(0, 0);
312 event_generator
.ClickLeftButton();
313 EXPECT_EQ("0 0", normal_delegate
.GetMouseButtonCountsAndReset());
314 EXPECT_EQ("0 0", block_delegate
.GetMouseButtonCountsAndReset());
315 event_generator
.MoveMouseWheel(0, 10);
316 // EXPECT_EQ(0, normal_event_counter.num_scroll_events());
318 event_generator
.MoveMouseTo(20, 20);
319 event_generator
.ClickLeftButton();
320 EXPECT_EQ("1 1", block_delegate
.GetMouseButtonCountsAndReset());
322 event_generator
.PressKey(ui::VKEY_A
, ui::EF_NONE
);
323 event_generator
.ReleaseKey(ui::VKEY_A
, ui::EF_NONE
);
324 EXPECT_EQ("0 0", normal_delegate
.GetKeyCountsAndReset());
325 EXPECT_EQ("1 1", block_delegate
.GetKeyCountsAndReset());
328 TEST_P(ScreenManagerTargeterTest
, BlockAndMouseCapture
) {
329 ScreenManager::ContainerParams
normal_params(
330 "normal", kTestZOrderPriority
);
331 normal_params
.can_activate_children
= true;
332 aura::Window
* normal_container
=
333 ScreenManager::Get()->CreateContainer(normal_params
);
334 normal_container
->SetEventTargeter(targeter_
.Pass());
336 aura::test::EventCountDelegate normal_delegate
;
337 scoped_ptr
<aura::Window
> normal_window(CreateWindow(
338 normal_container
, &normal_delegate
, gfx::Rect(0, 0, 100, 100)));
340 ui::test::EventGenerator
event_generator(root_window());
341 event_generator
.MoveMouseTo(0, 0);
342 event_generator
.PressLeftButton();
344 // Creating blocking container while mouse pressing.
345 ScreenManager::ContainerParams
block_params("blocking",
346 kTestZOrderPriority
+ 1);
347 block_params
.can_activate_children
= true;
348 block_params
.block_events
= true;
349 aura::Window
* block_container
=
350 ScreenManager::Get()->CreateContainer(block_params
);
352 aura::test::EventCountDelegate block_delegate
;
353 scoped_ptr
<aura::Window
> block_window(CreateWindow(
354 block_container
, &block_delegate
, gfx::Rect(10, 10, 100, 100)));
356 // Release event should be sent to |normal_window| because it captures the
358 event_generator
.ReleaseLeftButton();
359 EXPECT_EQ("1 1", normal_delegate
.GetMouseButtonCountsAndReset());
360 EXPECT_EQ("0 0", block_delegate
.GetMouseButtonCountsAndReset());
362 // After release, further mouse events should not be sent to |normal_window|
363 // because block_container blocks the input.
364 event_generator
.ClickLeftButton();
365 EXPECT_EQ("0 0", normal_delegate
.GetMouseButtonCountsAndReset());
366 EXPECT_EQ("0 0", block_delegate
.GetMouseButtonCountsAndReset());
369 INSTANTIATE_TEST_CASE_P(WithOrWithoutTargeter
,
370 ScreenManagerTargeterTest
,
371 testing::Values(false, true));
373 } // namespace athena