summaryrefslogtreecommitdiffstats
path: root/ash/wm
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-30 00:49:07 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-30 00:49:07 +0000
commit18b80e259f94c811d1d7b34cca9271361d61e70e (patch)
tree701a8fbc51530064c4282843f582fd3ea4573407 /ash/wm
parent54a1c72a0496c5df102468fc9dfabbc9a349abc5 (diff)
downloadchromium_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.cc69
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.h11
-rw-r--r--ash/wm/overview/window_selector_unittest.cc104
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