// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/compositor/layer.h" #include "ui/compositor/test/test_layers.h" #include "ui/views/view.h" #include "ui/views/view_constants_aura.h" #include "ui/views/widget/widget.h" namespace views { namespace { // Creates a control widget with the passed in parameters. // The caller takes ownership of the returned widget. Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) { Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.parent = parent; params.bounds = bounds; Widget* widget = new Widget(); widget->Init(params); return widget; } // Sets the name of |window| and |window|'s layer to |name|. void SetWindowAndLayerName(aura::Window* window, const std::string& name) { window->SetName(name); window->layer()->set_name(name); } // Returns a string containing the name of each of the child windows (bottommost // first) of |parent|. The format of the string is "name1 name2 name3 ...". std::string ChildWindowNamesAsString(const aura::Window& parent) { std::string names; typedef std::vector Windows; for (Windows::const_iterator it = parent.children().begin(); it != parent.children().end(); ++it) { if (!names.empty()) names += " "; names += (*it)->name(); } return names; } typedef aura::test::AuraTestBase WindowReordererTest; // Test that views with layers and views with associated windows are reordered // according to the view hierarchy. TEST_F(WindowReordererTest, Basic) { scoped_ptr parent(CreateControlWidget(root_window(), gfx::Rect(0, 0, 100, 100))); parent->Show(); aura::Window* parent_window = parent->GetNativeWindow(); View* contents_view = new View(); parent->SetContentsView(contents_view); // 1) Test that layers for views and layers for windows associated to a host // view are stacked below the layers for any windows not associated to a host // view. View* v = new View(); v->SetPaintToLayer(true); v->layer()->set_name("v"); contents_view->AddChildView(v); scoped_ptr w1(CreateControlWidget(parent_window, gfx::Rect(0, 1, 100, 101))); SetWindowAndLayerName(w1->GetNativeView(), "w1"); w1->Show(); scoped_ptr w2(CreateControlWidget(parent_window, gfx::Rect(0, 2, 100, 102))); SetWindowAndLayerName(w2->GetNativeView(), "w2"); w2->Show(); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v w1 w2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); View* host_view2 = new View(); contents_view->AddChildView(host_view2); w2->GetNativeView()->SetProperty(kHostViewKey, host_view2); EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v w2 w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); View* host_view1 = new View(); w1->GetNativeView()->SetProperty(kHostViewKey, host_view1); contents_view->AddChildViewAt(host_view1, 0); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w1 v w2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // 2) Test the z-order of the windows and layers as a result of reordering the // views. contents_view->ReorderChildView(host_view1, -1); EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v w2 w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); contents_view->ReorderChildView(host_view2, -1); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v w1 w2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // 3) Test the z-order of the windows and layers as a result of reordering the // views in situations where the window order remains unchanged. contents_view->ReorderChildView(v, -1); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w1 w2 v", ui::test::ChildLayerNamesAsString(*parent_window->layer())); contents_view->ReorderChildView(host_view2, -1); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w1 v w2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // Work around for bug in NativeWidgetAura. // TODO: fix bug and remove this. parent->Close(); } // Test that different orderings of: // - adding a window to a parent widget // - adding a "host" view to a parent widget // - associating the "host" view and window // all correctly reorder the child windows and layers. TEST_F(WindowReordererTest, Association) { scoped_ptr parent(CreateControlWidget(root_window(), gfx::Rect(0, 0, 100, 100))); parent->Show(); aura::Window* parent_window = parent->GetNativeWindow(); View* contents_view = new View(); parent->SetContentsView(contents_view); aura::Window* w1 = aura::test::CreateTestWindowWithId(0, parent->GetNativeWindow()); SetWindowAndLayerName(w1, "w1"); aura::Window* w2 = aura::test::CreateTestWindowWithId(0, NULL); SetWindowAndLayerName(w2, "w2"); View* host_view2 = new View(); // 1) Test that parenting the window to the parent widget last results in a // correct ordering of child windows and layers. contents_view->AddChildView(host_view2); w2->SetProperty(views::kHostViewKey, host_view2); EXPECT_EQ("w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); parent_window->AddChild(w2); EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w2 w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // 2) Test that associating the window and "host" view last results in a // correct ordering of child windows and layers. View* host_view1 = new View(); contents_view->AddChildViewAt(host_view1, 0); EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w2 w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); w1->SetProperty(views::kHostViewKey, host_view1); EXPECT_EQ("w1 w2", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w1 w2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // 3) Test that parenting the "host" view to the parent widget last results // in a correct ordering of child windows and layers. contents_view->RemoveChildView(host_view2); contents_view->AddChildViewAt(host_view2, 0); EXPECT_EQ("w2 w1", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("w2 w1", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // Work around for bug in NativeWidgetAura. // TODO: fix bug and remove this. parent->Close(); } // It is possible to associate a window to a view which has a parent layer // (other than the widget layer). In this case, the parent layer of the host // view and the parent layer of the associated window are different. Test that // the layers and windows are properly reordered in this case. TEST_F(WindowReordererTest, HostViewParentHasLayer) { scoped_ptr parent(CreateControlWidget(root_window(), gfx::Rect(0, 0, 100, 100))); parent->Show(); aura::Window* parent_window = parent->GetNativeWindow(); View* contents_view = new View(); parent->SetContentsView(contents_view); // Create the following view hierarchy. (*) denotes views which paint to a // layer. // // contents_view // +-- v1 // +-- v11* // +-- v12 (attached window) // +-- v13* // +--v2* View* v1 = new View(); contents_view->AddChildView(v1); View* v11 = new View(); v11->SetPaintToLayer(true); v11->layer()->set_name("v11"); v1->AddChildView(v11); scoped_ptr w(CreateControlWidget(parent_window, gfx::Rect(0, 1, 100, 101))); SetWindowAndLayerName(w->GetNativeView(), "w"); w->Show(); View* v12 = new View(); v1->AddChildView(v12); w->GetNativeView()->SetProperty(kHostViewKey, v12); View* v13 = new View(); v13->SetPaintToLayer(true); v13->layer()->set_name("v13"); v1->AddChildView(v13); View* v2 = new View(); v2->SetPaintToLayer(true); v2->layer()->set_name("v2"); contents_view->AddChildView(v2); // Test intial state. EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v11 w v13 v2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // |w|'s layer should be stacked above |v1|'s layer. v1->SetPaintToLayer(true); v1->layer()->set_name("v1"); EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v1 w v2", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // Test moving the host view from one view with a layer to another. v2->AddChildView(v12); EXPECT_EQ("w", ChildWindowNamesAsString(*parent_window)); EXPECT_EQ("v1 v2 w", ui::test::ChildLayerNamesAsString(*parent_window->layer())); // Work around for bug in NativeWidgetAura. // TODO: fix bug and remove this. parent->Close(); } } // namespace } // namespace views