diff options
author | oshima <oshima@chromium.org> | 2014-10-09 09:15:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-09 16:16:12 +0000 |
commit | bb11c71d45fea38bab72ca28a6c44b19c7d9f564 (patch) | |
tree | ca47d3f94aa70299b3d36fd94165adc5d7462c86 /athena | |
parent | 17bfcf19eb55145a7886d4f9e52196b06f5d5100 (diff) | |
download | chromium_src-bb11c71d45fea38bab72ca28a6c44b19c7d9f564.zip chromium_src-bb11c71d45fea38bab72ca28a6c44b19c7d9f564.tar.gz chromium_src-bb11c71d45fea38bab72ca28a6c44b19c7d9f564.tar.bz2 |
Handle transient children as a part of transient parent
Exclude transient children from window list.
Introduced TransientGroupSetter to set the window property to all transient children.
This CL depends on https://codereview.chromium.org/628413002/.
BUG=410499
TEST=Updated WindowListProviderImplTest.
Manual tests for animations: go to chrome://extensions, enable dev mode, and open file dialog. Go to overview mode, scroll, delete, select activity with file dialog.
Review URL: https://codereview.chromium.org/633623002
Cr-Commit-Position: refs/heads/master@{#298890}
Diffstat (limited to 'athena')
-rw-r--r-- | athena/wm/public/window_list_provider.h | 4 | ||||
-rw-r--r-- | athena/wm/test/window_manager_impl_test_api.cc | 1 | ||||
-rw-r--r-- | athena/wm/window_list_provider_impl.cc | 62 | ||||
-rw-r--r-- | athena/wm/window_list_provider_impl.h | 8 | ||||
-rw-r--r-- | athena/wm/window_list_provider_impl_unittest.cc | 165 | ||||
-rw-r--r-- | athena/wm/window_manager_impl.cc | 28 | ||||
-rw-r--r-- | athena/wm/window_manager_impl.h | 4 | ||||
-rw-r--r-- | athena/wm/window_overview_mode.cc | 209 |
8 files changed, 332 insertions, 149 deletions
diff --git a/athena/wm/public/window_list_provider.h b/athena/wm/public/window_list_provider.h index 8790b1f..69560ea 100644 --- a/athena/wm/public/window_list_provider.h +++ b/athena/wm/public/window_list_provider.h @@ -29,10 +29,6 @@ class ATHENA_EXPORT WindowListProvider { // Returns true if the |window| is part of the list. virtual bool IsWindowInList(aura::Window* window) const = 0; - // Returns true if the given window is a window which can be handled by the - // WindowListProvider. - virtual bool IsValidWindow(aura::Window* window) const = 0; - // Stacks a given |window| in direct front of a |reference_window|. // Note: The |window| and |reference_window| has to be in the list already. virtual void StackWindowFrontOf(aura::Window* window, diff --git a/athena/wm/test/window_manager_impl_test_api.cc b/athena/wm/test/window_manager_impl_test_api.cc index bf346f9..ef7a2cf 100644 --- a/athena/wm/test/window_manager_impl_test_api.cc +++ b/athena/wm/test/window_manager_impl_test_api.cc @@ -4,6 +4,7 @@ #include "athena/wm/test/window_manager_impl_test_api.h" +#include "athena/wm/window_list_provider_impl.h" #include "athena/wm/window_manager_impl.h" namespace athena { diff --git a/athena/wm/window_list_provider_impl.cc b/athena/wm/window_list_provider_impl.cc index f684c41..a6aa781 100644 --- a/athena/wm/window_list_provider_impl.cc +++ b/athena/wm/window_list_provider_impl.cc @@ -6,41 +6,50 @@ #include <algorithm> +#include "athena/athena_export.h" #include "athena/wm/public/window_list_provider_observer.h" #include "ui/aura/window.h" +#include "ui/aura/window_property.h" +#include "ui/wm/core/transient_window_manager.h" +#include "ui/wm/core/window_util.h" + +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(ATHENA_EXPORT, bool); namespace athena { +namespace { + +// Used to keep track of which window should be managed. This is necessary +// as the necessary informatino used in IsValidWindow (transient parent +// for example) may not available during destruction. +DEFINE_WINDOW_PROPERTY_KEY(bool, kManagedKey, false); + +} // namespace WindowListProviderImpl::WindowListProviderImpl(aura::Window* container) : container_(container) { CHECK(container_); container_->AddObserver(this); RecreateWindowList(); - std::for_each(window_list_.begin(), window_list_.end(), - std::bind2nd(std::mem_fun(&aura::Window::AddObserver), - this)); + for (auto* window : window_list_) + window->AddObserver(this); } WindowListProviderImpl::~WindowListProviderImpl() { // Remove all remaining window observers. - for (aura::Window::Windows::const_iterator iter = window_list_.begin(); - iter != window_list_.end(); - ++iter) { - CHECK(IsValidWindow(*iter)); - (*iter)->RemoveObserver(this); + for (auto* window : window_list_) { + CHECK(window->GetProperty(kManagedKey)); + window->RemoveObserver(this); } container_->RemoveObserver(this); } -void WindowListProviderImpl::RecreateWindowList() { - window_list_.clear(); - const aura::Window::Windows& container_children = container_->children(); - for (aura::Window::Windows::const_iterator iter = container_children.begin(); - iter != container_children.end(); - ++iter) { - if (IsValidWindow(*iter)) - window_list_.push_back(*iter); - } +bool WindowListProviderImpl::IsValidWindow(aura::Window* window) const { + if (wm::GetTransientParent(window)) + return false; + + // TODO(oshima): crbug.com/413912. + return window->type() == ui::wm::WINDOW_TYPE_NORMAL || + window->type() == ui::wm::WINDOW_TYPE_PANEL; } void WindowListProviderImpl::AddObserver(WindowListProviderObserver* observer) { @@ -57,15 +66,10 @@ const aura::Window::Windows& WindowListProviderImpl::GetWindowList() const { } bool WindowListProviderImpl::IsWindowInList(aura::Window* window) const { + // TODO(oshima): Use kManagedKey specify which windows are managed. return window->parent() == container_ && IsValidWindow(window); } -bool WindowListProviderImpl::IsValidWindow(aura::Window* window) const { - // TODO(oshima): crbug.com/413912 - return window->type() == ui::wm::WINDOW_TYPE_NORMAL || - window->type() == ui::wm::WINDOW_TYPE_PANEL; -} - void WindowListProviderImpl::StackWindowFrontOf( aura::Window* window, aura::Window* reference_window) { @@ -84,16 +88,26 @@ void WindowListProviderImpl::StackWindowBehindTo( container_->StackChildBelow(window, reference_window); } +void WindowListProviderImpl::RecreateWindowList() { + window_list_.clear(); + for (auto* window : container_->children()) { + if (window->GetProperty(kManagedKey)) + window_list_.push_back(window); + } +} + void WindowListProviderImpl::OnWindowAdded(aura::Window* window) { if (!IsValidWindow(window) || window->parent() != container_) return; + + window->SetProperty(kManagedKey, true); RecreateWindowList(); DCHECK(IsWindowInList(window)); window->AddObserver(this); } void WindowListProviderImpl::OnWillRemoveWindow(aura::Window* window) { - if (!IsValidWindow(window) || window->parent() != container_) + if (!window->GetProperty(kManagedKey)) return; DCHECK(IsWindowInList(window)); aura::Window::Windows::iterator find = std::find(window_list_.begin(), diff --git a/athena/wm/window_list_provider_impl.h b/athena/wm/window_list_provider_impl.h index a686da2..ae1d956 100644 --- a/athena/wm/window_list_provider_impl.h +++ b/athena/wm/window_list_provider_impl.h @@ -6,6 +6,7 @@ #define ATHENA_WM_WINDOW_LIST_PROVIDER_IMPL_H_ #include "athena/wm/public/window_list_provider.h" +#include "base/gtest_prod_util.h" #include "ui/aura/window_observer.h" namespace athena { @@ -20,20 +21,21 @@ class ATHENA_EXPORT WindowListProviderImpl : public WindowListProvider, explicit WindowListProviderImpl(aura::Window* container); virtual ~WindowListProviderImpl(); - private: - void RecreateWindowList(); + bool IsValidWindow(aura::Window* window) const; // WindowListProvider: virtual void AddObserver(WindowListProviderObserver* observer) override; virtual void RemoveObserver(WindowListProviderObserver* observer) override; virtual const aura::Window::Windows& GetWindowList() const override; virtual bool IsWindowInList(aura::Window* window) const override; - virtual bool IsValidWindow(aura::Window* window) const override; virtual void StackWindowFrontOf(aura::Window* window, aura::Window*reference_window) override; virtual void StackWindowBehindTo(aura::Window* window, aura::Window*reference_window) override; + private: + void RecreateWindowList(); + // aura::WindowObserver: virtual void OnWindowAdded(aura::Window* new_window) override; virtual void OnWillRemoveWindow(aura::Window* old_window) override; diff --git a/athena/wm/window_list_provider_impl_unittest.cc b/athena/wm/window_list_provider_impl_unittest.cc index 3419b2e..5b03d2d 100644 --- a/athena/wm/window_list_provider_impl_unittest.cc +++ b/athena/wm/window_list_provider_impl_unittest.cc @@ -6,10 +6,14 @@ #include <algorithm> +#include "athena/screen/public/screen_manager.h" #include "athena/test/base/athena_test_base.h" #include "athena/wm/public/window_list_provider_observer.h" +#include "athena/wm/public/window_manager.h" +#include "ui/aura/client/window_tree_client.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/wm/core/window_util.h" namespace athena { @@ -21,11 +25,26 @@ bool AreWindowListsEqual(const aura::Window::Windows& one, std::equal(one.begin(), one.end(), two.begin()); } -scoped_ptr<aura::Window> CreateWindow(aura::WindowDelegate* delegate, +scoped_ptr<aura::Window> CreateWindow(aura::Window* parent, + aura::WindowDelegate* delegate, ui::wm::WindowType window_type) { scoped_ptr<aura::Window> window(new aura::Window(delegate)); window->SetType(window_type); window->Init(aura::WINDOW_LAYER_SOLID_COLOR); + if (parent) + parent->AddChild(window.get()); + return window.Pass(); +} + +scoped_ptr<aura::Window> CreateTransientWindow(aura::Window* transient_parent, + aura::WindowDelegate* delegate, + ui::wm::WindowType window_type) { + scoped_ptr<aura::Window> window(new aura::Window(delegate)); + window->SetType(window_type); + window->Init(aura::WINDOW_LAYER_SOLID_COLOR); + wm::AddTransientChild(transient_parent, window.get()); + aura::client::ParentWindowWithContext( + window.get(), ScreenManager::Get()->GetContext(), gfx::Rect()); return window.Pass(); } @@ -94,24 +113,27 @@ typedef test::AthenaTestBase WindowListProviderImplTest; TEST_F(WindowListProviderImplTest, StackingOrder) { aura::test::TestWindowDelegate delegate; scoped_ptr<aura::Window> container(new aura::Window(&delegate)); + scoped_ptr<WindowListProvider> list_provider( + new WindowListProviderImpl(container.get())); + scoped_ptr<aura::Window> first = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> second = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> third = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); - container->AddChild(first.get()); - container->AddChild(second.get()); - container->AddChild(third.get()); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); + + EXPECT_EQ(3u, container->children().size()); + EXPECT_EQ(container->children().size(), + list_provider->GetWindowList().size()); - scoped_ptr<WindowListProvider> list_provider( - new WindowListProviderImpl(container.get())); EXPECT_TRUE(AreWindowListsEqual(container->children(), list_provider->GetWindowList())); container->StackChildAtTop(first.get()); EXPECT_TRUE(AreWindowListsEqual(container->children(), list_provider->GetWindowList())); + EXPECT_EQ(3u, container->children().size()); EXPECT_EQ(first.get(), container->children().back()); } @@ -119,21 +141,17 @@ TEST_F(WindowListProviderImplTest, StackingOrder) { TEST_F(WindowListProviderImplTest, ListContainsOnlyNormalWindows) { aura::test::TestWindowDelegate delegate; scoped_ptr<aura::Window> container(new aura::Window(&delegate)); + scoped_ptr<WindowListProvider> list_provider( + new WindowListProviderImpl(container.get())); + scoped_ptr<aura::Window> first = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> second = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_POPUP); scoped_ptr<aura::Window> third = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> fourth = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU); - container->AddChild(first.get()); - container->AddChild(second.get()); - container->AddChild(third.get()); - container->AddChild(fourth.get()); - - scoped_ptr<WindowListProvider> list_provider( - new WindowListProviderImpl(container.get())); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_MENU); const aura::Window::Windows& list = list_provider->GetWindowList(); EXPECT_EQ(list.end(), std::find(list.begin(), list.end(), second.get())); @@ -146,16 +164,15 @@ TEST_F(WindowListProviderImplTest, ListContainsOnlyNormalWindows) { TEST_F(WindowListProviderImplTest, SimpleChecks) { aura::test::TestWindowDelegate delegate; scoped_ptr<aura::Window> container(new aura::Window(&delegate)); + scoped_ptr<WindowListProviderImpl> list_provider( + new WindowListProviderImpl(container.get())); scoped_ptr<aura::Window> normal_window = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> popup_window = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_POPUP); scoped_ptr<aura::Window> menu_window = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_MENU); - - scoped_ptr<WindowListProvider> list_provider( - new WindowListProviderImpl(container.get())); + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_MENU); // Check which windows are valid and which are not. EXPECT_TRUE(list_provider->IsValidWindow(normal_window.get())); @@ -176,19 +193,18 @@ TEST_F(WindowListProviderImplTest, SimpleChecks) { TEST_F(WindowListProviderImplTest, TestWindowOrderingFunctions) { aura::test::TestWindowDelegate delegate; scoped_ptr<aura::Window> container(new aura::Window(&delegate)); - - scoped_ptr<aura::Window> window1 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); - scoped_ptr<aura::Window> window2 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); - scoped_ptr<aura::Window> window3 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); - scoped_ptr<WindowListProvider> list_provider( new WindowListProviderImpl(container.get())); scoped_ptr<WindowListObserver> observer( new WindowListObserver(list_provider.get())); + scoped_ptr<aura::Window> window1 = + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_NORMAL); + scoped_ptr<aura::Window> window2 = + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_NORMAL); + scoped_ptr<aura::Window> window3 = + CreateWindow(NULL, &delegate, ui::wm::WINDOW_TYPE_NORMAL); + EXPECT_FALSE(list_provider->IsWindowInList(window1.get())); EXPECT_FALSE(list_provider->IsWindowInList(window2.get())); EXPECT_FALSE(list_provider->IsWindowInList(window3.get())); @@ -244,26 +260,20 @@ TEST_F(WindowListProviderImplTest, TestWindowOrderingFunctions) { TEST_F(WindowListProviderImplTest, TestWindowRemovalNotification) { aura::test::TestWindowDelegate delegate; scoped_ptr<aura::Window> container(new aura::Window(&delegate)); + scoped_ptr<WindowListProvider> list_provider( + new WindowListProviderImpl(container.get())); + scoped_ptr<WindowListObserver> observer( + new WindowListObserver(list_provider.get())); scoped_ptr<aura::Window> window1 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> window2 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> window3 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_NORMAL); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); scoped_ptr<aura::Window> window4 = - CreateWindow(&delegate, ui::wm::WINDOW_TYPE_POPUP); + CreateWindow(container.get(), &delegate, ui::wm::WINDOW_TYPE_POPUP); - scoped_ptr<WindowListProvider> list_provider( - new WindowListProviderImpl(container.get())); - scoped_ptr<WindowListObserver> observer( - new WindowListObserver(list_provider.get())); - - // Add the windows. - container->AddChild(window1.get()); - container->AddChild(window2.get()); - container->AddChild(window3.get()); - container->AddChild(window4.get()); // The popup-window (window4) should not be included in the window-list. ASSERT_EQ(3U, list_provider->GetWindowList().size()); EXPECT_EQ(0, observer->window_removal_calls()); @@ -287,4 +297,63 @@ TEST_F(WindowListProviderImplTest, TestWindowRemovalNotification) { EXPECT_EQ(3, observer->window_removal_calls()); } +// Test that transient windows are handled property. +TEST_F(WindowListProviderImplTest, TransientWindows) { + aura::test::TestWindowDelegate delegate; + delegate.set_can_focus(true); + + WindowListProvider* list_provider = + WindowManager::Get()->GetWindowListProvider(); + + scoped_ptr<WindowListObserver> observer( + new WindowListObserver(list_provider)); + scoped_ptr<aura::Window> w1 = CreateTestWindow(&delegate, gfx::Rect()); + w1->Show(); + scoped_ptr<aura::Window> w2 = CreateTestWindow(&delegate, gfx::Rect()); + w2->Show(); + scoped_ptr<aura::Window> t1 = + CreateTransientWindow(w1.get(), &delegate, ui::wm::WINDOW_TYPE_NORMAL); + t1->Show(); + + EXPECT_EQ(2u, list_provider->GetWindowList().size()); + + // Activation should honor transient relations. + wm::ActivateWindow(w2.get()); + EXPECT_EQ(w1.get(), list_provider->GetWindowList()[0]); + EXPECT_EQ(w2.get(), list_provider->GetWindowList()[1]); + + EXPECT_EQ(w1.get(), w1->parent()->children()[0]); + EXPECT_EQ(t1.get(), w1->parent()->children()[1]); + EXPECT_EQ(w2.get(), w1->parent()->children()[2]); + + wm::ActivateWindow(w1.get()); + EXPECT_EQ(w2.get(), w1->parent()->children()[0]); + EXPECT_EQ(w1.get(), w1->parent()->children()[1]); + EXPECT_EQ(t1.get(), w1->parent()->children()[2]); + + // Manual operations should honor transient relations too. + // TODO(oshima): moving the active window back should activate the top window. + list_provider->StackWindowBehindTo(w1.get(), w2.get()); + EXPECT_EQ(w1.get(), w1->parent()->children()[0]); + EXPECT_EQ(t1.get(), w1->parent()->children()[1]); + EXPECT_EQ(w2.get(), w1->parent()->children()[2]); + + list_provider->StackWindowFrontOf(w1.get(), w2.get()); + EXPECT_EQ(w2.get(), w1->parent()->children()[0]); + EXPECT_EQ(w1.get(), w1->parent()->children()[1]); + EXPECT_EQ(t1.get(), w1->parent()->children()[2]); + + // Transient windows should follow the transient parent's + // visibility. + EXPECT_TRUE(t1->IsVisible()); + w1->Hide(); + EXPECT_FALSE(t1->IsVisible()); + w1->Show(); + EXPECT_TRUE(t1->IsVisible()); + + // Resetting transient window won't notify the observer. + t1.reset(); + EXPECT_EQ(0, observer->window_removal_calls()); +} + } // namespace athena diff --git a/athena/wm/window_manager_impl.cc b/athena/wm/window_manager_impl.cc index 35722c1..92b6dda 100644 --- a/athena/wm/window_manager_impl.cc +++ b/athena/wm/window_manager_impl.cc @@ -23,6 +23,7 @@ #include "ui/gfx/display.h" #include "ui/gfx/screen.h" #include "ui/wm/core/shadow_controller.h" +#include "ui/wm/core/transient_window_manager.h" #include "ui/wm/core/window_util.h" #include "ui/wm/core/wm_state.h" #include "ui/wm/public/activation_client.h" @@ -99,7 +100,14 @@ void AthenaContainerLayoutManager::OnWindowResized() { } void AthenaContainerLayoutManager::OnWindowAddedToLayout(aura::Window* child) { - if (!instance->window_list_provider_->IsWindowInList(child)) + // TODO(oshima): Split view modes needs to take the transient window into + // account. + if (wm::GetTransientParent(child)) { + wm::TransientWindowManager::Get(child) + ->set_parent_controls_visibility(true); + } + + if (!instance->window_list_provider_->IsValidWindow(child)) return; if (instance->split_view_controller_->IsSplitViewModeActive() && @@ -240,10 +248,22 @@ void WindowManagerImpl::SetInOverview(bool active) { void WindowManagerImpl::InstallAccelerators() { const AcceleratorData accelerator_data[] = { - {TRIGGER_ON_PRESS, ui::VKEY_F6, ui::EF_NONE, CMD_TOGGLE_OVERVIEW, + {TRIGGER_ON_PRESS, + ui::VKEY_F6, + ui::EF_NONE, + CMD_TOGGLE_OVERVIEW, + AF_NONE}, + {TRIGGER_ON_PRESS, + ui::VKEY_F6, + ui::EF_CONTROL_DOWN, + CMD_TOGGLE_SPLIT_VIEW, AF_NONE}, - {TRIGGER_ON_PRESS, ui::VKEY_F6, ui::EF_CONTROL_DOWN, - CMD_TOGGLE_SPLIT_VIEW, AF_NONE}, + // Debug + {TRIGGER_ON_PRESS, + ui::VKEY_6, + ui::EF_NONE, + CMD_TOGGLE_OVERVIEW, + AF_NONE | AF_DEBUG}, }; AcceleratorManager::Get()->RegisterAccelerators( accelerator_data, arraysize(accelerator_data), this); diff --git a/athena/wm/window_manager_impl.h b/athena/wm/window_manager_impl.h index 2edd856..b5261f4 100644 --- a/athena/wm/window_manager_impl.h +++ b/athena/wm/window_manager_impl.h @@ -27,7 +27,7 @@ class WindowManagerImplTestApi; class BezelController; class SplitViewController; -class WindowListProvider; +class WindowListProviderImpl; class WindowManagerObserver; class ATHENA_EXPORT WindowManagerImpl : public WindowManager, @@ -86,7 +86,7 @@ class ATHENA_EXPORT WindowManagerImpl : public WindowManager, virtual void OnTitleDragCanceled(aura::Window* window) override; scoped_ptr<aura::Window> container_; - scoped_ptr<WindowListProvider> window_list_provider_; + scoped_ptr<WindowListProviderImpl> window_list_provider_; scoped_ptr<WindowOverviewMode> overview_; scoped_ptr<BezelController> bezel_controller_; scoped_ptr<SplitViewController> split_view_controller_; diff --git a/athena/wm/window_overview_mode.cc b/athena/wm/window_overview_mode.cc index ce67744..0b16b6c 100644 --- a/athena/wm/window_overview_mode.cc +++ b/athena/wm/window_overview_mode.cc @@ -4,8 +4,7 @@ #include "athena/wm/window_overview_mode.h" -#include <algorithm> -#include <functional> +#include <complex> #include <vector> #include "athena/wm/overview_toolbar.h" @@ -13,7 +12,7 @@ #include "athena/wm/public/window_list_provider_observer.h" #include "athena/wm/split_view_controller.h" #include "base/bind.h" -#include "base/macros.h" +#include "base/memory/scoped_vector.h" #include "ui/aura/scoped_window_targeter.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" @@ -31,11 +30,10 @@ #include "ui/wm/core/shadow_types.h" #include "ui/wm/core/window_animations.h" #include "ui/wm/core/window_util.h" +#include "ui/wm/public/activation_client.h" namespace { -const float kOverviewDefaultScale = 0.75f; - struct WindowOverviewState { // The current overview state of the window. 0.f means the window is at the // topmost position. 1.f means the window is at the bottom-most position. @@ -53,14 +51,17 @@ struct WindowOverviewState { } // namespace -DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*) +DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*); DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowOverviewState, kWindowOverviewState, - NULL) + NULL); + namespace athena { namespace { +const float kOverviewDefaultScale = 0.75f; + gfx::Transform GetTransformForSplitWindow(aura::Window* window, float scale) { const float kScrollWindowPositionInOverview = 0.65f; int x_translate = window->bounds().width() * (1 - scale) / 2; @@ -99,14 +100,102 @@ gfx::Transform GetTransformForState(aura::Window* window, return transform; } -// Sets the progress-state for the window in the overview mode. -void SetWindowProgress(aura::Window* window, float progress) { - WindowOverviewState* state = window->GetProperty(kWindowOverviewState); - state->progress = progress; +// A utility class used to set the transform/opacity to the window and +// its transient children. +class TransientGroupSetter { + public: + explicit TransientGroupSetter(aura::Window* window) : window_(window) { + } + ~TransientGroupSetter() {} - gfx::Transform transform = GetTransformForState(window, state); - window->SetTransform(transform); -} + // Aborts all animations including its transient children. + void AbortAllAnimations() { + window_->layer()->GetAnimator()->AbortAllAnimations(); + for (auto* transient_child : wm::GetTransientChildren(window_)) + transient_child->layer()->GetAnimator()->AbortAllAnimations(); + } + + // Applys transform to the window and its transient children. + // Transient children gets a tranfrorm with the offset relateive + // it its transient parent. + void SetTransform(const gfx::Transform& transform) { + window_->SetTransform(transform); + for (auto* transient_child : wm::GetTransientChildren(window_)) { + gfx::Rect window_bounds = window_->bounds(); + gfx::Rect child_bounds = transient_child->bounds(); + gfx::Transform transient_window_transform(TranslateTransformOrigin( + child_bounds.origin() - window_bounds.origin(), transform)); + transient_child->SetTransform(transient_window_transform); + } + } + + // Sets the opacity to the window and its transient children. + void SetOpacity(float opacity) { + window_->layer()->SetOpacity(opacity); + for (auto* transient_child : wm::GetTransientChildren(window_)) { + transient_child->layer()->SetOpacity(opacity); + } + } + + // Apply the transform with the overview scroll |progress|. + void SetWindowProgress(float progress) { + WindowOverviewState* state = window_->GetProperty(kWindowOverviewState); + state->progress = progress; + + SetTransform(GetTransformForState(window_, state)); + } + + private: + static gfx::Transform TranslateTransformOrigin( + const gfx::Vector2d& new_origin, + const gfx::Transform& transform) { + gfx::Transform result; + result.Translate(-new_origin.x(), -new_origin.y()); + result.PreconcatTransform(transform); + result.Translate(new_origin.x(), new_origin.y()); + return result; + } + + aura::Window* window_; + + DISALLOW_COPY_AND_ASSIGN(TransientGroupSetter); +}; + +// TransientGroupSetter with animation. +class AnimateTransientGroupSetter : public TransientGroupSetter { + public: + explicit AnimateTransientGroupSetter(aura::Window* window) + : TransientGroupSetter(window) { + animation_settings_.push_back(CreateScopedLayerAnimationSettings(window)); + for (auto* transient_child : wm::GetTransientChildren(window)) { + animation_settings_.push_back( + CreateScopedLayerAnimationSettings(transient_child)); + } + } + ~AnimateTransientGroupSetter() {} + + ui::ScopedLayerAnimationSettings* GetMainWindowAnimationSettings() { + CHECK(animation_settings_.size()); + return animation_settings_[0]; + } + + private: + static ui::ScopedLayerAnimationSettings* CreateScopedLayerAnimationSettings( + aura::Window* window) { + const int kTransitionMs = 250; + + ui::ScopedLayerAnimationSettings* settings = + new ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()); + settings->SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + settings->SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kTransitionMs)); + return settings; + } + + ScopedVector<ui::ScopedLayerAnimationSettings> animation_settings_; + DISALLOW_COPY_AND_ASSIGN(AnimateTransientGroupSetter); +}; void HideWindowIfNotVisible(aura::Window* window, SplitViewController* split_view_controller) { @@ -115,7 +204,9 @@ void HideWindowIfNotVisible(aura::Window* window, should_hide = window != split_view_controller->left_window() && window != split_view_controller->right_window(); } else { - should_hide = !wm::IsActiveWindow(window); + aura::Window* active = aura::client::GetActivationClient( + window->GetRootWindow())->GetActiveWindow(); + should_hide = active != window && wm::GetTransientParent(active) != window; } if (should_hide) window->Hide(); @@ -126,18 +217,15 @@ void RestoreWindowState(aura::Window* window, SplitViewController* split_view_controller) { window->ClearProperty(kWindowOverviewState); - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); - - settings.AddObserver(new ui::ClosureAnimationObserver( - base::Bind(&HideWindowIfNotVisible, window, split_view_controller))); + AnimateTransientGroupSetter setter(window); - window->SetTransform(gfx::Transform()); + setter.GetMainWindowAnimationSettings()->AddObserver( + new ui::ClosureAnimationObserver( + base::Bind(&HideWindowIfNotVisible, window, split_view_controller))); + setter.SetTransform(gfx::Transform()); // Reset the window opacity in case the user is dragging a window. - window->layer()->SetOpacity(1.0f); + setter.SetOpacity(1.0f); wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); } @@ -156,19 +244,17 @@ void TransformSplitWindowScale(aura::Window* window, float scale) { gfx::Transform transform = window->layer()->GetTargetTransform(); if (transform.Scale2d() == gfx::Vector2dF(scale, scale)) return; - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - window->SetTransform(GetTransformForSplitWindow(window, scale)); + AnimateTransientGroupSetter setter(window); + setter.SetTransform(GetTransformForSplitWindow(window, scale)); } void AnimateWindowTo(aura::Window* animate_window, aura::Window* target_window) { - ui::ScopedLayerAnimationSettings settings( - animate_window->layer()->GetAnimator()); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + AnimateTransientGroupSetter setter(animate_window); + WindowOverviewState* target_state = target_window->GetProperty(kWindowOverviewState); - SetWindowProgress(animate_window, target_state->progress); + setter.SetWindowProgress(target_state->progress); } // Always returns the same target. @@ -231,10 +317,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, window_list_provider_->GetWindowList(); if (windows.empty()) return; - std::for_each(windows.begin(), - windows.end(), - std::bind2nd(std::ptr_fun(&RestoreWindowState), - split_view_controller_)); + for (auto* window : windows) + RestoreWindowState(window, split_view_controller_); } private: @@ -314,20 +398,19 @@ class WindowOverviewModeImpl : public WindowOverviewMode, ++index; } - scoped_refptr<ui::LayerAnimator> animator = - window->layer()->GetAnimator(); + TransientGroupSetter setter(window); // Unset any in-progress animation. - animator->AbortAllAnimations(); + setter.AbortAllAnimations(); + + // Showing transient parent will show the transient children if any. window->Show(); - window->SetTransform(gfx::Transform()); + + setter.SetTransform(gfx::Transform()); // Setup the animation. { - ui::ScopedLayerAnimationSettings settings(animator); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250)); - SetWindowProgress(window, progress); + AnimateTransientGroupSetter setter(window); + setter.SetWindowProgress(progress); } } } @@ -347,7 +430,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, targeter->FindTargetForLocatedEvent(container_, event)); while (target && target->parent() != container_) target = target->parent(); - return target; + aura::Window* transient_parent = wm::GetTransientParent(target); + return transient_parent ? transient_parent : target; } // Scroll the window list by |delta_y| amount. |delta_y| is negative when @@ -369,7 +453,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, // It is possible to scroll |window| up. Scroll it up, and update // |delta_y_p| for the next window. float apply = delta_y_p * state->progress; - SetWindowProgress(window, std::max(0.f, state->progress - apply * 3)); + TransientGroupSetter setter(window); + setter.SetWindowProgress(std::max(0.f, state->progress - apply * 3)); delta_y_p -= apply; } } @@ -385,7 +470,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, if (1.f - state->progress > kEpsilon) { // It is possible to scroll |window| down. Scroll it down, and update // |delta_y_p| for the next window. - SetWindowProgress(window, std::min(1.f, state->progress + delta_y_p)); + TransientGroupSetter setter(window); + setter.SetWindowProgress(std::min(1.f, state->progress + delta_y_p)); delta_y_p /= 2.f; } } @@ -446,7 +532,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, gfx::Transform transform = GetTransformForState(dragged_window_, dragged_state); transform.Translate(-dragged_distance.x(), 0); - dragged_window_->SetTransform(transform); + TransientGroupSetter setter(dragged_window_); + setter.SetTransform(transform); // Update the toolbar. const int kMinDistanceForActionButtons = 20; @@ -488,11 +575,11 @@ class WindowOverviewModeImpl : public WindowOverviewMode, ? 1 : gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity); if (animate_opacity) { - ui::ScopedLayerAnimationSettings settings( - dragged_window_->layer()->GetAnimator()); - dragged_window_->layer()->SetOpacity(opacity); + AnimateTransientGroupSetter setter(dragged_window_); + setter.SetOpacity(opacity); } else { - dragged_window_->layer()->SetOpacity(opacity); + TransientGroupSetter setter(dragged_window_); + setter.SetOpacity(opacity); } if (split_view_controller_->IsSplitViewModeActive()) { @@ -525,9 +612,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode, void CloseDragWindow(const ui::GestureEvent& gesture) { // Animate |dragged_window_| offscreen first, then destroy it. { - wm::ScopedHidingAnimationSettings settings(dragged_window_); - settings.layer_animation_settings()->SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + AnimateTransientGroupSetter setter(dragged_window_); WindowOverviewState* dragged_state = dragged_window_->GetProperty(kWindowOverviewState); @@ -541,8 +626,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, else transform_x = -(transformed_bounds.x() + transformed_bounds.width()); transform.Translate(transform_x / kOverviewDefaultScale, 0); - dragged_window_->SetTransform(transform); - dragged_window_->layer()->SetOpacity(kMinOpacity); + + setter.SetOpacity(kMinOpacity); } delete dragged_window_; dragged_window_ = NULL; @@ -554,13 +639,9 @@ class WindowOverviewModeImpl : public WindowOverviewMode, dragged_window_->GetProperty(kWindowOverviewState); CHECK(dragged_state); - ui::ScopedLayerAnimationSettings settings( - dragged_window_->layer()->GetAnimator()); - settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - dragged_window_->SetTransform( - GetTransformForState(dragged_window_, dragged_state)); - dragged_window_->layer()->SetOpacity(1.f); + AnimateTransientGroupSetter setter(dragged_window_); + setter.SetTransform(GetTransformForState(dragged_window_, dragged_state)); + setter.SetOpacity(1.0f); dragged_window_ = NULL; } |