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/test/athena_test_base.h" 10 #include "athena/wm/public/window_list_provider_observer.h" 11 #include "ui/aura/test/test_window_delegate.h" 12 #include "ui/aura/window.h" 13 14 namespace athena { 15 16 namespace { 17 18 bool AreWindowListsEqual(const aura::Window::Windows& one, 19 const aura::Window::Windows& two) { 20 return one.size() == two.size() && 21 std::equal(one.begin(), one.end(), two.begin()); 22 } 23 24 scoped_ptr<aura::Window> CreateWindow(aura::WindowDelegate* delegate, 25 ui::wm::WindowType window_type) { 26 scoped_ptr<aura::Window> window(new aura::Window(delegate)); 27 window->SetType(window_type); 28 window->Init(aura::WINDOW_LAYER_SOLID_COLOR); 29 return window.Pass(); 30 } 31 32 // Return a string which defines the order of windows in |now| using the indices 33 // of |original|. The string will then have the lowest/oldest window on the left 34 // and the highest / newest on the right. 35 std::string GetWindowOrder(const aura::Window::Windows& original, 36 const aura::Window::Windows& now) { 37 if (original.size() != now.size()) 38 return "size has changed."; 39 std::string output; 40 for (aura::Window::Windows::const_iterator it = now.begin(); 41 it != now.end(); ++it) { 42 for (size_t i = 0; i < original.size(); i++) { 43 if ((*it) == original[i]) { 44 output += (output.size() ? " " : std::string()) + 45 std::to_string(i + 1); 46 break; 47 } 48 } 49 } 50 return output; 51 } 52 53 class WindowListObserver : public WindowListProviderObserver { 54 public: 55 explicit WindowListObserver(WindowListProvider* provider) 56 : calls_(0), window_removal_calls_(0), provider_(provider) { 57 provider_->AddObserver(this); 58 } 59 virtual ~WindowListObserver() { 60 provider_->RemoveObserver(this); 61 } 62 63 int calls() const { return calls_; } 64 int window_removal_calls() const { return window_removal_calls_; } 65 66 // WindowListProviderObserver: 67 virtual void OnWindowStackingChanged() OVERRIDE { 68 calls_++; 69 } 70 71 virtual void OnWindowRemoved(aura::Window* removed_window, 72 int index) OVERRIDE { 73 window_removal_calls_++; 74 } 75 76 private: 77 // The number of calls to the observer. 78 int calls_; 79 int window_removal_calls_; 80 81 // The associated WindowListProvider which is observed. 82 WindowListProvider* provider_; 83 84 DISALLOW_COPY_AND_ASSIGN(WindowListObserver); 85 }; 86 87 88 } // namespace 89 90 typedef test::AthenaTestBase WindowListProviderImplTest; 91 92 // Tests that the order of windows match the stacking order of the windows in 93 // the container, even after the order is changed through the aura Window API. 94 TEST_F(WindowListProviderImplTest, StackingOrder) { 95 aura::test::TestWindowDelegate delegate; 96 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); 97 scoped_ptr<aura::Window> first = 98 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 99 scoped_ptr<aura::Window> second = 100 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 101 scoped_ptr<aura::Window> third = 102 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 103 container->AddChild(first.get()); 104 container->AddChild(second.get()); 105 container->AddChild(third.get()); 106 107 scoped_ptr<WindowListProvider> list_provider( 108 new WindowListProviderImpl(container.get())); 109 EXPECT_TRUE(AreWindowListsEqual(container->children(), 110 list_provider->GetWindowList())); 111 112 container->StackChildAtTop(first.get()); 113 EXPECT_TRUE(AreWindowListsEqual(container->children(), 114 list_provider->GetWindowList())); 115 EXPECT_EQ(first.get(), container->children().back()); 116 } 117 118 // Tests that only normal windows of the associated container will be listed. 119 TEST_F(WindowListProviderImplTest, ListContainsOnlyNormalWindows) { 120 aura::test::TestWindowDelegate delegate; 121 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); 122 scoped_ptr<aura::Window> first = 123 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 124 scoped_ptr<aura::Window> second = 125 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); 126 scoped_ptr<aura::Window> third = 127 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 128 scoped_ptr<aura::Window> fourth = 129 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU); 130 container->AddChild(first.get()); 131 container->AddChild(second.get()); 132 container->AddChild(third.get()); 133 container->AddChild(fourth.get()); 134 135 scoped_ptr<WindowListProvider> list_provider( 136 new WindowListProviderImpl(container.get())); 137 138 const aura::Window::Windows& list = list_provider->GetWindowList(); 139 EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), second.get())); 140 EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), fourth.get())); 141 EXPECT_NE(list.end(), std::find(list.begin(), list.end(), first.get())); 142 EXPECT_NE(list.end(), std::find(list.begin(), list.end(), third.get())); 143 } 144 145 // Testing that IsValidWidow, IsWindowInList and AddWindow work as expected. 146 TEST_F(WindowListProviderImplTest, SimpleChecks) { 147 aura::test::TestWindowDelegate delegate; 148 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); 149 150 scoped_ptr<aura::Window> normal_window = 151 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 152 scoped_ptr<aura::Window> popup_window = 153 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); 154 scoped_ptr<aura::Window> menu_window = 155 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU); 156 157 scoped_ptr<WindowListProvider> list_provider( 158 new WindowListProviderImpl(container.get())); 159 160 // Check which windows are valid and which are not. 161 EXPECT_TRUE(list_provider->IsValidWindow(normal_window.get())); 162 EXPECT_FALSE(list_provider->IsValidWindow(popup_window.get())); 163 EXPECT_FALSE(list_provider->IsValidWindow(menu_window.get())); 164 165 // Check that no window is currently in the list. 166 EXPECT_FALSE(list_provider->IsWindowInList(normal_window.get())); 167 EXPECT_FALSE(list_provider->IsWindowInList(popup_window.get())); 168 EXPECT_FALSE(list_provider->IsWindowInList(menu_window.get())); 169 170 // Check that adding the window will add it to the list. 171 container->AddChild(normal_window.get()); 172 EXPECT_TRUE(list_provider->IsWindowInList(normal_window.get())); 173 } 174 175 // Testing that window ordering functions work as expected. 176 TEST_F(WindowListProviderImplTest, TestWindowOrderingFunctions) { 177 aura::test::TestWindowDelegate delegate; 178 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); 179 180 scoped_ptr<aura::Window> window1 = 181 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 182 scoped_ptr<aura::Window> window2 = 183 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 184 scoped_ptr<aura::Window> window3 = 185 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 186 187 scoped_ptr<WindowListProvider> list_provider( 188 new WindowListProviderImpl(container.get())); 189 scoped_ptr<WindowListObserver> observer( 190 new WindowListObserver(list_provider.get())); 191 192 EXPECT_FALSE(list_provider->IsWindowInList(window1.get())); 193 EXPECT_FALSE(list_provider->IsWindowInList(window2.get())); 194 EXPECT_FALSE(list_provider->IsWindowInList(window3.get())); 195 196 // Add the windows. 197 container->AddChild(window1.get()); 198 container->AddChild(window2.get()); 199 container->AddChild(window3.get()); 200 // Make a copy of the window-list in the original order. 201 aura::Window::Windows original_order = list_provider->GetWindowList(); 202 ASSERT_EQ(3U, original_order.size()); 203 EXPECT_EQ(original_order[0], window1.get()); 204 EXPECT_EQ(original_order[1], window2.get()); 205 EXPECT_EQ(original_order[2], window3.get()); 206 207 EXPECT_EQ(0, observer.get()->calls()); 208 209 // Move 1 (from the back) in front of 2. 210 list_provider->StackWindowFrontOf(window1.get(), window2.get()); 211 EXPECT_EQ("2 1 3", GetWindowOrder(original_order, 212 list_provider->GetWindowList())); 213 EXPECT_EQ(1, observer->calls()); 214 215 // Move 3 (from the front) in front of 2. 216 list_provider->StackWindowFrontOf(window3.get(), window2.get()); 217 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, 218 list_provider->GetWindowList())); 219 EXPECT_EQ(2, observer->calls()); 220 221 // Move 1 (from the front) behind 2. 222 list_provider->StackWindowBehindTo(window1.get(), window2.get()); 223 EXPECT_EQ("1 2 3", GetWindowOrder(original_order, 224 list_provider->GetWindowList())); 225 EXPECT_EQ(3, observer->calls()); 226 227 // Move 1 (from the back) in front of 3. 228 list_provider->StackWindowFrontOf(window1.get(), window3.get()); 229 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, 230 list_provider->GetWindowList())); 231 EXPECT_EQ(4, observer->calls()); 232 233 // Test that no change should also report no call. 234 list_provider->StackWindowFrontOf(window1.get(), window3.get()); 235 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, 236 list_provider->GetWindowList())); 237 EXPECT_EQ(4, observer->calls()); 238 list_provider->StackWindowBehindTo(window3.get(), window1.get()); 239 EXPECT_EQ("2 3 1", GetWindowOrder(original_order, 240 list_provider->GetWindowList())); 241 EXPECT_EQ(4, observer->calls()); 242 } 243 244 TEST_F(WindowListProviderImplTest, TestWindowRemovalNotification) { 245 aura::test::TestWindowDelegate delegate; 246 scoped_ptr<aura::Window> container(new aura::Window(&delegate)); 247 248 scoped_ptr<aura::Window> window1 = 249 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 250 scoped_ptr<aura::Window> window2 = 251 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 252 scoped_ptr<aura::Window> window3 = 253 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); 254 scoped_ptr<aura::Window> window4 = 255 CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); 256 257 scoped_ptr<WindowListProvider> list_provider( 258 new WindowListProviderImpl(container.get())); 259 scoped_ptr<WindowListObserver> observer( 260 new WindowListObserver(list_provider.get())); 261 262 // Add the windows. 263 container->AddChild(window1.get()); 264 container->AddChild(window2.get()); 265 container->AddChild(window3.get()); 266 container->AddChild(window4.get()); 267 // The popup-window (window4) should not be included in the window-list. 268 ASSERT_EQ(3U, list_provider->GetWindowList().size()); 269 EXPECT_EQ(0, observer->window_removal_calls()); 270 EXPECT_FALSE(list_provider->IsWindowInList(window4.get())); 271 272 // Destroying the popup window should not trigger the remove notification. 273 window4.reset(); 274 ASSERT_EQ(3U, list_provider->GetWindowList().size()); 275 EXPECT_EQ(0, observer->window_removal_calls()); 276 277 window2.reset(); 278 ASSERT_EQ(2U, list_provider->GetWindowList().size()); 279 EXPECT_EQ(1, observer->window_removal_calls()); 280 281 window1.reset(); 282 ASSERT_EQ(1U, list_provider->GetWindowList().size()); 283 EXPECT_EQ(2, observer->window_removal_calls()); 284 285 window3.reset(); 286 ASSERT_EQ(0U, list_provider->GetWindowList().size()); 287 EXPECT_EQ(3, observer->window_removal_calls()); 288 } 289 290 } // namespace athena 291