| // Copyright (c) 2012 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/wm/core/window_modality_controller.h" |
| |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/test/child_modal_window.h" |
| #include "ash/wm/window_util.h" |
| #include "ui/aura/client/aura_constants.h" |
| #include "ui/aura/client/capture_client.h" |
| #include "ui/aura/test/test_window_delegate.h" |
| #include "ui/aura/test/test_windows.h" |
| #include "ui/aura/window.h" |
| #include "ui/aura/window_event_dispatcher.h" |
| #include "ui/base/ui_base_types.h" |
| #include "ui/events/test/event_generator.h" |
| #include "ui/views/test/capture_tracking_view.h" |
| #include "ui/views/widget/widget.h" |
| #include "ui/wm/core/window_util.h" |
| |
| namespace ash { |
| |
| typedef test::AshTestBase WindowModalityControllerTest; |
| |
| namespace { |
| |
| bool ValidateStacking(aura::Window* parent, int ids[], int count) { |
| for (int i = 0; i < count; ++i) { |
| if (parent->children().at(i)->id() != ids[i]) |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace |
| |
| // Creates three windows, w1, w11, and w12. w11 is a non-modal transient, w12 is |
| // a modal transient. |
| // Validates: |
| // - it should be possible to activate w12 even when w11 is open. |
| // - activating w1 activates w12 and updates stacking order appropriately. |
| // - closing a window passes focus up the stack. |
| TEST_F(WindowModalityControllerTest, BasicActivation) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w11( |
| CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); |
| std::unique_ptr<aura::Window> w12( |
| CreateTestWindowInShellWithDelegate(&d, -12, gfx::Rect())); |
| |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| wm::ActivateWindow(w11.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| |
| w12->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| ::wm::AddTransientChild(w1.get(), w12.get()); |
| wm::ActivateWindow(w12.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w12.get())); |
| |
| wm::ActivateWindow(w11.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| |
| int check1[] = {-1, -12, -11}; |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w12.get())); |
| // Transient children are always stacked above their transient parent, which |
| // is why this order is not -11, -1, -12. |
| int check2[] = {-1, -11, -12}; |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2))); |
| |
| w12.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| w11.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| } |
| |
| // Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below |
| // w1. |
| // Validates: |
| // - activating w1 while w11/w111 is showing always activates most deeply nested |
| // descendant. |
| // - closing a window passes focus up the stack. |
| TEST_F(WindowModalityControllerTest, NestedModals) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w11( |
| CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); |
| std::unique_ptr<aura::Window> w111( |
| CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect())); |
| std::unique_ptr<aura::Window> w2( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| ::wm::AddTransientChild(w11.get(), w111.get()); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| wm::ActivateWindow(w2.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w2.get())); |
| |
| // Set up modality. |
| w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w111.get())); |
| int check1[] = {-2, -1, -11, -111}; |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); |
| |
| wm::ActivateWindow(w11.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w111.get())); |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); |
| |
| wm::ActivateWindow(w111.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w111.get())); |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1))); |
| |
| wm::ActivateWindow(w2.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w2.get())); |
| int check2[] = {-1, -11, -111, -2}; |
| EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2))); |
| |
| w2.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w111.get())); |
| w111.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| w11.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| } |
| |
| // Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below |
| // w1. |
| // Validates: |
| // - destroying w11 while w111 is focused activates w1. |
| TEST_F(WindowModalityControllerTest, NestedModalsOuterClosed) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w11( |
| CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect())); |
| // |w111| will be owned and deleted by |w11|. |
| aura::Window* w111 = |
| CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect()); |
| std::unique_ptr<aura::Window> w2( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| ::wm::AddTransientChild(w11.get(), w111); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| wm::ActivateWindow(w2.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w2.get())); |
| |
| // Set up modality. |
| w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w111)); |
| |
| w111->Hide(); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| |
| // TODO(oshima): Re-showing doesn't set the focus back to |
| // modal window. There is no such use case right now, but it |
| // probably should. |
| |
| w11.reset(); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| } |
| |
| // Modality also prevents events from being passed to the transient parent. |
| TEST_F(WindowModalityControllerTest, Events) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect(0, 0, 100, 100))); |
| std::unique_ptr<aura::Window> w11( |
| CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect(20, 20, 50, 50))); |
| std::unique_ptr<aura::Window> w111( |
| CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect(20, 20, 50, 50))); |
| |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| |
| // Add a non-modal child to the modal window in order to ensure modality still |
| // works in this case. This is a regression test for https://crbug.com/456697. |
| ::wm::AddTransientChild(w11.get(), w111.get()); |
| |
| { |
| // Clicking a point within w1 should activate that window. |
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
| gfx::Point(10, 10)); |
| generator.ClickLeftButton(); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| } |
| |
| w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| |
| { |
| // Clicking a point within w1 should activate w11. |
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
| gfx::Point(10, 10)); |
| generator.ClickLeftButton(); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| } |
| } |
| |
| // Events on modal parent activate. |
| TEST_F(WindowModalityControllerTest, EventsForEclipsedWindows) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect(0, 0, 100, 100))); |
| std::unique_ptr<aura::Window> w11( |
| CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect(20, 20, 50, 50))); |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| std::unique_ptr<aura::Window> w2( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect(0, 0, 50, 50))); |
| |
| w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| |
| // Partially eclipse w1 with w2. |
| wm::ActivateWindow(w2.get()); |
| { |
| // Clicking a point on w1 that is not eclipsed by w2. |
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
| gfx::Point(90, 90)); |
| generator.ClickLeftButton(); |
| EXPECT_TRUE(wm::IsActiveWindow(w11.get())); |
| } |
| } |
| |
| // Creates windows w1 and non activatiable child w11. Creates transient window |
| // w2 and adds it as a transeint child of w1. Ensures that w2 is parented to |
| // the parent of w1, and that GetModalTransient(w11) returns w2. |
| TEST_F(WindowModalityControllerTest, GetModalTransient) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w11( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); |
| std::unique_ptr<aura::Window> w2( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| |
| aura::Window* wt; |
| wt = ::wm::GetModalTransient(w1.get()); |
| ASSERT_EQ(static_cast<aura::Window*>(NULL), wt); |
| |
| // Parent w2 to w1. It should get parented to the parent of w1. |
| ::wm::AddTransientChild(w1.get(), w2.get()); |
| ASSERT_EQ(2U, w1->parent()->children().size()); |
| EXPECT_EQ(-2, w1->parent()->children().at(1)->id()); |
| |
| // Request the modal transient window for w1, it should be w2. |
| wt = ::wm::GetModalTransient(w1.get()); |
| ASSERT_NE(static_cast<aura::Window*>(NULL), wt); |
| EXPECT_EQ(-2, wt->id()); |
| |
| // Request the modal transient window for w11, it should also be w2. |
| wt = ::wm::GetModalTransient(w11.get()); |
| ASSERT_NE(static_cast<aura::Window*>(NULL), wt); |
| EXPECT_EQ(-2, wt->id()); |
| } |
| |
| // Verifies we generate a capture lost when showing a modal window. |
| TEST_F(WindowModalityControllerTest, ChangeCapture) { |
| views::Widget* widget = views::Widget::CreateWindowWithContext( |
| NULL, Shell::GetPrimaryRootWindow()); |
| std::unique_ptr<aura::Window> widget_window(widget->GetNativeView()); |
| views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView; |
| widget->client_view()->AddChildView(view); |
| widget->SetBounds(gfx::Rect(0, 0, 200, 200)); |
| view->SetBoundsRect(widget->client_view()->GetLocalBounds()); |
| widget->Show(); |
| |
| gfx::Point center(view->width() / 2, view->height() / 2); |
| views::View::ConvertPointToScreen(view, ¢er); |
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center); |
| generator.PressLeftButton(); |
| EXPECT_TRUE(view->got_press()); |
| |
| views::Widget* modal_widget = |
| views::Widget::CreateWindowWithParent(NULL, widget->GetNativeView()); |
| std::unique_ptr<aura::Window> modal_window(modal_widget->GetNativeView()); |
| modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| views::test::CaptureTrackingView* modal_view = |
| new views::test::CaptureTrackingView; |
| modal_widget->client_view()->AddChildView(modal_view); |
| modal_widget->SetBounds(gfx::Rect(50, 50, 200, 200)); |
| modal_view->SetBoundsRect(modal_widget->client_view()->GetLocalBounds()); |
| modal_widget->Show(); |
| |
| EXPECT_TRUE(view->got_capture_lost()); |
| generator.ReleaseLeftButton(); |
| |
| view->reset(); |
| |
| EXPECT_FALSE(modal_view->got_capture_lost()); |
| EXPECT_FALSE(modal_view->got_press()); |
| |
| gfx::Point modal_center(modal_view->width() / 2, modal_view->height() / 2); |
| views::View::ConvertPointToScreen(modal_view, &modal_center); |
| generator.MoveMouseTo(modal_center, 1); |
| generator.PressLeftButton(); |
| EXPECT_TRUE(modal_view->got_press()); |
| EXPECT_FALSE(modal_view->got_capture_lost()); |
| EXPECT_FALSE(view->got_capture_lost()); |
| EXPECT_FALSE(view->got_press()); |
| } |
| |
| // Test that when a child modal window becomes visible, we only release the |
| // capture window if the current capture window is in the hierarchy of the child |
| // modal window's modal parent window. |
| TEST_F(WindowModalityControllerTest, ReleaseCapture) { |
| // Create a window hierachy like this: |
| // _______________w0______________ |
| // | | | |
| // w1 <------ w3 w2 |
| // | (modal to) |
| // w11 |
| |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w11( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); |
| std::unique_ptr<aura::Window> w2( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| std::unique_ptr<aura::Window> w3( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| w3->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD); |
| ::wm::SetModalParent(w3.get(), w1.get()); |
| |
| // w1's capture should be released when w3 becomes visible. |
| w3->Hide(); |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->SetCapture(w1.get()); |
| EXPECT_EQ(w1.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| w3->Show(); |
| EXPECT_NE(w1.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| |
| // w11's capture should be released when w3 becomes visible. |
| w3->Hide(); |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->SetCapture(w11.get()); |
| EXPECT_EQ(w11.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| w3->Show(); |
| EXPECT_NE(w11.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| |
| // w2's capture should not be released when w3 becomes visible. |
| w3->Hide(); |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->SetCapture(w2.get()); |
| EXPECT_EQ(w2.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| w3->Show(); |
| EXPECT_EQ(w2.get(), |
| aura::client::GetCaptureClient(Shell::GetPrimaryRootWindow()) |
| ->GetGlobalCaptureWindow()); |
| } |
| |
| class TouchTrackerWindowDelegate : public aura::test::TestWindowDelegate { |
| public: |
| TouchTrackerWindowDelegate() |
| : received_touch_(false), last_event_type_(ui::ET_UNKNOWN) {} |
| ~TouchTrackerWindowDelegate() override {} |
| |
| void reset() { |
| received_touch_ = false; |
| last_event_type_ = ui::ET_UNKNOWN; |
| } |
| |
| bool received_touch() const { return received_touch_; } |
| ui::EventType last_event_type() const { return last_event_type_; } |
| |
| private: |
| // Overridden from aura::test::TestWindowDelegate. |
| void OnTouchEvent(ui::TouchEvent* event) override { |
| received_touch_ = true; |
| last_event_type_ = event->type(); |
| aura::test::TestWindowDelegate::OnTouchEvent(event); |
| } |
| |
| bool received_touch_; |
| ui::EventType last_event_type_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TouchTrackerWindowDelegate); |
| }; |
| |
| // Modality should prevent events from being passed to the transient parent. |
| TEST_F(WindowModalityControllerTest, TouchEvent) { |
| TouchTrackerWindowDelegate d1; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d1, -1, gfx::Rect(0, 0, 100, 100))); |
| TouchTrackerWindowDelegate d11; |
| std::unique_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate( |
| &d11, -11, gfx::Rect(20, 20, 50, 50))); |
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
| gfx::Point(10, 10)); |
| |
| ::wm::AddTransientChild(w1.get(), w11.get()); |
| d1.reset(); |
| d11.reset(); |
| |
| { |
| // Clicking a point within w1 should activate that window. |
| generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10)); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| EXPECT_TRUE(d1.received_touch()); |
| EXPECT_FALSE(d11.received_touch()); |
| } |
| |
| { |
| // Adding a modal window while a touch is down should fire a touch cancel. |
| generator.PressTouch(); |
| generator.MoveTouch(gfx::Point(10, 10)); |
| d1.reset(); |
| d11.reset(); |
| |
| w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| EXPECT_TRUE(d1.received_touch()); |
| EXPECT_EQ(ui::ET_TOUCH_CANCELLED, d1.last_event_type()); |
| EXPECT_FALSE(d11.received_touch()); |
| } |
| } |
| |
| // Child-modal test. |
| // Creates: |
| // - A |parent| window that hosts a |modal_parent| window within itself. The |
| // |parent| and |modal_parent| windows are not the same window. The |
| // |modal_parent| window is not activatable, because it's contained within the |
| // |parent| window. |
| // - A |child| window with parent window |parent|, but is modal to |
| // |modal_parent| window. |
| // Validates: |
| // - Clicking on the |modal_parent| should activate the |child| window. |
| // - Clicking on the |parent| window outside of the |modal_parent| bounds should |
| // activate the |parent| window. |
| // - Clicking on the |child| while |parent| is active should activate the |
| // |child| window. |
| // - Focus should follow the active window. |
| TEST_F(WindowModalityControllerTest, ChildModal) { |
| test::ChildModalParent* delegate = |
| new test::ChildModalParent(CurrentContext()); |
| views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( |
| delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400)); |
| widget->Show(); |
| |
| aura::Window* parent = widget->GetNativeView(); |
| EXPECT_TRUE(wm::IsActiveWindow(parent)); |
| |
| aura::Window* modal_parent = delegate->GetModalParent(); |
| EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent); |
| EXPECT_NE(parent, modal_parent); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| |
| delegate->ShowChild(); |
| aura::Window* child = delegate->GetChild(); |
| EXPECT_NE(static_cast<aura::Window*>(NULL), child); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| |
| wm::ActivateWindow(modal_parent); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| |
| wm::ActivateWindow(parent); |
| |
| EXPECT_FALSE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_TRUE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_FALSE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_TRUE(parent->HasFocus()); |
| |
| wm::ActivateWindow(child); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| } |
| |
| // Same as |ChildModal| test, but using |EventGenerator| rather than bypassing |
| // it by calling |ActivateWindow|. |
| TEST_F(WindowModalityControllerTest, ChildModalEventGenerator) { |
| test::ChildModalParent* delegate = |
| new test::ChildModalParent(CurrentContext()); |
| views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( |
| delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400)); |
| widget->Show(); |
| |
| aura::Window* parent = widget->GetNativeView(); |
| EXPECT_TRUE(wm::IsActiveWindow(parent)); |
| |
| aura::Window* modal_parent = delegate->GetModalParent(); |
| EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent); |
| EXPECT_NE(parent, modal_parent); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| |
| delegate->ShowChild(); |
| aura::Window* child = delegate->GetChild(); |
| EXPECT_NE(static_cast<aura::Window*>(NULL), child); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| |
| { |
| ui::test::EventGenerator generator( |
| Shell::GetPrimaryRootWindow(), |
| parent->bounds().origin() + |
| gfx::Vector2d(10, parent->bounds().height() - 10)); |
| generator.ClickLeftButton(); |
| generator.ClickLeftButton(); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| } |
| |
| { |
| ui::test::EventGenerator generator( |
| Shell::GetPrimaryRootWindow(), |
| parent->bounds().origin() + gfx::Vector2d(10, 10)); |
| generator.ClickLeftButton(); |
| |
| EXPECT_FALSE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_TRUE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_FALSE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_TRUE(parent->HasFocus()); |
| } |
| |
| { |
| ui::test::EventGenerator generator( |
| Shell::GetPrimaryRootWindow(), |
| child->bounds().origin() + gfx::Vector2d(10, 10)); |
| generator.ClickLeftButton(); |
| |
| EXPECT_TRUE(wm::IsActiveWindow(child)); |
| EXPECT_FALSE(wm::IsActiveWindow(modal_parent)); |
| EXPECT_FALSE(wm::IsActiveWindow(parent)); |
| |
| EXPECT_TRUE(child->HasFocus()); |
| EXPECT_FALSE(modal_parent->HasFocus()); |
| EXPECT_FALSE(parent->HasFocus()); |
| } |
| } |
| |
| // Window-modal test for the case when the originally clicked window is an |
| // ancestor of the modal parent. |
| TEST_F(WindowModalityControllerTest, WindowModalAncestor) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w2( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); |
| std::unique_ptr<aura::Window> w3( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get())); |
| std::unique_ptr<aura::Window> w4( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); |
| ::wm::AddTransientChild(w1.get(), w4.get()); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| |
| wm::ActivateWindow(w2.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| |
| wm::ActivateWindow(w3.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| |
| wm::ActivateWindow(w4.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| } |
| |
| // Child-modal test for the case when the originally clicked window is an |
| // ancestor of the modal parent. |
| TEST_F(WindowModalityControllerTest, ChildModalAncestor) { |
| aura::test::TestWindowDelegate d; |
| std::unique_ptr<aura::Window> w1( |
| CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect())); |
| std::unique_ptr<aura::Window> w2( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get())); |
| std::unique_ptr<aura::Window> w3( |
| aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get())); |
| std::unique_ptr<aura::Window> w4( |
| CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect())); |
| w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD); |
| ::wm::SetModalParent(w4.get(), w2.get()); |
| ::wm::AddTransientChild(w1.get(), w4.get()); |
| |
| wm::ActivateWindow(w1.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w1.get())); |
| |
| wm::ActivateWindow(w2.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| |
| wm::ActivateWindow(w3.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| |
| wm::ActivateWindow(w4.get()); |
| EXPECT_TRUE(wm::IsActiveWindow(w4.get())); |
| } |
| |
| } // namespace ash |