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. 4 5#include "ui/wm/core/transient_window_stacking_client.h" 6 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" 12 13using aura::test::ChildWindowIDsAsString; 14using aura::test::CreateTestWindowWithId; 15using aura::Window; 16 17namespace wm { 18 19class TransientWindowStackingClientTest : public aura::test::AuraTestBase { 20 public: 21 TransientWindowStackingClientTest() {} 22 virtual ~TransientWindowStackingClientTest() {} 23 24 virtual void SetUp() OVERRIDE { 25 AuraTestBase::SetUp(); 26 client_.reset(new TransientWindowStackingClient); 27 aura::client::SetWindowStackingClient(client_.get()); 28 } 29 30 virtual void TearDown() OVERRIDE { 31 aura::client::SetWindowStackingClient(NULL); 32 AuraTestBase::TearDown(); 33 } 34 35 private: 36 scoped_ptr<TransientWindowStackingClient> client_; 37 DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClientTest); 38}; 39 40// Tests that transient children are stacked as a unit when using stack above. 41TEST_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()); 52 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())); 60 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())); 65 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())); 72 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())); 76 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())); 80 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())); 84 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())); 88 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())); 92 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())); 97 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())); 104 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())); 108} 109 110// Tests that transient children are stacked as a unit when using stack below. 111TEST_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()); 122 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())); 130 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())); 138 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())); 142 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())); 146 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())); 150 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())); 154 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())); 158 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())); 162 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())); 167 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())); 171 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())); 175} 176 177TEST_F(TransientWindowStackingClientTest, 178 StackWindowsWhoseLayersHaveNoDelegate) { 179 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); 180 window1->layer()->set_name("1"); 181 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); 182 window2->layer()->set_name("2"); 183 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window())); 184 window3->layer()->set_name("3"); 185 186 // This brings |window1| (and its layer) to the front. 187 root_window()->StackChildAbove(window1.get(), window3.get()); 188 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); 189 EXPECT_EQ("2 3 1", 190 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 191 192 // Since |window1| does not have a delegate, |window2| should not move in 193 // front of it, nor should its layer. 194 window1->layer()->set_delegate(NULL); 195 root_window()->StackChildAbove(window2.get(), window1.get()); 196 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(root_window())); 197 EXPECT_EQ("3 2 1", 198 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 199 200 // It should still be possible to stack |window3| immediately below |window1|. 201 root_window()->StackChildBelow(window3.get(), window1.get()); 202 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); 203 EXPECT_EQ("2 3 1", 204 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 205 206 // Since neither |window3| nor |window1| have a delegate, |window2| should 207 // not move in front of either. 208 window3->layer()->set_delegate(NULL); 209 root_window()->StackChildBelow(window2.get(), window1.get()); 210 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window())); 211 EXPECT_EQ("2 3 1", 212 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 213} 214 215} // namespace wm 216