diff options
author | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-30 00:49:07 +0000 |
---|---|---|
committer | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-30 00:49:07 +0000 |
commit | 18b80e259f94c811d1d7b34cca9271361d61e70e (patch) | |
tree | 701a8fbc51530064c4282843f582fd3ea4573407 /ash/wm | |
parent | 54a1c72a0496c5df102468fc9dfabbc9a349abc5 (diff) | |
download | chromium_src-18b80e259f94c811d1d7b34cca9271361d61e70e.zip chromium_src-18b80e259f94c811d1d7b34cca9271361d61e70e.tar.gz chromium_src-18b80e259f94c811d1d7b34cca9271361d61e70e.tar.bz2 |
Copy window and its transient parents when moving to another display.
BUG=306157
TEST=WindowSelectorTest.CycleMultipleDisplaysCopiesWindows
TEST=Open two browsers on different displays. Press Ctrl+O to show an open file dialog. Then Alt+Tab and hold Alt. The browser and the open file dialog should be visible in the overview on the other display.
Review URL: https://codereview.chromium.org/41073006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231691 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
-rw-r--r-- | ash/wm/overview/scoped_transform_overview_window.cc | 69 | ||||
-rw-r--r-- | ash/wm/overview/scoped_transform_overview_window.h | 11 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_unittest.cc | 104 |
3 files changed, 157 insertions, 27 deletions
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc index a9322c0..dc82e6e 100644 --- a/ash/wm/overview/scoped_transform_overview_window.cc +++ b/ash/wm/overview/scoped_transform_overview_window.cc @@ -98,10 +98,6 @@ ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() { if (window_) { WindowSelectorAnimationSettings animation_settings(window_); gfx::Transform transform; - // If the initial window wasn't destroyed and we have copied the window - // layer, the copy needs to be animated out. - // CleanupWidgetAfterAnimationObserver will destroy the widget and - // layer after the animation is complete. SetTransformOnWindowAndTransientChildren(original_transform_, true); if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) != ui::SHOW_STATE_MINIMIZED) { @@ -121,8 +117,11 @@ ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() { } bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const { - if (window_copy_ && window_copy_->GetWindow()->Contains(target)) - return true; + for (ScopedVector<ScopedWindowCopy>::const_iterator iter = + window_copies_.begin(); iter != window_copies_.end(); ++iter) { + if ((*iter)->GetWindow()->Contains(target)) + return true; + } aura::Window* window = window_; while (window) { if (window->Contains(target)) @@ -192,25 +191,45 @@ void ScopedTransformOverviewWindow::SetTransform( bool animate) { DCHECK(overview_started_); - // If the window bounds have changed and a copy of the window is being - // shown on another display, forcibly recreate the copy. - if (window_copy_ && window_copy_->GetWindow()->GetBoundsInScreen() != - window_->GetBoundsInScreen()) { - DCHECK_NE(window_->GetRootWindow(), root_window); - // TODO(flackr): If only the position changed and not the size, update the - // existing window_copy_'s position and continue to use it. - window_copy_.reset(); - } - - if (root_window != window_->GetRootWindow() && !window_copy_) { - // TODO(flackr): Create copies of the transient children and transient - // parent windows as well. Currently they will only be visible on the - // window's initial display. - window_copy_.reset(new ScopedWindowCopy(root_window, window_)); + if (root_window != window_->GetRootWindow()) { + if (!window_copies_.empty()) { + bool bounds_or_hierarchy_changed = false; + aura::Window* window = window_; + for (ScopedVector<ScopedWindowCopy>::reverse_iterator iter = + window_copies_.rbegin(); + !bounds_or_hierarchy_changed && iter != window_copies_.rend(); + ++iter, window = GetModalTransientParent(window)) { + if (!window) { + bounds_or_hierarchy_changed = true; + } else if ((*iter)->GetWindow()->GetBoundsInScreen() != + window->GetBoundsInScreen()) { + bounds_or_hierarchy_changed = true; + } + } + // Clearing the window copies array will force it to be recreated. + // TODO(flackr): If only the position changed and not the size, + // update the existing window copy's position and continue to use it. + if (bounds_or_hierarchy_changed) + window_copies_.clear(); + } + if (window_copies_.empty()) { + // TODO(flackr): Create copies of the transient children windows as well. + // Currently they will only be visible on the window's initial display. + CopyWindowAndTransientParents(root_window, window_); + } } SetTransformOnWindowAndTransientChildren(transform, animate); } +void ScopedTransformOverviewWindow::CopyWindowAndTransientParents( + aura::Window* target_root, + aura::Window* window) { + aura::Window* modal_parent = GetModalTransientParent(window); + if (modal_parent) + CopyWindowAndTransientParents(target_root, modal_parent); + window_copies_.push_back(new ScopedWindowCopy(target_root, window)); +} + void ScopedTransformOverviewWindow::SetTransformOnWindowAndTransientChildren( const gfx::Transform& transform, bool animate) { @@ -218,11 +237,13 @@ void ScopedTransformOverviewWindow::SetTransformOnWindowAndTransientChildren( aura::Window* window = window_; while (window->transient_parent()) window = window->transient_parent(); - if (window_copy_) { + for (ScopedVector<ScopedWindowCopy>::const_iterator iter = + window_copies_.begin(); iter != window_copies_.end(); ++iter) { SetTransformOnWindow( - window_copy_->GetWindow(), + (*iter)->GetWindow(), TranslateTransformOrigin(ScreenAsh::ConvertRectToScreen( - window_->parent(), window_->GetTargetBounds()).origin() - origin, + (*iter)->GetWindow()->parent(), + (*iter)->GetWindow()->GetTargetBounds()).origin() - origin, transform), animate); } diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h index 0ff00de..2bc1b0f 100644 --- a/ash/wm/overview/scoped_transform_overview_window.h +++ b/ash/wm/overview/scoped_transform_overview_window.h @@ -6,7 +6,7 @@ #define ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_ #include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "ui/gfx/rect.h" #include "ui/gfx/transform.h" @@ -80,6 +80,11 @@ class ScopedTransformOverviewWindow { aura::Window* window() const { return window_; } private: + // Creates copies of |window| and all of its modal transient parents on the + // root window |target_root|. + void CopyWindowAndTransientParents(aura::Window* target_root, + aura::Window* window); + // Applies the |transform| to the overview window and all of its transient // children using animations. If |animate| the transform is animated in, // otherwise it is applied immediately. @@ -89,8 +94,8 @@ class ScopedTransformOverviewWindow { // A weak pointer to the real window in the overview. aura::Window* window_; - // A copy of the window used to transition the window to another root. - scoped_ptr<ScopedWindowCopy> window_copy_; + // Copies of the window and transient parents for a different root window. + ScopedVector<ScopedWindowCopy> window_copies_; // If true, the window was minimized and should be restored if the window // was not selected. diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index eff4ace..6ee7c3b 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc @@ -61,6 +61,41 @@ bool IsWindowAbove(aura::Window* w1, aura::Window* w2) { return false; } +aura::Window* GetWindowByName(aura::Window* container, + const std::string& name) { + aura::Window* window = NULL; + for (aura::Window::Windows::const_iterator iter = + container->children().begin(); iter != container->children().end(); + ++iter) { + if ((*iter)->name() == name) { + // The name should be unique. + DCHECK(!window); + window = *iter; + } + } + return window; +} + +// Returns the copy of |window| created for overview. It is found using the +// window name which should be the same as the source window's name with a +// special suffix, and in the same container as the source window. +aura::Window* GetCopyWindow(aura::Window* window) { + aura::Window* copy_window = NULL; + std::string copy_name = window->name() + " (Copy)"; + std::vector<aura::Window*> containers( + Shell::GetContainersFromAllRootWindows(window->parent()->id(), NULL)); + for (std::vector<aura::Window*>::iterator iter = containers.begin(); + iter != containers.end(); ++iter) { + aura::Window* found = GetWindowByName(*iter, copy_name); + if (found) { + // There should only be one copy window. + DCHECK(!copy_window); + copy_window = found; + } + } + return copy_window; +} + } // namespace class WindowSelectorTest : public test::AshTestBase { @@ -735,6 +770,75 @@ TEST_F(WindowSelectorTest, CycleOverviewUsesCurrentDisplay) { ToEnclosingRect(GetTransformedTargetBounds(window1.get())))); EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( ToEnclosingRect(GetTransformedTargetBounds(window2.get())))); + StopCycling(); +} + +// Verifies that the windows being shown on another display are copied. +TEST_F(WindowSelectorTest, CycleMultipleDisplaysCopiesWindows) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("400x400,400x400"); + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + + gfx::Rect root1_rect(0, 0, 100, 100); + gfx::Rect root2_rect(450, 0, 100, 100); + scoped_ptr<aura::Window> unmoved1(CreateWindow(root2_rect)); + scoped_ptr<aura::Window> unmoved2(CreateWindow(root2_rect)); + scoped_ptr<aura::Window> moved1_trans_parent(CreateWindow(root1_rect)); + scoped_ptr<aura::Window> moved1(CreateWindow(root1_rect)); + unmoved1->SetName("unmoved1"); + unmoved2->SetName("unmoved2"); + moved1->SetName("moved1"); + moved1->SetProperty(aura::client::kModalKey, + ui::MODAL_TYPE_WINDOW); + moved1_trans_parent->AddTransientChild(moved1.get()); + moved1_trans_parent->SetName("moved1_trans_parent"); + + EXPECT_EQ(root_windows[0], moved1->GetRootWindow()); + EXPECT_EQ(root_windows[0], moved1_trans_parent->GetRootWindow()); + EXPECT_EQ(root_windows[1], unmoved1->GetRootWindow()); + EXPECT_EQ(root_windows[1], unmoved2->GetRootWindow()); + wm::ActivateWindow(unmoved2.get()); + wm::ActivateWindow(unmoved1.get()); + + Cycle(WindowSelector::FORWARD); + FireOverviewStartTimer(); + + // All windows are moved to second root window. + EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( + ToEnclosingRect(GetTransformedTargetBounds(unmoved1.get())))); + EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( + ToEnclosingRect(GetTransformedTargetBounds(unmoved2.get())))); + EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( + ToEnclosingRect(GetTransformedTargetBounds(moved1.get())))); + EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains( + ToEnclosingRect(GetTransformedTargetBounds(moved1_trans_parent.get())))); + + // unmoved1 and unmoved2 were already on the correct display and should not + // have been copied. + EXPECT_TRUE(!GetCopyWindow(unmoved1.get())); + EXPECT_TRUE(!GetCopyWindow(unmoved2.get())); + + // moved1 and its transient parent moved1_trans_parent should have also been + // copied for displaying on root_windows[1]. + aura::Window* copy1 = GetCopyWindow(moved1.get()); + aura::Window* copy1_trans_parent = GetCopyWindow(moved1_trans_parent.get()); + ASSERT_FALSE(!copy1); + ASSERT_FALSE(!copy1_trans_parent); + + // Verify that the bounds and transform of the copy match the original window + // but that it is on the other root window. + EXPECT_EQ(root_windows[1], copy1->GetRootWindow()); + EXPECT_EQ(moved1->GetBoundsInScreen(), copy1->GetBoundsInScreen()); + EXPECT_EQ(moved1->layer()->GetTargetTransform(), + copy1->layer()->GetTargetTransform()); + StopCycling(); + + // After cycling the copy windows should have been destroyed. + RunAllPendingInMessageLoop(); + EXPECT_TRUE(!GetCopyWindow(moved1.get())); + EXPECT_TRUE(!GetCopyWindow(moved1_trans_parent.get())); } // Tests that beginning to cycle from overview mode moves windows to the |