From 1850ca92fc5c5faa2907b3befcf40067265148cc Mon Sep 17 00:00:00 2001 From: "Torne (Richard Coles)" Date: Wed, 12 Nov 2014 17:59:43 +0000 Subject: Merge from Chromium at DEPS revision 03655fd3f6d7 This commit was generated by merge_to_master.py. Change-Id: Ifba5396691b9164ba027be04398f7bc8e938750d --- athena/screen/modal_window_controller.cc | 6 +++ athena/screen/screen_manager_impl.cc | 44 ++++++++++++++-- athena/screen/screen_manager_unittest.cc | 88 +++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 5 deletions(-) (limited to 'athena/screen') diff --git a/athena/screen/modal_window_controller.cc b/athena/screen/modal_window_controller.cc index 90357e9ce4..140b2c9aba 100644 --- a/athena/screen/modal_window_controller.cc +++ b/athena/screen/modal_window_controller.cc @@ -111,6 +111,12 @@ void ModalWindowController::UpdateDimming(aura::Window* ignore) { // invisible, but don't delete it until next event execution // because the call stack may still have and use the pointer. modal_container_->RemoveObserver(this); + + // Hide the window before removing it, so the focus manager which will run + // in RemoveChild handler can know that this container is no longer + // available. + modal_container_->Hide(); + modal_container_->parent()->RemoveChild(modal_container_); base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, modal_container_); modal_container_ = nullptr; diff --git a/athena/screen/screen_manager_impl.cc b/athena/screen/screen_manager_impl.cc index 471df3b29d..20a4bd5d33 100644 --- a/athena/screen/screen_manager_impl.cc +++ b/athena/screen/screen_manager_impl.cc @@ -51,7 +51,7 @@ struct HigherPriorityFinder { bool BlockEvents(aura::Window* container) { ScreenManager::ContainerParams* params = container->GetProperty(kContainerParamsKey); - return params && params->block_events; + return params && params->block_events && container->IsVisible(); } bool DefaultContainer(aura::Window* container) { @@ -109,11 +109,47 @@ class AthenaFocusRules : public wm::BaseFocusRules { return BaseFocusRules::CanActivateWindow(window); } + aura::Window* GetTopmostWindowToActivateInContainer( + aura::Window* container, + aura::Window* ignore) const { + for (aura::Window::Windows::const_reverse_iterator i = + container->children().rbegin(); + i != container->children().rend(); + ++i) { + if (*i != ignore && CanActivateWindow(*i)) + return *i; + } + return NULL; + } + virtual aura::Window* GetNextActivatableWindow( aura::Window* ignore) const override { - aura::Window* next = wm::BaseFocusRules::GetNextActivatableWindow(ignore); - // TODO(oshima): Search from activatable containers if |next| is nullptr. - // crbug.com/424750. + const aura::Window::Windows& containers = + ignore->GetRootWindow()->children(); + auto starting_container_iter = containers.begin(); + for (auto container_iter = containers.begin(); + container_iter != containers.end(); + container_iter++) { + if ((*container_iter)->Contains(ignore)) { + starting_container_iter = container_iter; + break; + } + } + + // Find next window from the front containers. + aura::Window* next = nullptr; + for (auto container_iter = starting_container_iter; + !next && container_iter != containers.end(); + container_iter++) { + next = GetTopmostWindowToActivateInContainer(*container_iter, ignore); + } + + // Find next window from the back containers. + auto container_iter = starting_container_iter; + while (!next && container_iter != containers.begin()) { + container_iter--; + next = GetTopmostWindowToActivateInContainer(*container_iter, ignore); + } return next; } diff --git a/athena/screen/screen_manager_unittest.cc b/athena/screen/screen_manager_unittest.cc index dd634ba44a..15588d34e4 100644 --- a/athena/screen/screen_manager_unittest.cc +++ b/athena/screen/screen_manager_unittest.cc @@ -15,7 +15,8 @@ #include "ui/events/test/event_generator.h" #include "ui/wm/core/window_util.h" -typedef athena::test::AthenaTestBase ScreenManagerTest; +using ScreenManagerTest = athena::test::AthenaTestBase; +using AthenaFocusRuleTest = athena::test::AthenaTestBase; namespace athena { namespace { @@ -163,6 +164,91 @@ TEST_F(ScreenManagerTest, DefaultContainer) { parent->AddChild(original_default); } +TEST_F(AthenaFocusRuleTest, FocusTravarsalFromSameContainer) { + ScreenManager::ContainerParams params("contaier", kTestZOrderPriority); + params.can_activate_children = true; + scoped_ptr + container(ScreenManager::Get()->CreateContainer(params)); + + scoped_ptr w1(CreateWindow( + container.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + wm::ActivateWindow(w1.get()); + EXPECT_TRUE(wm::IsActiveWindow(w1.get())); + + scoped_ptr w2(CreateWindow( + container.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + EXPECT_TRUE(wm::IsActiveWindow(w1.get())); + + container->RemoveChild(w1.get()); + EXPECT_TRUE(wm::IsActiveWindow(w2.get())); +} + +TEST_F(AthenaFocusRuleTest, FocusTravarsalFromOtherContainer) { + ScreenManager::ContainerParams params2("contaier2", kTestZOrderPriority + 1); + params2.can_activate_children = true; + scoped_ptr + container2(ScreenManager::Get()->CreateContainer(params2)); + scoped_ptr w2(CreateWindow( + container2.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + wm::ActivateWindow(w2.get()); + EXPECT_TRUE(wm::IsActiveWindow(w2.get())); + + ScreenManager::ContainerParams params1("contaier1", kTestZOrderPriority); + params1.can_activate_children = true; + scoped_ptr + container1(ScreenManager::Get()->CreateContainer(params1)); + ScreenManager::ContainerParams params3("contaier3", kTestZOrderPriority + 2); + params3.can_activate_children = true; + scoped_ptr + container3(ScreenManager::Get()->CreateContainer(params3)); + scoped_ptr w1(CreateWindow( + container1.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + scoped_ptr w3(CreateWindow( + container3.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + + EXPECT_TRUE(wm::IsActiveWindow(w2.get())); + + container2->RemoveChild(w2.get()); + // Focus moves to a window in the front contaier. + EXPECT_TRUE(wm::IsActiveWindow(w3.get())); + + container3->RemoveChild(w3.get()); + // Focus moves to a window in the back contaier. + EXPECT_TRUE(wm::IsActiveWindow(w1.get())); +} + +TEST_F(AthenaFocusRuleTest, FocusTravarsalFromEventBlockedContainer) { + ScreenManager::ContainerParams params1("contaier1", kTestZOrderPriority + 1); + params1.can_activate_children = true; + scoped_ptr + container1(ScreenManager::Get()->CreateContainer(params1)); + + ScreenManager::ContainerParams params2("contaier2", kTestZOrderPriority + 2); + params2.can_activate_children = true; + params2.block_events = true; + scoped_ptr + container2(ScreenManager::Get()->CreateContainer(params2)); + + scoped_ptr w1(CreateWindow( + container1.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + scoped_ptr w2(CreateWindow( + container2.get(), nullptr, gfx::Rect(0, 0, 100, 100))); + + wm::ActivateWindow(w2.get()); + EXPECT_TRUE(wm::IsActiveWindow(w2.get())); + + // Confirm that w1 can't get the focus. + wm::ActivateWindow(w1.get()); + EXPECT_FALSE(wm::IsActiveWindow(w1.get())); + EXPECT_TRUE(wm::IsActiveWindow(w2.get())); + + container2->Hide(); + w2.reset(); + container2.reset(); + + EXPECT_TRUE(wm::IsActiveWindow(w1.get())); +} + namespace { class ScreenManagerTargeterTest -- cgit v1.2.3