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.
4
5#include "athena/screen/public/screen_manager.h"
6
7#include <algorithm>
8#include <string>
9
10#include "athena/test/athena_test_base.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/events/test/event_generator.h"
15#include "ui/wm/core/window_util.h"
16
17typedef athena::test::AthenaTestBase ScreenManagerTest;
18
19namespace athena {
20namespace {
21
22const int kTestZOrderPriority = 10;
23
24aura::Window* Create(const std::string& name, int z_order_priority) {
25  ScreenManager::ContainerParams params(name, z_order_priority);
26  return ScreenManager::Get()->CreateContainer(params);
27}
28
29aura::Window* CreateWindow(aura::Window* container,
30                           aura::WindowDelegate* delegate,
31                           const gfx::Rect& bounds) {
32  aura::Window* window = new aura::Window(delegate);
33  window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
34  window->Init(aura::WINDOW_LAYER_TEXTURED);
35  container->AddChild(window);
36  window->Show();
37  window->SetBounds(bounds);
38  return window;
39}
40
41void CheckZOrder(aura::Window* w1, aura::Window* w2) {
42  aura::Window* parent = w1->parent();
43  const aura::Window::Windows& children = parent->children();
44  aura::Window::Windows::const_iterator begin_iter = children.begin();
45  aura::Window::Windows::const_iterator end_iter = children.end();
46
47  aura::Window::Windows::const_iterator w1_iter =
48      std::find(begin_iter, end_iter, w1);
49  aura::Window::Windows::const_iterator w2_iter =
50      std::find(begin_iter, end_iter, w2);
51  EXPECT_NE(end_iter, w1_iter);
52  EXPECT_NE(end_iter, w2_iter);
53  EXPECT_TRUE(w1_iter < w2_iter);
54}
55
56}  // namespace
57
58TEST_F(ScreenManagerTest, CreateContainer) {
59  size_t num_containers = root_window()->children().size();
60
61  aura::Window* container = Create("test", kTestZOrderPriority);
62  EXPECT_EQ("test", container->name());
63
64  const aura::Window::Windows& containers = root_window()->children();
65  EXPECT_EQ(num_containers + 1, containers.size());
66  EXPECT_NE(containers.end(),
67            std::find(containers.begin(), containers.end(), container));
68}
69
70TEST_F(ScreenManagerTest, Zorder) {
71  aura::Window* window_10 = Create("test10", 10);
72  aura::Window* window_11 = Create("test11", 11);
73  aura::Window* window_12 = Create("test12", 12);
74
75  {
76    SCOPED_TRACE("Init");
77    CheckZOrder(window_10, window_11);
78    CheckZOrder(window_11, window_12);
79  }
80  {
81    SCOPED_TRACE("Delete");
82    delete window_11;
83    CheckZOrder(window_10, window_12);
84  }
85  {
86    SCOPED_TRACE("Insert");
87    window_11 = Create("test11", 11);
88    CheckZOrder(window_10, window_11);
89    CheckZOrder(window_11, window_12);
90  }
91}
92
93TEST_F(ScreenManagerTest, NonActivatableContainer) {
94  ScreenManager::ContainerParams non_activatable(
95      "non_activatable", kTestZOrderPriority);
96  non_activatable.can_activate_children = false;
97  aura::Window* no_activatable_container =
98      ScreenManager::Get()->CreateContainer(non_activatable);
99
100  ScreenManager::ContainerParams activatable(
101      "activatable", kTestZOrderPriority + 1);
102  activatable.can_activate_children = true;
103  aura::Window* activatable_container =
104      ScreenManager::Get()->CreateContainer(activatable);
105
106  scoped_ptr<aura::Window> window(
107      CreateWindow(no_activatable_container, NULL, gfx::Rect(0, 0, 100, 100)));
108  EXPECT_FALSE(wm::CanActivateWindow(window.get()));
109
110  activatable_container->AddChild(window.get());
111  EXPECT_TRUE(wm::CanActivateWindow(window.get()));
112}
113
114TEST_F(ScreenManagerTest, GrabInputContainer) {
115  ScreenManager::ContainerParams normal_params(
116      "normal", kTestZOrderPriority);
117  normal_params.can_activate_children = true;
118  aura::Window* normal_container =
119      ScreenManager::Get()->CreateContainer(normal_params);
120
121  aura::test::EventCountDelegate normal_delegate;
122  scoped_ptr<aura::Window> normal_window(CreateWindow(
123      normal_container, &normal_delegate, gfx::Rect(0, 0, 100, 100)));
124
125  EXPECT_TRUE(wm::CanActivateWindow(normal_window.get()));
126  wm::ActivateWindow(normal_window.get());
127  ui::test::EventGenerator event_generator(root_window());
128  event_generator.MoveMouseTo(0, 0);
129  event_generator.ClickLeftButton();
130  EXPECT_EQ("1 1", normal_delegate.GetMouseButtonCountsAndReset());
131  event_generator.PressKey(ui::VKEY_A, ui::EF_NONE);
132  event_generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
133  EXPECT_EQ("1 1", normal_delegate.GetKeyCountsAndReset());
134
135  ScreenManager::ContainerParams grab_params(
136      "grabbing", kTestZOrderPriority + 1);
137  grab_params.can_activate_children = true;
138  grab_params.grab_inputs = true;
139  aura::Window* grab_container =
140      ScreenManager::Get()->CreateContainer(grab_params);
141
142  EXPECT_FALSE(wm::CanActivateWindow(normal_window.get()));
143
144  aura::test::EventCountDelegate grab_delegate;
145  scoped_ptr<aura::Window> grab_window(CreateWindow(
146      grab_container, &grab_delegate, gfx::Rect(10, 10, 100, 100)));
147  EXPECT_TRUE(wm::CanActivateWindow(grab_window.get()));
148
149  wm::ActivateWindow(grab_window.get());
150
151  // (0, 0) is still on normal_window, but the event should not go there
152  // because grabbing_container prevents it.
153  event_generator.MoveMouseTo(0, 0);
154  event_generator.ClickLeftButton();
155  EXPECT_EQ("0 0", normal_delegate.GetMouseButtonCountsAndReset());
156  EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
157
158  event_generator.MoveMouseTo(20, 20);
159  event_generator.ClickLeftButton();
160  EXPECT_EQ("1 1", grab_delegate.GetMouseButtonCountsAndReset());
161
162  event_generator.PressKey(ui::VKEY_A, ui::EF_NONE);
163  event_generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
164  EXPECT_EQ("0 0", normal_delegate.GetKeyCountsAndReset());
165  EXPECT_EQ("1 1", grab_delegate.GetKeyCountsAndReset());
166}
167
168TEST_F(ScreenManagerTest, GrabShouldNotBlockVirtualKeyboard) {
169  ScreenManager::ContainerParams grab_params("grabbing", kTestZOrderPriority);
170  grab_params.can_activate_children = true;
171  grab_params.grab_inputs = true;
172  aura::Window* grab_container =
173      ScreenManager::Get()->CreateContainer(grab_params);
174
175  aura::test::EventCountDelegate grab_delegate;
176  scoped_ptr<aura::Window> grab_window(
177      CreateWindow(grab_container, &grab_delegate, gfx::Rect(0, 0, 100, 100)));
178  EXPECT_TRUE(wm::CanActivateWindow(grab_window.get()));
179
180  // Create a normal container appearing over the |grab_container|. This is
181  // essentially the case of virtual keyboard.
182  ScreenManager::ContainerParams vk_params(
183      "virtual keyboard", kTestZOrderPriority + 1);
184  vk_params.can_activate_children = true;
185  aura::Window* vk_container = ScreenManager::Get()->CreateContainer(vk_params);
186
187  aura::test::EventCountDelegate vk_delegate;
188  scoped_ptr<aura::Window> vk_window(
189      CreateWindow(vk_container, &vk_delegate, gfx::Rect(0, 20, 100, 80)));
190  EXPECT_TRUE(wm::CanActivateWindow(vk_window.get()));
191
192  ui::test::EventGenerator event_generator(root_window());
193  event_generator.MoveMouseTo(10, 25);
194  event_generator.ClickLeftButton();
195  EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
196  EXPECT_EQ("1 1", vk_delegate.GetMouseButtonCountsAndReset());
197}
198
199TEST_F(ScreenManagerTest, GrabAndMouseCapture) {
200  ScreenManager::ContainerParams normal_params(
201      "normal", kTestZOrderPriority);
202  normal_params.can_activate_children = true;
203  aura::Window* normal_container =
204      ScreenManager::Get()->CreateContainer(normal_params);
205
206  aura::test::EventCountDelegate normal_delegate;
207  scoped_ptr<aura::Window> normal_window(CreateWindow(
208      normal_container, &normal_delegate, gfx::Rect(0, 0, 100, 100)));
209
210  ui::test::EventGenerator event_generator(root_window());
211  event_generator.MoveMouseTo(0, 0);
212  event_generator.PressLeftButton();
213
214  // Creating grabbing container while mouse pressing.
215  ScreenManager::ContainerParams grab_params(
216      "grabbing", kTestZOrderPriority + 1);
217  grab_params.can_activate_children = true;
218  grab_params.grab_inputs = true;
219  aura::Window* grab_container =
220      ScreenManager::Get()->CreateContainer(grab_params);
221
222  aura::test::EventCountDelegate grab_delegate;
223  scoped_ptr<aura::Window> grab_window(CreateWindow(
224      grab_container, &grab_delegate, gfx::Rect(10, 10, 100, 100)));
225
226  // Release event should be sent to |normal_window| because it captures the
227  // mouse event.
228  event_generator.ReleaseLeftButton();
229  EXPECT_EQ("1 1", normal_delegate.GetMouseButtonCountsAndReset());
230  EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
231
232  // After release, further mouse events should not be sent to |normal_window|
233  // because grab_container grabs the input.
234  event_generator.ClickLeftButton();
235  EXPECT_EQ("0 0", normal_delegate.GetMouseButtonCountsAndReset());
236  EXPECT_EQ("0 0", grab_delegate.GetMouseButtonCountsAndReset());
237}
238
239}  // namespace athena
240