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