Home | History | Annotate | Download | only in widget
      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