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.
5 #include "athena/wm/window_list_provider_impl.h"
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"
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());
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
);
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.";
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);
53 class WindowListObserver
: public WindowListProviderObserver
{
55 explicit WindowListObserver(WindowListProvider
* provider
)
56 : calls_(0), window_removal_calls_(0), provider_(provider
) {
57 provider_
->AddObserver(this);
59 virtual ~WindowListObserver() {
60 provider_
->RemoveObserver(this);
63 int calls() const { return calls_
; }
64 int window_removal_calls() const { return window_removal_calls_
; }
66 // WindowListProviderObserver:
67 virtual void OnWindowStackingChanged() OVERRIDE
{
71 virtual void OnWindowRemoved(aura::Window
* removed_window
,
73 window_removal_calls_
++;
77 // The number of calls to the observer.
79 int window_removal_calls_
;
81 // The associated WindowListProvider which is observed.
82 WindowListProvider
* provider_
;
84 DISALLOW_COPY_AND_ASSIGN(WindowListObserver
);
90 typedef test::AthenaTestBase WindowListProviderImplTest
;
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());
107 scoped_ptr
<WindowListProvider
> list_provider(
108 new WindowListProviderImpl(container
.get()));
109 EXPECT_TRUE(AreWindowListsEqual(container
->children(),
110 list_provider
->GetWindowList()));
112 container
->StackChildAtTop(first
.get());
113 EXPECT_TRUE(AreWindowListsEqual(container
->children(),
114 list_provider
->GetWindowList()));
115 EXPECT_EQ(first
.get(), container
->children().back());
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());
135 scoped_ptr
<WindowListProvider
> list_provider(
136 new WindowListProviderImpl(container
.get()));
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()));
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
));
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
);
157 scoped_ptr
<WindowListProvider
> list_provider(
158 new WindowListProviderImpl(container
.get()));
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()));
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()));
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()));
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
));
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
);
187 scoped_ptr
<WindowListProvider
> list_provider(
188 new WindowListProviderImpl(container
.get()));
189 scoped_ptr
<WindowListObserver
> observer(
190 new WindowListObserver(list_provider
.get()));
192 EXPECT_FALSE(list_provider
->IsWindowInList(window1
.get()));
193 EXPECT_FALSE(list_provider
->IsWindowInList(window2
.get()));
194 EXPECT_FALSE(list_provider
->IsWindowInList(window3
.get()));
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());
207 EXPECT_EQ(0, observer
.get()->calls());
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());
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());
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());
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());
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());
244 TEST_F(WindowListProviderImplTest
, TestWindowRemovalNotification
) {
245 aura::test::TestWindowDelegate delegate
;
246 scoped_ptr
<aura::Window
> container(new aura::Window(&delegate
));
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
);
257 scoped_ptr
<WindowListProvider
> list_provider(
258 new WindowListProviderImpl(container
.get()));
259 scoped_ptr
<WindowListObserver
> observer(
260 new WindowListObserver(list_provider
.get()));
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()));
272 // Destroying the popup window should not trigger the remove notification.
274 ASSERT_EQ(3U, list_provider
->GetWindowList().size());
275 EXPECT_EQ(0, observer
->window_removal_calls());
278 ASSERT_EQ(2U, list_provider
->GetWindowList().size());
279 EXPECT_EQ(1, observer
->window_removal_calls());
282 ASSERT_EQ(1U, list_provider
->GetWindowList().size());
283 EXPECT_EQ(2, observer
->window_removal_calls());
286 ASSERT_EQ(0U, list_provider
->GetWindowList().size());
287 EXPECT_EQ(3, observer
->window_removal_calls());
290 } // namespace athena