OLD | NEW |
| (Empty) |
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/wm/window_list_provider_impl.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "athena/screen/public/screen_manager.h" | |
10 #include "athena/test/base/athena_test_base.h" | |
11 #include "athena/test/base/test_windows.h" | |
12 #include "athena/wm/public/window_list_provider_observer.h" | |
13 #include "athena/wm/public/window_manager.h" | |
14 #include "base/strings/string_number_conversions.h" | |
15 #include "ui/aura/client/window_tree_client.h" | |
16 #include "ui/aura/test/test_window_delegate.h" | |
17 #include "ui/aura/window.h" | |
18 #include "ui/wm/core/window_util.h" | |
19 | |
20 namespace athena { | |
21 | |
22 namespace { | |
23 | |
24 bool AreWindowListsEqual(const aura::Window::Windows& one, | |
25 const aura::Window::Windows& two) { | |
26 return one.size() == two.size() && | |
27 std::equal(one.begin(), one.end(), two.begin()); | |
28 } | |
29 | |
30 scoped_ptr<aura::Window> CreateWindow(aura::Window* parent, | |
31 aura::WindowDelegate* delegate, | |
32 ui::wm::WindowType window_type) { | |
33 scoped_ptr<aura::Window> window(new aura::Window(delegate)); | |
34 window->SetType(window_type); | |
35 window->Init(aura::WINDOW_LAYER_SOLID_COLOR); | |
36 if (parent) | |
37 parent->AddChild(window.get()); | |
38 return window.Pass(); | |
39 } | |
40 | |
41 // Return a string which defines the order of windows in |now| using the indices | |
42 // of |original|. The string will then have the lowest/oldest window on the left | |
43 // and the highest / newest on the right. | |
44 std::string GetWindowOrder(const aura::Window::Windows& original, | |
45 const aura::Window::Windows& now) { | |
46 if (original.size() != now.size()) | |
47 return "size has changed."; | |
48 std::string output; | |
49 for (aura::Window::Windows::const_iterator it = now.begin(); | |
50 it != now.end(); ++it) { | |
51 for (size_t i = 0; i < original.size(); i++) { | |
52 if ((*it) == original[i]) { | |
53 output += (output.size() ? " " : std::string()) + | |
54 base::IntToString(i + 1); | |
55 break; | |
56 } | |
57 } | |
58 } | |
59 return output; | |
60 } | |
61 | |
62 class WindowListObserver : public WindowListProviderObserver { | |
63 public: | |
64 explicit WindowListObserver(WindowListProvider* provider) | |
65 : calls_(0), | |
66 window_add_calls_(0), | |
67 window_removal_calls_(0), | |
68 provider_(provider) { | |
69 provider_->AddObserver(this); | |
70 } | |
71 ~WindowListObserver() override { provider_->RemoveObserver(this); } | |
72 | |
73 int calls() const { return calls_; } | |
74 int window_add_calls() const { return window_add_calls_; } | |
75 int window_removal_calls() const { return window_removal_calls_; } | |
76 | |
77 // WindowListProviderObserver: | |
78 void OnWindowStackingChangedInList() override { calls_++; } | |
79 | |
80 void OnWindowAddedToList(aura::Window* removed_window) override { | |
81 window_add_calls_++; | |
82 } | |
83 | |
84 void OnWindowRemovedFromList(aura::Window* removed_window, | |
85 int index) override { | |
86 window_removal_calls_++; | |
87 } | |
88 | |
89 private: | |
90 // The number of calls to the observer. | |
91 int calls_; | |
92 int window_add_calls_; | |
93 int window_removal_calls_; | |
94 | |
95 // The associated WindowListProvider which is observed. | |
96 WindowListProvider* provider_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(WindowListObserver); | |
99 }; | |
100 | |
101 | |
102 } // namespace | |
103 | |
104 typedef test::AthenaTestBase WindowListProviderImplTest; | |
105 | |
106 // Tests that the order of windows match the stacking order of the windows in | |
107 // the container, even after the order is changed through the aura Window API. | |
108 TEST_F(WindowListProviderImplTest, StackingOrder) { | |
109 aura::test::TestWindowDelegate delegate; | |
110 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); | |
111 scoped_ptr<WindowListProvider> list_provider( | |
112 new WindowListProviderImpl(container.get())); | |
113 | |
114 scoped_ptr<aura::Window> first = test::CreateWindowWithType( | |
115 &delegate, container.get(), ui::wm::WINDOW_TYPE_NORMAL); | |
116 scoped_ptr<aura::Window> second = | |
117 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
118 scoped_ptr<aura::Window> third = | |
119 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
120 | |
121 EXPECT_EQ(3u, container->children().size()); | |
122 EXPECT_EQ(container->children().size(), | |
123 list_provider->GetWindowList().size()); | |
124 | |
125 EXPECT_TRUE(AreWindowListsEqual(container->children(), | |
126 list_provider->GetWindowList())); | |
127 | |
128 container->StackChildAtTop(first.get()); | |
129 EXPECT_TRUE(AreWindowListsEqual(container->children(), | |
130 list_provider->GetWindowList())); | |
131 EXPECT_EQ(3u, container->children().size()); | |
132 EXPECT_EQ(first.get(), container->children().back()); | |
133 } | |
134 | |
135 // Tests that only normal windows of the associated container will be listed. | |
136 TEST_F(WindowListProviderImplTest, ListContainsOnlyNormalWindows) { | |
137 aura::test::TestWindowDelegate delegate; | |
138 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); | |
139 scoped_ptr<WindowListProvider> list_provider( | |
140 new WindowListProviderImpl(container.get())); | |
141 | |
142 scoped_ptr<aura::Window> first = | |
143 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
144 scoped_ptr<aura::Window> second = | |
145 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_POPUP); | |
146 scoped_ptr<aura::Window> third = | |
147 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
148 scoped_ptr<aura::Window> fourth = | |
149 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_MENU); | |
150 | |
151 const aura::Window::Windows& list = list_provider->GetWindowList(); | |
152 EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), second.get())); | |
153 EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), fourth.get())); | |
154 EXPECT_NE(list.end(), std::find(list.begin(), list.end(), first.get())); | |
155 EXPECT_NE(list.end(), std::find(list.begin(), list.end(), third.get())); | |
156 } | |
157 | |
158 // Testing that IsValidWidow, IsWindowInList and AddWindow work as expected. | |
159 TEST_F(WindowListProviderImplTest, SimpleChecks) { | |
160 aura::test::TestWindowDelegate delegate; | |
161 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); | |
162 scoped_ptr<WindowListProviderImpl> list_provider( | |
163 new WindowListProviderImpl(container.get())); | |
164 | |
165 scoped_ptr<aura::Window> normal_window = | |
166 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
167 scoped_ptr<aura::Window> popup_window = | |
168 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_POPUP); | |
169 scoped_ptr<aura::Window> menu_window = | |
170 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_MENU); | |
171 | |
172 // Check which windows are valid and which are not. | |
173 EXPECT_TRUE(list_provider->IsValidWindow(normal_window.get())); | |
174 EXPECT_FALSE(list_provider->IsValidWindow(popup_window.get())); | |
175 EXPECT_FALSE(list_provider->IsValidWindow(menu_window.get())); | |
176 | |
177 // Check that no window is currently in the list. | |
178 EXPECT_FALSE(list_provider->IsWindowInList(normal_window.get())); | |
179 EXPECT_FALSE(list_provider->IsWindowInList(popup_window.get())); | |
180 EXPECT_FALSE(list_provider->IsWindowInList(menu_window.get())); | |
181 | |
182 // Check that adding the window will add it to the list. | |
183 container->AddChild(normal_window.get()); | |
184 EXPECT_TRUE(list_provider->IsWindowInList(normal_window.get())); | |
185 } | |
186 | |
187 // Testing that window ordering functions work as expected. | |
188 TEST_F(WindowListProviderImplTest, TestWindowOrderingFunctions) { | |
189 aura::test::TestWindowDelegate delegate; | |
190 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); | |
191 scoped_ptr<WindowListProvider> list_provider( | |
192 new WindowListProviderImpl(container.get())); | |
193 scoped_ptr<WindowListObserver> observer( | |
194 new WindowListObserver(list_provider.get())); | |
195 | |
196 scoped_ptr<aura::Window> window1 = | |
197 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
198 scoped_ptr<aura::Window> window2 = | |
199 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
200 scoped_ptr<aura::Window> window3 = | |
201 CreateWindow(nullptr, &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
202 | |
203 EXPECT_FALSE(list_provider->IsWindowInList(window1.get())); | |
204 EXPECT_FALSE(list_provider->IsWindowInList(window2.get())); | |
205 EXPECT_FALSE(list_provider->IsWindowInList(window3.get())); | |
206 | |
207 // Add the windows. | |
208 container->AddChild(window1.get()); | |
209 container->AddChild(window2.get()); | |
210 container->AddChild(window3.get()); | |
211 // Make a copy of the window-list in the original order. | |
212 aura::Window::Windows original_order = list_provider->GetWindowList(); | |
213 ASSERT_EQ(3U, original_order.size()); | |
214 EXPECT_EQ(original_order[0], window1.get()); | |
215 EXPECT_EQ(original_order[1], window2.get()); | |
216 EXPECT_EQ(original_order[2], window3.get()); | |
217 | |
218 EXPECT_EQ(0, observer.get()->calls()); | |
219 | |
220 // Move 1 (from the back) in front of 2. | |
221 list_provider->StackWindowFrontOf(window1.get(), window2.get()); | |
222 EXPECT_EQ("2 1 3", GetWindowOrder(original_order, | |
223 list_provider->GetWindowList())); | |
224 EXPECT_EQ(1, observer->calls()); | |
225 | |
226 // Move 3 (from the front) in front of 2. | |
227 list_provider->StackWindowFrontOf(window3.get(), window2.get()); | |
228 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, | |
229 list_provider->GetWindowList())); | |
230 EXPECT_EQ(2, observer->calls()); | |
231 | |
232 // Move 1 (from the front) behind 2. | |
233 list_provider->StackWindowBehindTo(window1.get(), window2.get()); | |
234 EXPECT_EQ("1 2 3", GetWindowOrder(original_order, | |
235 list_provider->GetWindowList())); | |
236 EXPECT_EQ(3, observer->calls()); | |
237 | |
238 // Move 1 (from the back) in front of 3. | |
239 list_provider->StackWindowFrontOf(window1.get(), window3.get()); | |
240 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, | |
241 list_provider->GetWindowList())); | |
242 EXPECT_EQ(4, observer->calls()); | |
243 | |
244 // Test that no change should also report no call. | |
245 list_provider->StackWindowFrontOf(window1.get(), window3.get()); | |
246 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, | |
247 list_provider->GetWindowList())); | |
248 EXPECT_EQ(4, observer->calls()); | |
249 list_provider->StackWindowBehindTo(window3.get(), window1.get()); | |
250 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, | |
251 list_provider->GetWindowList())); | |
252 EXPECT_EQ(4, observer->calls()); | |
253 } | |
254 | |
255 TEST_F(WindowListProviderImplTest, TestWindowAddRemoveNotification) { | |
256 aura::test::TestWindowDelegate delegate; | |
257 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); | |
258 scoped_ptr<WindowListProvider> list_provider( | |
259 new WindowListProviderImpl(container.get())); | |
260 scoped_ptr<WindowListObserver> observer( | |
261 new WindowListObserver(list_provider.get())); | |
262 | |
263 scoped_ptr<aura::Window> window1 = | |
264 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
265 scoped_ptr<aura::Window> window2 = | |
266 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
267 scoped_ptr<aura::Window> window3 = | |
268 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); | |
269 scoped_ptr<aura::Window> window4 = | |
270 CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_POPUP); | |
271 // The popup-window (window4) should not be added tot he list. | |
272 EXPECT_EQ(3, observer->window_add_calls()); | |
273 | |
274 // The popup-window should not be included in the window-list. | |
275 ASSERT_EQ(3U, list_provider->GetWindowList().size()); | |
276 EXPECT_EQ(0, observer->window_removal_calls()); | |
277 EXPECT_EQ(3, observer->window_add_calls()); | |
278 EXPECT_FALSE(list_provider->IsWindowInList(window4.get())); | |
279 | |
280 // Destroying the popup window should not trigger the remove notification. | |
281 window4.reset(); | |
282 ASSERT_EQ(3U, list_provider->GetWindowList().size()); | |
283 EXPECT_EQ(0, observer->window_removal_calls()); | |
284 | |
285 window2.reset(); | |
286 ASSERT_EQ(2U, list_provider->GetWindowList().size()); | |
287 EXPECT_EQ(1, observer->window_removal_calls()); | |
288 | |
289 window1.reset(); | |
290 ASSERT_EQ(1U, list_provider->GetWindowList().size()); | |
291 EXPECT_EQ(2, observer->window_removal_calls()); | |
292 | |
293 window3.reset(); | |
294 ASSERT_EQ(0U, list_provider->GetWindowList().size()); | |
295 EXPECT_EQ(3, observer->window_removal_calls()); | |
296 } | |
297 | |
298 // Test that transient windows are handled property. | |
299 TEST_F(WindowListProviderImplTest, TransientWindows) { | |
300 aura::test::TestWindowDelegate delegate; | |
301 delegate.set_can_focus(true); | |
302 | |
303 WindowListProvider* list_provider = | |
304 WindowManager::Get()->GetWindowListProvider(); | |
305 | |
306 scoped_ptr<WindowListObserver> observer( | |
307 new WindowListObserver(list_provider)); | |
308 scoped_ptr<aura::Window> w1 = test::CreateNormalWindow(&delegate, nullptr); | |
309 w1->Show(); | |
310 scoped_ptr<aura::Window> w2 = test::CreateNormalWindow(&delegate, nullptr); | |
311 w2->Show(); | |
312 scoped_ptr<aura::Window> t1 = test::CreateTransientWindow( | |
313 &delegate, w1.get(), ui::MODAL_TYPE_NONE, false); | |
314 t1->Show(); | |
315 | |
316 EXPECT_EQ(2u, list_provider->GetWindowList().size()); | |
317 | |
318 // Activation should honor transient relations. | |
319 wm::ActivateWindow(w2.get()); | |
320 EXPECT_EQ(w1.get(), list_provider->GetWindowList()[0]); | |
321 EXPECT_EQ(w2.get(), list_provider->GetWindowList()[1]); | |
322 | |
323 EXPECT_EQ(w1.get(), w1->parent()->children()[0]); | |
324 EXPECT_EQ(t1.get(), w1->parent()->children()[1]); | |
325 EXPECT_EQ(w2.get(), w1->parent()->children()[2]); | |
326 | |
327 wm::ActivateWindow(w1.get()); | |
328 EXPECT_EQ(w2.get(), w1->parent()->children()[0]); | |
329 EXPECT_EQ(w1.get(), w1->parent()->children()[1]); | |
330 EXPECT_EQ(t1.get(), w1->parent()->children()[2]); | |
331 | |
332 // Manual operations should honor transient relations too. | |
333 // TODO(oshima): moving the active window back should activate the top window. | |
334 list_provider->StackWindowBehindTo(w1.get(), w2.get()); | |
335 EXPECT_EQ(w1.get(), w1->parent()->children()[0]); | |
336 EXPECT_EQ(t1.get(), w1->parent()->children()[1]); | |
337 EXPECT_EQ(w2.get(), w1->parent()->children()[2]); | |
338 | |
339 list_provider->StackWindowFrontOf(w1.get(), w2.get()); | |
340 EXPECT_EQ(w2.get(), w1->parent()->children()[0]); | |
341 EXPECT_EQ(w1.get(), w1->parent()->children()[1]); | |
342 EXPECT_EQ(t1.get(), w1->parent()->children()[2]); | |
343 | |
344 // Transient windows should follow the transient parent's | |
345 // visibility. | |
346 EXPECT_TRUE(t1->IsVisible()); | |
347 w1->Hide(); | |
348 EXPECT_FALSE(t1->IsVisible()); | |
349 w1->Show(); | |
350 EXPECT_TRUE(t1->IsVisible()); | |
351 | |
352 // Resetting transient window won't notify the observer. | |
353 t1.reset(); | |
354 EXPECT_EQ(0, observer->window_removal_calls()); | |
355 } | |
356 | |
357 } // namespace athena | |
OLD | NEW |