| 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 |