1 // Copyright (c) 2013 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 "ui/wm/core/transient_window_stacking_client.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "ui/aura/test/aura_test_base.h"
9 #include "ui/aura/test/test_windows.h"
10 #include "ui/compositor/test/test_layers.h"
11 #include "ui/wm/core/window_util.h"
13 using aura::test::ChildWindowIDsAsString
;
14 using aura::test::CreateTestWindowWithId
;
19 class TransientWindowStackingClientTest
: public aura::test::AuraTestBase
{
21 TransientWindowStackingClientTest() {}
22 ~TransientWindowStackingClientTest() override
{}
24 void SetUp() override
{
25 AuraTestBase::SetUp();
26 client_
.reset(new TransientWindowStackingClient
);
27 aura::client::SetWindowStackingClient(client_
.get());
30 void TearDown() override
{
31 aura::client::SetWindowStackingClient(NULL
);
32 AuraTestBase::TearDown();
36 scoped_ptr
<TransientWindowStackingClient
> client_
;
37 DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClientTest
);
40 // Tests that transient children are stacked as a unit when using stack above.
41 TEST_F(TransientWindowStackingClientTest
, TransientChildrenGroupAbove
) {
42 scoped_ptr
<Window
> parent(CreateTestWindowWithId(0, root_window()));
43 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, parent
.get()));
44 Window
* w11
= CreateTestWindowWithId(11, parent
.get());
45 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, parent
.get()));
46 Window
* w21
= CreateTestWindowWithId(21, parent
.get());
47 Window
* w211
= CreateTestWindowWithId(211, parent
.get());
48 Window
* w212
= CreateTestWindowWithId(212, parent
.get());
49 Window
* w213
= CreateTestWindowWithId(213, parent
.get());
50 Window
* w22
= CreateTestWindowWithId(22, parent
.get());
51 ASSERT_EQ(8u, parent
->children().size());
53 AddTransientChild(w1
.get(), w11
); // w11 is now owned by w1.
54 AddTransientChild(w2
.get(), w21
); // w21 is now owned by w2.
55 AddTransientChild(w2
.get(), w22
); // w22 is now owned by w2.
56 AddTransientChild(w21
, w211
); // w211 is now owned by w21.
57 AddTransientChild(w21
, w212
); // w212 is now owned by w21.
58 AddTransientChild(w21
, w213
); // w213 is now owned by w21.
59 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
61 // Stack w1 at the top (end), this should force w11 to be last (on top of w1).
62 parent
->StackChildAtTop(w1
.get());
63 EXPECT_EQ(w11
, parent
->children().back());
64 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent
.get()));
66 // This tests that the order in children_ array rather than in
67 // transient_children_ array is used when reinserting transient children.
68 // If transient_children_ array was used '22' would be following '21'.
69 parent
->StackChildAtTop(w2
.get());
70 EXPECT_EQ(w22
, parent
->children().back());
71 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
73 parent
->StackChildAbove(w11
, w2
.get());
74 EXPECT_EQ(w11
, parent
->children().back());
75 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent
.get()));
77 parent
->StackChildAbove(w21
, w1
.get());
78 EXPECT_EQ(w22
, parent
->children().back());
79 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
81 parent
->StackChildAbove(w21
, w22
);
82 EXPECT_EQ(w213
, parent
->children().back());
83 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent
.get()));
85 parent
->StackChildAbove(w11
, w21
);
86 EXPECT_EQ(w11
, parent
->children().back());
87 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent
.get()));
89 parent
->StackChildAbove(w213
, w21
);
90 EXPECT_EQ(w11
, parent
->children().back());
91 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
93 // No change when stacking a transient parent above its transient child.
94 parent
->StackChildAbove(w21
, w211
);
95 EXPECT_EQ(w11
, parent
->children().back());
96 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
98 // This tests that the order in children_ array rather than in
99 // transient_children_ array is used when reinserting transient children.
100 // If transient_children_ array was used '22' would be following '21'.
101 parent
->StackChildAbove(w2
.get(), w1
.get());
102 EXPECT_EQ(w212
, parent
->children().back());
103 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent
.get()));
105 parent
->StackChildAbove(w11
, w213
);
106 EXPECT_EQ(w11
, parent
->children().back());
107 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
110 // Tests that transient children are stacked as a unit when using stack below.
111 TEST_F(TransientWindowStackingClientTest
, TransientChildrenGroupBelow
) {
112 scoped_ptr
<Window
> parent(CreateTestWindowWithId(0, root_window()));
113 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, parent
.get()));
114 Window
* w11
= CreateTestWindowWithId(11, parent
.get());
115 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, parent
.get()));
116 Window
* w21
= CreateTestWindowWithId(21, parent
.get());
117 Window
* w211
= CreateTestWindowWithId(211, parent
.get());
118 Window
* w212
= CreateTestWindowWithId(212, parent
.get());
119 Window
* w213
= CreateTestWindowWithId(213, parent
.get());
120 Window
* w22
= CreateTestWindowWithId(22, parent
.get());
121 ASSERT_EQ(8u, parent
->children().size());
123 AddTransientChild(w1
.get(), w11
); // w11 is now owned by w1.
124 AddTransientChild(w2
.get(), w21
); // w21 is now owned by w2.
125 AddTransientChild(w2
.get(), w22
); // w22 is now owned by w2.
126 AddTransientChild(w21
, w211
); // w211 is now owned by w21.
127 AddTransientChild(w21
, w212
); // w212 is now owned by w21.
128 AddTransientChild(w21
, w213
); // w213 is now owned by w21.
129 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
131 // Stack w2 at the bottom, this should force w11 to be last (on top of w1).
132 // This also tests that the order in children_ array rather than in
133 // transient_children_ array is used when reinserting transient children.
134 // If transient_children_ array was used '22' would be following '21'.
135 parent
->StackChildAtBottom(w2
.get());
136 EXPECT_EQ(w11
, parent
->children().back());
137 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent
.get()));
139 parent
->StackChildAtBottom(w1
.get());
140 EXPECT_EQ(w22
, parent
->children().back());
141 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
143 parent
->StackChildBelow(w21
, w1
.get());
144 EXPECT_EQ(w11
, parent
->children().back());
145 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent
.get()));
147 parent
->StackChildBelow(w11
, w2
.get());
148 EXPECT_EQ(w22
, parent
->children().back());
149 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent
.get()));
151 parent
->StackChildBelow(w22
, w21
);
152 EXPECT_EQ(w213
, parent
->children().back());
153 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent
.get()));
155 parent
->StackChildBelow(w21
, w11
);
156 EXPECT_EQ(w11
, parent
->children().back());
157 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent
.get()));
159 parent
->StackChildBelow(w213
, w211
);
160 EXPECT_EQ(w11
, parent
->children().back());
161 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
163 // No change when stacking a transient parent below its transient child.
164 parent
->StackChildBelow(w21
, w211
);
165 EXPECT_EQ(w11
, parent
->children().back());
166 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
168 parent
->StackChildBelow(w1
.get(), w2
.get());
169 EXPECT_EQ(w212
, parent
->children().back());
170 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent
.get()));
172 parent
->StackChildBelow(w213
, w11
);
173 EXPECT_EQ(w11
, parent
->children().back());
174 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent
.get()));
177 // Tests that windows can be stacked above windows with a NULL layer delegate.
178 // Windows have a NULL layer delegate when they are in the process of closing.
179 // See crbug.com/443433
180 TEST_F(TransientWindowStackingClientTest
,
181 StackAboveWindowWithNULLLayerDelegate
) {
182 scoped_ptr
<Window
> parent(CreateTestWindowWithId(0, root_window()));
183 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, parent
.get()));
184 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, parent
.get()));
185 w2
->layer()->set_delegate(NULL
);
186 EXPECT_EQ(w2
.get(), parent
->children().back());
188 parent
->StackChildAbove(w1
.get(), w2
.get());
189 EXPECT_EQ(w1
.get(), parent
->children().back());