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 "ui/views/view.h"
6
7 #include <memory>
8
9 #include "ui/aura/window.h"
10 #include "ui/compositor/layer.h"
11 #include "ui/compositor/layer_tree_owner.h"
12 #include "ui/compositor/test/test_layers.h"
13 #include "ui/gfx/geometry/rect.h"
14 #include "ui/views/test/views_test_base.h"
15 #include "ui/views/view_constants_aura.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/wm/core/window_util.h"
18
19 namespace views {
20
21 namespace {
22
23 // Creates a widget of TYPE_CONTROL.
24 // The caller takes ownership of the returned widget.
CreateControlWidget(aura::Window * parent,const gfx::Rect & bounds)25 Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) {
26 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
27 params.parent = parent;
28 params.bounds = bounds;
29 Widget* widget = new Widget();
30 widget->Init(std::move(params));
31 return widget;
32 }
33
34 // Returns a view with a layer with the passed in |bounds| and |layer_name|.
35 // The caller takes ownership of the returned view.
CreateViewWithLayer(const gfx::Rect & bounds,const char * layer_name)36 View* CreateViewWithLayer(const gfx::Rect& bounds, const char* layer_name) {
37 View* view = new View();
38 view->SetBoundsRect(bounds);
39 view->SetPaintToLayer();
40 view->layer()->SetName(layer_name);
41 return view;
42 }
43
44 } // namespace
45
46 class ViewAuraTest : public ViewsTestBase {
47 public:
48 ViewAuraTest() = default;
49 ~ViewAuraTest() override = default;
50
GetViewsWithLayers(Widget * widget)51 const View::Views& GetViewsWithLayers(Widget* widget) {
52 return widget->GetViewsWithLayers();
53 }
54
55 private:
56 DISALLOW_COPY_AND_ASSIGN(ViewAuraTest);
57 };
58
59 // Test that wm::RecreateLayers() recreates the layers for all child windows and
60 // all child views and that the z-order of the recreated layers matches that of
61 // the original layers.
62 // Test hierarchy:
63 // w1
64 // +-- v1
65 // +-- v2 (no layer)
66 // +-- v3 (no layer)
67 // +-- v4
68 // +-- w2
69 // +-- v5
70 // +-- v6
71 // +-- v7
72 // +-- v8
73 // +-- v9
TEST_F(ViewAuraTest,RecreateLayersWithWindows)74 TEST_F(ViewAuraTest, RecreateLayersWithWindows) {
75 Widget* w1 = CreateControlWidget(GetContext(), gfx::Rect(0, 0, 100, 100));
76 w1->GetNativeView()->layer()->SetName("w1");
77
78 View* v2 = new View();
79 v2->SetBounds(0, 1, 100, 101);
80 View* v3 = new View();
81 v3->SetBounds(0, 2, 100, 102);
82 View* w2_host_view = new View();
83
84 View* v1 = CreateViewWithLayer(gfx::Rect(0, 3, 100, 103), "v1");
85 ui::Layer* v1_layer = v1->layer();
86 w1->GetRootView()->AddChildView(v1);
87 w1->GetRootView()->AddChildView(v2);
88 v2->AddChildView(v3);
89 View* v4 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4");
90 ui::Layer* v4_layer = v4->layer();
91 v2->AddChildView(v4);
92
93 w1->GetRootView()->AddChildView(w2_host_view);
94 View* v7 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v7");
95 ui::Layer* v7_layer = v7->layer();
96 w1->GetRootView()->AddChildView(v7);
97
98 View* v8 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v8");
99 ui::Layer* v8_layer = v8->layer();
100 v7->AddChildView(v8);
101
102 View* v9 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v9");
103 ui::Layer* v9_layer = v9->layer();
104 v7->AddChildView(v9);
105
106 Widget* w2 =
107 CreateControlWidget(w1->GetNativeView(), gfx::Rect(0, 5, 100, 105));
108 w2->GetNativeView()->layer()->SetName("w2");
109 w2->GetNativeView()->SetProperty(kHostViewKey, w2_host_view);
110
111 View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
112 w2->GetRootView()->AddChildView(v5);
113 View* v6 = CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6");
114 ui::Layer* v6_layer = v6->layer();
115 v5->AddChildView(v6);
116
117 // Test the initial order of the layers.
118 ui::Layer* w1_layer = w1->GetNativeView()->layer();
119 ASSERT_EQ("w1", w1_layer->name());
120 ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
121 ui::Layer* w2_layer = w1_layer->children()[2];
122 ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
123 ui::Layer* v5_layer = w2_layer->children()[0];
124 ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
125
126 // Verify the value of Widget::GetRootLayers(). It should only include layers
127 // from layer-backed Views descended from the Widget's root View.
128 View::Views old_w1_views_with_layers = GetViewsWithLayers(w1);
129 ASSERT_EQ(3u, old_w1_views_with_layers.size());
130 EXPECT_EQ(v1, old_w1_views_with_layers[0]);
131 EXPECT_EQ(v4, old_w1_views_with_layers[1]);
132 EXPECT_EQ(v7, old_w1_views_with_layers[2]);
133
134 {
135 std::unique_ptr<ui::LayerTreeOwner> cloned_owner(
136 wm::RecreateLayers(w1->GetNativeView()));
137 EXPECT_EQ(w1_layer, cloned_owner->root());
138 EXPECT_NE(w1_layer, w1->GetNativeView()->layer());
139
140 // The old layers should still exist and have the same hierarchy.
141 ASSERT_EQ("w1", w1_layer->name());
142 ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
143 ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
144 ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
145 EXPECT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_layer));
146
147 ASSERT_EQ(4u, w1_layer->children().size());
148 EXPECT_EQ(v1_layer, w1_layer->children()[0]);
149 EXPECT_EQ(v4_layer, w1_layer->children()[1]);
150 EXPECT_EQ(w2_layer, w1_layer->children()[2]);
151 EXPECT_EQ(v7_layer, w1_layer->children()[3]);
152
153 ASSERT_EQ(1u, w2_layer->children().size());
154 EXPECT_EQ(v5_layer, w2_layer->children()[0]);
155
156 ASSERT_EQ(1u, v5_layer->children().size());
157 EXPECT_EQ(v6_layer, v5_layer->children()[0]);
158
159 ASSERT_EQ(0u, v6_layer->children().size());
160
161 EXPECT_EQ(2u, v7_layer->children().size());
162 EXPECT_EQ(v8_layer, v7_layer->children()[0]);
163 EXPECT_EQ(v9_layer, v7_layer->children()[1]);
164
165 // The cloned layers should have the same hierarchy as old, but with new
166 // ui::Layer instances.
167 ui::Layer* w1_new_layer = w1->GetNativeView()->layer();
168 EXPECT_EQ("w1", w1_new_layer->name());
169 EXPECT_NE(w1_layer, w1_new_layer);
170 ui::Layer* v1_new_layer = w1_new_layer->children()[0];
171 ui::Layer* v4_new_layer = w1_new_layer->children()[1];
172 ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_new_layer));
173 EXPECT_NE(v1_layer, v1_new_layer);
174 EXPECT_NE(v4_layer, v4_new_layer);
175 ui::Layer* w2_new_layer = w1_new_layer->children()[2];
176 ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_new_layer));
177 ui::Layer* v5_new_layer = w2_new_layer->children()[0];
178 ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_new_layer));
179 ui::Layer* v7_new_layer = w1_new_layer->children()[3];
180 ASSERT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_new_layer));
181 EXPECT_NE(v7_layer, v7_new_layer);
182
183 // Ensure Widget::GetViewsWithLayers() is correctly updated.
184 View::Views new_w1_views_with_layers = GetViewsWithLayers(w1);
185 ASSERT_EQ(3u, new_w1_views_with_layers.size());
186 EXPECT_EQ(v1, new_w1_views_with_layers[0]);
187 EXPECT_EQ(v4, new_w1_views_with_layers[1]);
188 EXPECT_EQ(v7, new_w1_views_with_layers[2]);
189 }
190 w1->CloseNow();
191 }
192
193 } // namespace views
194