1 // Copyright 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/aura/root_window.h" 6 #include "ui/aura/test/aura_test_base.h" 7 #include "ui/aura/test/test_windows.h" 8 #include "ui/aura/window.h" 9 #include "ui/compositor/layer.h" 10 #include "ui/compositor/test/test_layers.h" 11 #include "ui/views/view.h" 12 #include "ui/views/view_constants_aura.h" 13 #include "ui/views/widget/widget.h" 14 15 namespace views { 16 namespace { 17 18 // Creates a control widget with the passed in parameters. 19 // The caller takes ownership of the returned widget. 20 Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) { 21 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); 22 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 23 params.parent = parent; 24 params.bounds = bounds; 25 Widget* widget = new Widget(); 26 widget->Init(params); 27 return widget; 28 } 29 30 // Sets the name of |window| and |window|'s layer to |name|. 31 void SetWindowAndLayerName(aura::Window* window, const std::string& name) { 32 window->SetName(name); 33 window->layer()->set_name(name); 34 } 35 36 // Returns a string containing the name of each of the child windows (bottommost 37 // first) of |parent|. The format of the string is "name1 name2 name3 ...". 38 std::string ChildWindowNamesAsString(const aura::Window& parent) { 39 std::string names; 40 typedef std::vector<aura::Window*> Windows; 41 for (Windows::const_iterator it = parent.children().begin(); 42 it != parent.children().end(); ++it) { 43 if (!names.empty()) 44 names += " "; 45 names += (*it)->name(); 46 } 47 return names; 48 } 49 50 typedef aura::test::AuraTestBase WindowReordererTest; 51 52 // Test that views with layers and views with associated windows are reordered 53 // according to the view hierarchy. 54 TEST_F(WindowReordererTest, Basic) { 55 scoped_ptr<Widget> parent(CreateControlWidget(root_window(), 56 gfx::Rect(0, 0, 100, 100))); 57 parent->Show(); 58 aura::Window* parent_window = parent->GetNativeWindow(); 59 60 View* contents_view = new View(); 61 parent->SetContentsView(contents_view); 62 63 // 1) Test that layers for views and layers for windows associated to a host 64 // view are stacked below the layers for any windows not associated to a host 65 // view. 66 View* v = new View(); 67 v->SetPaintToLayer(true); 68 v->layer()->set_name("v"); 69 contents_view->AddChildView(v); 70 71 scoped_ptr<Widget> w1(CreateControlWidget(parent_window, 72 gfx::Rect(0, 1, 100, 101))); 73 SetWindowAndLayerName(w1->GetNativeView(), "w1"); 74 w1->Show(); 75 scoped_ptr<Widget> w2(CreateControlWidget(parent_window, 76 gfx::Rect(0, 2, 100, 102))); 77 SetWindowAndLayerName(w2->GetNativeView(), "w2"); 78 w2->Show(); 79 80 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 81 EXPECT_EQ("v w1 w2", 82 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 83 84 View* host_view2 = new View(); 85 contents_view->AddChildView(host_view2); 86 w2->GetNativeView()->SetProperty(kHostViewKey, host_view2); 87 EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); 88 EXPECT_EQ("v w2 w1", 89 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 90 91 View* host_view1 = new View(); 92 w1->GetNativeView()->SetProperty(kHostViewKey, host_view1); 93 contents_view->AddChildViewAt(host_view1, 0); 94 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 95 EXPECT_EQ("w1 v w2", 96 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 97 98 // 2) Test the z-order of the windows and layers as a result of reordering the 99 // views. 100 contents_view->ReorderChildView(host_view1, -1); 101 EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); 102 EXPECT_EQ("v w2 w1", 103 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 104 105 contents_view->ReorderChildView(host_view2, -1); 106 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 107 EXPECT_EQ("v w1 w2", 108 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 109 110 // 3) Test the z-order of the windows and layers as a result of reordering the 111 // views in situations where the window order remains unchanged. 112 contents_view->ReorderChildView(v, -1); 113 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 114 EXPECT_EQ("w1 w2 v", 115 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 116 117 contents_view->ReorderChildView(host_view2, -1); 118 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 119 EXPECT_EQ("w1 v w2", 120 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 121 122 // Work around for bug in NativeWidgetAura. 123 // TODO: fix bug and remove this. 124 parent->Close(); 125 } 126 127 // Test that different orderings of: 128 // - adding a window to a parent widget 129 // - adding a "host" view to a parent widget 130 // - associating the "host" view and window 131 // all correctly reorder the child windows and layers. 132 TEST_F(WindowReordererTest, Association) { 133 scoped_ptr<Widget> parent(CreateControlWidget(root_window(), 134 gfx::Rect(0, 0, 100, 100))); 135 parent->Show(); 136 aura::Window* parent_window = parent->GetNativeWindow(); 137 138 View* contents_view = new View(); 139 parent->SetContentsView(contents_view); 140 141 aura::Window* w1 = aura::test::CreateTestWindowWithId(0, 142 parent->GetNativeWindow()); 143 SetWindowAndLayerName(w1, "w1"); 144 145 aura::Window* w2 = aura::test::CreateTestWindowWithId(0, NULL); 146 SetWindowAndLayerName(w2, "w2"); 147 148 View* host_view2 = new View(); 149 150 // 1) Test that parenting the window to the parent widget last results in a 151 // correct ordering of child windows and layers. 152 contents_view->AddChildView(host_view2); 153 w2->SetProperty(views::kHostViewKey, host_view2); 154 EXPECT_EQ("w1", ChildWindowNamesAsString(*parent_window)); 155 EXPECT_EQ("w1", 156 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 157 158 parent_window->AddChild(w2); 159 EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); 160 EXPECT_EQ("w2 w1", 161 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 162 163 // 2) Test that associating the window and "host" view last results in a 164 // correct ordering of child windows and layers. 165 View* host_view1 = new View(); 166 contents_view->AddChildViewAt(host_view1, 0); 167 EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); 168 EXPECT_EQ("w2 w1", 169 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 170 171 w1->SetProperty(views::kHostViewKey, host_view1); 172 EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); 173 EXPECT_EQ("w1 w2", 174 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 175 176 // 3) Test that parenting the "host" view to the parent widget last results 177 // in a correct ordering of child windows and layers. 178 contents_view->RemoveChildView(host_view2); 179 contents_view->AddChildViewAt(host_view2, 0); 180 EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); 181 EXPECT_EQ("w2 w1", 182 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 183 184 // Work around for bug in NativeWidgetAura. 185 // TODO: fix bug and remove this. 186 parent->Close(); 187 } 188 189 // It is possible to associate a window to a view which has a parent layer 190 // (other than the widget layer). In this case, the parent layer of the host 191 // view and the parent layer of the associated window are different. Test that 192 // the layers and windows are properly reordered in this case. 193 TEST_F(WindowReordererTest, HostViewParentHasLayer) { 194 scoped_ptr<Widget> parent(CreateControlWidget(root_window(), 195 gfx::Rect(0, 0, 100, 100))); 196 parent->Show(); 197 aura::Window* parent_window = parent->GetNativeWindow(); 198 199 View* contents_view = new View(); 200 parent->SetContentsView(contents_view); 201 202 // Create the following view hierarchy. (*) denotes views which paint to a 203 // layer. 204 // 205 // contents_view 206 // +-- v1 207 // +-- v11* 208 // +-- v12 (attached window) 209 // +-- v13* 210 // +--v2* 211 212 View* v1 = new View(); 213 contents_view->AddChildView(v1); 214 215 View* v11 = new View(); 216 v11->SetPaintToLayer(true); 217 v11->layer()->set_name("v11"); 218 v1->AddChildView(v11); 219 220 scoped_ptr<Widget> w(CreateControlWidget(parent_window, 221 gfx::Rect(0, 1, 100, 101))); 222 SetWindowAndLayerName(w->GetNativeView(), "w"); 223 w->Show(); 224 225 View* v12 = new View(); 226 v1->AddChildView(v12); 227 w->GetNativeView()->SetProperty(kHostViewKey, v12); 228 229 View* v13 = new View(); 230 v13->SetPaintToLayer(true); 231 v13->layer()->set_name("v13"); 232 v1->AddChildView(v13); 233 234 View* v2 = new View(); 235 v2->SetPaintToLayer(true); 236 v2->layer()->set_name("v2"); 237 contents_view->AddChildView(v2); 238 239 // Test intial state. 240 EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); 241 EXPECT_EQ("v11 w v13 v2", 242 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 243 244 // |w|'s layer should be stacked above |v1|'s layer. 245 v1->SetPaintToLayer(true); 246 v1->layer()->set_name("v1"); 247 EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); 248 EXPECT_EQ("v1 w v2", 249 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 250 251 // Test moving the host view from one view with a layer to another. 252 v2->AddChildView(v12); 253 EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); 254 EXPECT_EQ("v1 v2 w", 255 ui::test::ChildLayerNamesAsString(*parent_window->layer())); 256 257 // Work around for bug in NativeWidgetAura. 258 // TODO: fix bug and remove this. 259 parent->Close(); 260 } 261 262 } // namespace 263 } // namespace views 264