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