OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "base/macros.h" | |
6 #include "base/strings/string_number_conversions.h" | |
7 #include "components/mus/ws/server_window.h" | |
8 #include "components/mus/ws/server_window_observer.h" | |
9 #include "components/mus/ws/test_server_window_delegate.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 | |
12 namespace mus { | |
13 namespace ws { | |
14 | |
15 namespace { | |
16 | |
17 class TestTransientWindowObserver : public ServerWindowObserver { | |
18 public: | |
19 TestTransientWindowObserver() : add_count_(0), remove_count_(0) {} | |
20 | |
21 ~TestTransientWindowObserver() override {} | |
22 | |
23 int add_count() const { return add_count_; } | |
24 int remove_count() const { return remove_count_; } | |
25 | |
26 // TransientWindowObserver overrides: | |
27 void OnTransientWindowAdded(ServerWindow* window, | |
28 ServerWindow* transient) override { | |
29 add_count_++; | |
30 } | |
31 void OnTransientWindowRemoved(ServerWindow* window, | |
32 ServerWindow* transient) override { | |
33 remove_count_++; | |
34 } | |
35 | |
36 private: | |
37 int add_count_; | |
38 int remove_count_; | |
39 | |
40 DISALLOW_COPY_AND_ASSIGN(TestTransientWindowObserver); | |
41 }; | |
42 | |
43 ServerWindow* CreateTestWindow(TestServerWindowDelegate* delegate, | |
44 const WindowId& window_id, | |
45 ServerWindow* parent) { | |
46 ServerWindow* window = new ServerWindow(delegate, window_id); | |
47 window->SetVisible(true); | |
48 if (parent) | |
49 parent->Add(window); | |
50 else | |
51 delegate->set_root_window(window); | |
52 return window; | |
53 } | |
54 | |
55 std::string ChildWindowIDsAsString(ServerWindow* parent) { | |
56 std::string result; | |
57 for (auto i = parent->children().begin(); i != parent->children().end(); | |
58 ++i) { | |
59 if (!result.empty()) | |
60 result += " "; | |
61 result += base::IntToString(WindowIdToTransportId((*i)->id())); | |
62 } | |
63 return result; | |
64 } | |
65 | |
66 } // namespace | |
67 | |
68 class TransientWindowsTest : public testing::Test { | |
69 public: | |
70 TransientWindowsTest() {} | |
71 ~TransientWindowsTest() override {} | |
72 | |
73 private: | |
74 DISALLOW_COPY_AND_ASSIGN(TransientWindowsTest); | |
75 }; | |
76 | |
77 TEST_F(TransientWindowsTest, TransientChildren) { | |
78 TestServerWindowDelegate server_window_delegate; | |
79 | |
80 std::unique_ptr<ServerWindow> parent( | |
81 CreateTestWindow(&server_window_delegate, WindowId(), nullptr)); | |
82 std::unique_ptr<ServerWindow> w1( | |
83 CreateTestWindow(&server_window_delegate, WindowId(1, 1), parent.get())); | |
84 std::unique_ptr<ServerWindow> w3( | |
85 CreateTestWindow(&server_window_delegate, WindowId(1, 2), parent.get())); | |
86 | |
87 ServerWindow* w2 = | |
88 CreateTestWindow(&server_window_delegate, WindowId(1, 3), parent.get()); | |
89 | |
90 // w2 is now owned by w1. | |
91 w1->AddTransientWindow(w2); | |
92 // Stack w1 at the top (end), this should force w2 to be last (on top of w1). | |
93 parent->StackChildAtTop(w1.get()); | |
94 ASSERT_EQ(3u, parent->children().size()); | |
95 EXPECT_EQ(w2, parent->children().back()); | |
96 | |
97 // Destroy w1, which should also destroy w3 (since it's a transient child). | |
98 w1.reset(); | |
99 w2 = nullptr; | |
100 ASSERT_EQ(1u, parent->children().size()); | |
101 EXPECT_EQ(w3.get(), parent->children()[0]); | |
102 } | |
103 | |
104 // Tests that transient children are stacked as a unit when using stack above. | |
105 TEST_F(TransientWindowsTest, TransientChildrenGroupAbove) { | |
106 TestServerWindowDelegate server_window_delegate; | |
107 | |
108 std::unique_ptr<ServerWindow> parent( | |
109 CreateTestWindow(&server_window_delegate, WindowId(), nullptr)); | |
110 std::unique_ptr<ServerWindow> w1( | |
111 CreateTestWindow(&server_window_delegate, WindowId(0, 1), parent.get())); | |
112 | |
113 ServerWindow* w11 = | |
114 CreateTestWindow(&server_window_delegate, WindowId(0, 11), parent.get()); | |
115 std::unique_ptr<ServerWindow> w2( | |
116 CreateTestWindow(&server_window_delegate, WindowId(0, 2), parent.get())); | |
117 | |
118 ServerWindow* w21 = | |
119 CreateTestWindow(&server_window_delegate, WindowId(0, 21), parent.get()); | |
120 ServerWindow* w211 = | |
121 CreateTestWindow(&server_window_delegate, WindowId(0, 211), parent.get()); | |
122 ServerWindow* w212 = | |
123 CreateTestWindow(&server_window_delegate, WindowId(0, 212), parent.get()); | |
124 ServerWindow* w213 = | |
125 CreateTestWindow(&server_window_delegate, WindowId(0, 213), parent.get()); | |
126 ServerWindow* w22 = | |
127 CreateTestWindow(&server_window_delegate, WindowId(0, 22), parent.get()); | |
128 ASSERT_EQ(8u, parent->children().size()); | |
129 | |
130 // w11 is now owned by w1. | |
131 w1->AddTransientWindow(w11); | |
132 // w21 is now owned by w2. | |
133 w2->AddTransientWindow(w21); | |
134 // w22 is now owned by w2. | |
135 w2->AddTransientWindow(w22); | |
136 // w211 is now owned by w21. | |
137 w21->AddTransientWindow(w211); | |
138 // w212 is now owned by w21. | |
139 w21->AddTransientWindow(w212); | |
140 // w213 is now owned by w21. | |
141 w21->AddTransientWindow(w213); | |
142 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
143 | |
144 // Stack w1 at the top (end), this should force w11 to be last (on top of w1). | |
145 parent->StackChildAtTop(w1.get()); | |
146 EXPECT_EQ(w11, parent->children().back()); | |
147 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); | |
148 | |
149 // This tests that the order in children_ array rather than in | |
150 // transient_children_ array is used when reinserting transient children. | |
151 // If transient_children_ array was used '22' would be following '21'. | |
152 parent->StackChildAtTop(w2.get()); | |
153 EXPECT_EQ(w22, parent->children().back()); | |
154 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
155 | |
156 w11->Reorder(w2.get(), mojom::OrderDirection::ABOVE); | |
157 EXPECT_EQ(w11, parent->children().back()); | |
158 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); | |
159 | |
160 w21->Reorder(w1.get(), mojom::OrderDirection::ABOVE); | |
161 EXPECT_EQ(w22, parent->children().back()); | |
162 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
163 | |
164 w21->Reorder(w22, mojom::OrderDirection::ABOVE); | |
165 EXPECT_EQ(w213, parent->children().back()); | |
166 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get())); | |
167 | |
168 w11->Reorder(w21, mojom::OrderDirection::ABOVE); | |
169 EXPECT_EQ(w11, parent->children().back()); | |
170 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get())); | |
171 | |
172 w213->Reorder(w21, mojom::OrderDirection::ABOVE); | |
173 EXPECT_EQ(w11, parent->children().back()); | |
174 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
175 | |
176 // No change when stacking a transient parent above its transient child. | |
177 w21->Reorder(w211, mojom::OrderDirection::ABOVE); | |
178 EXPECT_EQ(w11, parent->children().back()); | |
179 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
180 | |
181 // This tests that the order in children_ array rather than in | |
182 // transient_children_ array is used when reinserting transient children. | |
183 // If transient_children_ array was used '22' would be following '21'. | |
184 w2->Reorder(w1.get(), mojom::OrderDirection::ABOVE); | |
185 EXPECT_EQ(w212, parent->children().back()); | |
186 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get())); | |
187 | |
188 w11->Reorder(w213, mojom::OrderDirection::ABOVE); | |
189 EXPECT_EQ(w11, parent->children().back()); | |
190 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
191 } | |
192 | |
193 TEST_F(TransientWindowsTest, TransienChildGroupBelow) { | |
194 TestServerWindowDelegate server_window_delegate; | |
195 | |
196 std::unique_ptr<ServerWindow> parent( | |
197 CreateTestWindow(&server_window_delegate, WindowId(), nullptr)); | |
198 std::unique_ptr<ServerWindow> w1( | |
199 CreateTestWindow(&server_window_delegate, WindowId(0, 1), parent.get())); | |
200 | |
201 ServerWindow* w11 = | |
202 CreateTestWindow(&server_window_delegate, WindowId(0, 11), parent.get()); | |
203 std::unique_ptr<ServerWindow> w2( | |
204 CreateTestWindow(&server_window_delegate, WindowId(0, 2), parent.get())); | |
205 | |
206 ServerWindow* w21 = | |
207 CreateTestWindow(&server_window_delegate, WindowId(0, 21), parent.get()); | |
208 ServerWindow* w211 = | |
209 CreateTestWindow(&server_window_delegate, WindowId(0, 211), parent.get()); | |
210 ServerWindow* w212 = | |
211 CreateTestWindow(&server_window_delegate, WindowId(0, 212), parent.get()); | |
212 ServerWindow* w213 = | |
213 CreateTestWindow(&server_window_delegate, WindowId(0, 213), parent.get()); | |
214 ServerWindow* w22 = | |
215 CreateTestWindow(&server_window_delegate, WindowId(0, 22), parent.get()); | |
216 ASSERT_EQ(8u, parent->children().size()); | |
217 | |
218 // w11 is now owned by w1. | |
219 w1->AddTransientWindow(w11); | |
220 // w21 is now owned by w2. | |
221 w2->AddTransientWindow(w21); | |
222 // w22 is now owned by w2. | |
223 w2->AddTransientWindow(w22); | |
224 // w211 is now owned by w21. | |
225 w21->AddTransientWindow(w211); | |
226 // w212 is now owned by w21. | |
227 w21->AddTransientWindow(w212); | |
228 // w213 is now owned by w21. | |
229 w21->AddTransientWindow(w213); | |
230 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
231 | |
232 // Stack w2 at the bottom, this should force w11 to be last (on top of w1). | |
233 // This also tests that the order in children_ array rather than in | |
234 // transient_children_ array is used when reinserting transient children. | |
235 // If transient_children_ array was used '22' would be following '21'. | |
236 parent->StackChildAtBottom(w2.get()); | |
237 EXPECT_EQ(w11, parent->children().back()); | |
238 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); | |
239 | |
240 parent->StackChildAtBottom(w1.get()); | |
241 EXPECT_EQ(w22, parent->children().back()); | |
242 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
243 | |
244 w21->Reorder(w1.get(), mojom::OrderDirection::BELOW); | |
245 EXPECT_EQ(w11, parent->children().back()); | |
246 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); | |
247 | |
248 w11->Reorder(w2.get(), mojom::OrderDirection::BELOW); | |
249 EXPECT_EQ(w22, parent->children().back()); | |
250 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); | |
251 | |
252 w22->Reorder(w21, mojom::OrderDirection::BELOW); | |
253 EXPECT_EQ(w213, parent->children().back()); | |
254 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get())); | |
255 | |
256 w21->Reorder(w11, mojom::OrderDirection::BELOW); | |
257 EXPECT_EQ(w11, parent->children().back()); | |
258 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get())); | |
259 | |
260 w213->Reorder(w211, mojom::OrderDirection::BELOW); | |
261 EXPECT_EQ(w11, parent->children().back()); | |
262 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
263 | |
264 // No change when stacking a transient parent below its transient child. | |
265 w21->Reorder(w211, mojom::OrderDirection::BELOW); | |
266 EXPECT_EQ(w11, parent->children().back()); | |
267 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
268 | |
269 w1->Reorder(w2.get(), mojom::OrderDirection::BELOW); | |
270 EXPECT_EQ(w212, parent->children().back()); | |
271 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get())); | |
272 | |
273 w213->Reorder(w11, mojom::OrderDirection::BELOW); | |
274 EXPECT_EQ(w11, parent->children().back()); | |
275 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); | |
276 } | |
277 | |
278 // Tests that transient windows are stacked properly when created. | |
279 TEST_F(TransientWindowsTest, StackUponCreation) { | |
280 TestServerWindowDelegate delegate; | |
281 std::unique_ptr<ServerWindow> parent( | |
282 CreateTestWindow(&delegate, WindowId(), nullptr)); | |
283 std::unique_ptr<ServerWindow> window0( | |
284 CreateTestWindow(&delegate, WindowId(0, 1), parent.get())); | |
285 std::unique_ptr<ServerWindow> window1( | |
286 CreateTestWindow(&delegate, WindowId(0, 2), parent.get())); | |
287 | |
288 ServerWindow* window2 = | |
289 CreateTestWindow(&delegate, WindowId(0, 3), parent.get()); | |
290 window0->AddTransientWindow(window2); | |
291 EXPECT_EQ("1 3 2", ChildWindowIDsAsString(parent.get())); | |
292 } | |
293 | |
294 // Tests that windows are restacked properly after a call to | |
295 // AddTransientWindow() or RemoveTransientWindow(). | |
296 TEST_F(TransientWindowsTest, RestackUponAddOrRemoveTransientWindow) { | |
297 TestServerWindowDelegate delegate; | |
298 std::unique_ptr<ServerWindow> parent( | |
299 CreateTestWindow(&delegate, WindowId(), nullptr)); | |
300 std::unique_ptr<ServerWindow> windows[4]; | |
301 for (int i = 0; i < 4; i++) | |
302 windows[i].reset(CreateTestWindow(&delegate, WindowId(0, i), parent.get())); | |
303 | |
304 EXPECT_EQ("0 1 2 3", ChildWindowIDsAsString(parent.get())); | |
305 | |
306 windows[0]->AddTransientWindow(windows[2].get()); | |
307 EXPECT_EQ("0 2 1 3", ChildWindowIDsAsString(parent.get())); | |
308 | |
309 windows[0]->AddTransientWindow(windows[3].get()); | |
310 EXPECT_EQ("0 2 3 1", ChildWindowIDsAsString(parent.get())); | |
311 | |
312 windows[0]->RemoveTransientWindow(windows[2].get()); | |
313 EXPECT_EQ("0 3 2 1", ChildWindowIDsAsString(parent.get())); | |
314 | |
315 windows[0]->RemoveTransientWindow(windows[3].get()); | |
316 EXPECT_EQ("0 3 2 1", ChildWindowIDsAsString(parent.get())); | |
317 } | |
318 | |
319 // Verifies TransientWindowObserver is notified appropriately. | |
320 TEST_F(TransientWindowsTest, TransientWindowObserverNotified) { | |
321 TestServerWindowDelegate delegate; | |
322 std::unique_ptr<ServerWindow> parent( | |
323 CreateTestWindow(&delegate, WindowId(), nullptr)); | |
324 std::unique_ptr<ServerWindow> w1( | |
325 CreateTestWindow(&delegate, WindowId(0, 1), parent.get())); | |
326 | |
327 TestTransientWindowObserver test_observer; | |
328 parent->AddObserver(&test_observer); | |
329 | |
330 parent->AddTransientWindow(w1.get()); | |
331 EXPECT_EQ(1, test_observer.add_count()); | |
332 EXPECT_EQ(0, test_observer.remove_count()); | |
333 | |
334 parent->RemoveTransientWindow(w1.get()); | |
335 EXPECT_EQ(1, test_observer.add_count()); | |
336 EXPECT_EQ(1, test_observer.remove_count()); | |
337 | |
338 parent->RemoveObserver(&test_observer); | |
339 } | |
340 | |
341 } // namespace ws | |
342 } // namespace mus | |
OLD | NEW |