summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-08 18:45:25 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-08 18:45:25 +0000
commit6b87f5d78bda81eb6b8804bd148b0d448dd79a6e (patch)
treef43bb56cf351630601c27c2c01a8a38602651ad9 /ash
parenta5c01bea0d4666bd67464619555dffea28b6e694 (diff)
downloadchromium_src-6b87f5d78bda81eb6b8804bd148b0d448dd79a6e.zip
chromium_src-6b87f5d78bda81eb6b8804bd148b0d448dd79a6e.tar.gz
chromium_src-6b87f5d78bda81eb6b8804bd148b0d448dd79a6e.tar.bz2
Transform parents of modal windows with modal window. Hide non overview windows.
BUG=304289 TEST=WindowSelectorTest.NonActivatableWindowsHidden, WindowSelectorTest.ModalChild, WindowSelectorTest.ClickModalWindowParent TEST=Open a browser, press Ctrl+O to open a modal window. Enter overview. Browser should be transformed with modal file open window. Clicking on browser should activate file open window. Review URL: https://codereview.chromium.org/26487003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227555 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.cc97
-rw-r--r--ash/wm/overview/scoped_transform_overview_window.h3
-rw-r--r--ash/wm/overview/window_overview.cc29
-rw-r--r--ash/wm/overview/window_overview.h9
-rw-r--r--ash/wm/overview/window_selector_panels.cc9
-rw-r--r--ash/wm/overview/window_selector_unittest.cc54
-rw-r--r--ash/wm/overview/window_selector_window.cc2
7 files changed, 155 insertions, 48 deletions
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc
index 0318e47..d51a56e 100644
--- a/ash/wm/overview/scoped_transform_overview_window.cc
+++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -4,6 +4,7 @@
#include "ash/wm/overview/scoped_transform_overview_window.h"
+#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/wm/window_state.h"
#include "ui/aura/client/aura_constants.h"
@@ -161,6 +162,40 @@ void SetTransformOnWindow(aura::Window* window,
}
}
+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;
+}
+
+void SetTransformOnWindowAndAllTransientChildren(
+ aura::Window* window,
+ const gfx::Transform& transform,
+ bool animate) {
+ SetTransformOnWindow(window, transform, animate);
+
+ aura::Window::Windows transient_children = window->transient_children();
+ for (aura::Window::Windows::iterator iter = transient_children.begin();
+ iter != transient_children.end(); ++iter) {
+ aura::Window* transient_child = *iter;
+ 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));
+ SetTransformOnWindow(transient_child, transient_window_transform, animate);
+ }
+}
+
+aura::Window* GetModalTransientParent(aura::Window* window) {
+ if (window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW)
+ return window->transient_parent();
+ return NULL;
+}
+
} // namespace
const int ScopedTransformOverviewWindow::kTransitionMilliseconds = 100;
@@ -215,10 +250,27 @@ ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
}
}
-bool ScopedTransformOverviewWindow::Contains(const aura::Window* window) const {
- if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
+bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
+ if (window_copy_ && window_copy_->GetNativeWindow()->Contains(target))
return true;
- return window_->Contains(window);
+ aura::Window* window = window_;
+ while (window) {
+ if (window->Contains(target))
+ return true;
+ window = GetModalTransientParent(window);
+ }
+ return false;
+}
+
+gfx::Rect ScopedTransformOverviewWindow::GetBoundsInScreen() const {
+ gfx::Rect bounds;
+ aura::Window* window = window_;
+ while (window) {
+ bounds.Union(ScreenAsh::ConvertRectToScreen(window->parent(),
+ window->GetTargetBounds()));
+ window = GetModalTransientParent(window);
+ }
+ return bounds;
}
void ScopedTransformOverviewWindow::RestoreWindow() {
@@ -277,6 +329,9 @@ void ScopedTransformOverviewWindow::SetTransform(
if (root_window != window_->GetRootWindow() && !window_copy_) {
DCHECK(!layer_);
+ // 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.
layer_ = views::corewm::RecreateWindowLayers(window_, true);
window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
}
@@ -286,28 +341,24 @@ void ScopedTransformOverviewWindow::SetTransform(
void ScopedTransformOverviewWindow::SetTransformOnWindowAndTransientChildren(
const gfx::Transform& transform,
bool animate) {
- SetTransformOnWindow(window_, transform, animate);
-
+ gfx::Point origin(GetBoundsInScreen().origin());
+ aura::Window* window = window_;
+ while (window->transient_parent())
+ window = window->transient_parent();
if (window_copy_) {
- SetTransformOnWindow(window_copy_->GetNativeWindow(), transform, animate);
- }
-
- // TODO(flackr): Create copies of the transient children windows as well.
- // Currently they will only be visible on the window's initial display.
- aura::Window::Windows transient_children = window_->transient_children();
- for (aura::Window::Windows::iterator iter = transient_children.begin();
- iter != transient_children.end(); ++iter) {
- aura::Window* transient_child = *iter;
- gfx::Transform transient_window_transform;
- gfx::Rect window_bounds = window_->bounds();
- gfx::Rect child_bounds = transient_child->bounds();
- transient_window_transform.Translate(window_bounds.x() - child_bounds.x(),
- window_bounds.y() - child_bounds.y());
- transient_window_transform.PreconcatTransform(transform);
- transient_window_transform.Translate(child_bounds.x() - window_bounds.x(),
- child_bounds.y() - window_bounds.y());
- SetTransformOnWindow(transient_child, transient_window_transform, animate);
+ SetTransformOnWindow(
+ window_copy_->GetNativeWindow(),
+ TranslateTransformOrigin(ScreenAsh::ConvertRectToScreen(
+ window_->parent(), window_->GetTargetBounds()).origin() - origin,
+ transform),
+ animate);
}
+ SetTransformOnWindowAndAllTransientChildren(
+ window,
+ TranslateTransformOrigin(ScreenAsh::ConvertRectToScreen(
+ window->parent(), window->GetTargetBounds()).origin() - origin,
+ transform),
+ animate);
}
void ScopedTransformOverviewWindow::PrepareForOverview() {
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h
index c9b7569..af656c1 100644
--- a/ash/wm/overview/scoped_transform_overview_window.h
+++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -46,6 +46,9 @@ class ScopedTransformOverviewWindow {
// used to determine if an event targetted this window.
bool Contains(const aura::Window* target) const;
+ // Returns the original bounds of all transformed windows.
+ gfx::Rect GetBoundsInScreen() const;
+
// Restores the window if it was minimized.
void RestoreWindow();
diff --git a/ash/wm/overview/window_overview.cc b/ash/wm/overview/window_overview.cc
index f3a928d..5574416 100644
--- a/ash/wm/overview/window_overview.cc
+++ b/ash/wm/overview/window_overview.cc
@@ -123,14 +123,25 @@ WindowOverview::WindowOverview(WindowSelector* window_selector,
// as suggested there.
cursor_client_->LockCursor();
}
- ash::Shell::GetInstance()->AddPreTargetHandler(this);
+ ash::Shell::GetInstance()->PrependPreTargetHandler(this);
Shell* shell = Shell::GetInstance();
shell->delegate()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
- SetOpacityOfNonOverviewWindows(0);
+ HideAndTrackNonOverviewWindows();
}
WindowOverview::~WindowOverview() {
- SetOpacityOfNonOverviewWindows(1);
+ const aura::WindowTracker::Windows hidden_windows = hidden_windows_.windows();
+ for (aura::WindowTracker::Windows::const_iterator iter =
+ hidden_windows.begin(); iter != hidden_windows.end(); ++iter) {
+ ui::ScopedLayerAnimationSettings settings(
+ (*iter)->layer()->GetAnimator());
+ settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
+ ScopedTransformOverviewWindow::kTransitionMilliseconds));
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ (*iter)->Show();
+ (*iter)->layer()->SetOpacity(1);
+ }
if (cursor_client_)
cursor_client_->UnlockCursor();
ash::Shell::GetInstance()->RemovePreTargetHandler(this);
@@ -284,7 +295,7 @@ aura::Window* WindowOverview::GetTargetedWindow(aura::Window* window) {
return NULL;
}
-void WindowOverview::SetOpacityOfNonOverviewWindows(float opacity) {
+void WindowOverview::HideAndTrackNonOverviewWindows() {
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
for (Shell::RootWindowList::const_iterator root_iter = root_windows.begin();
root_iter != root_windows.end(); ++root_iter) {
@@ -294,8 +305,6 @@ void WindowOverview::SetOpacityOfNonOverviewWindows(float opacity) {
for (aura::Window::Windows::const_iterator iter =
container->children().begin(); iter != container->children().end();
++iter) {
- // Skip windows in overview and those which are not visible. A layer
- // opacity of 0 is still considered visible.
if (GetTargetedWindow(*iter) || !(*iter)->IsVisible())
continue;
ui::ScopedLayerAnimationSettings settings(
@@ -304,11 +313,9 @@ void WindowOverview::SetOpacityOfNonOverviewWindows(float opacity) {
ScopedTransformOverviewWindow::kTransitionMilliseconds));
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- // Changing the visibility (i.e. calling Window::Hide) would also hide
- // modal child windows, however the modal child window being activatable
- // is in the overview and should be visible. Instead, use opacity to
- // fade out non-activatable windows during overview.
- (*iter)->layer()->SetOpacity(opacity);
+ (*iter)->Hide();
+ (*iter)->layer()->SetOpacity(0);
+ hidden_windows_.Add(*iter);
}
}
}
diff --git a/ash/wm/overview/window_overview.h b/ash/wm/overview/window_overview.h
index 8fbaed7..595cee1 100644
--- a/ash/wm/overview/window_overview.h
+++ b/ash/wm/overview/window_overview.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/time/time.h"
+#include "ui/aura/window_tracker.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/rect.h"
@@ -76,8 +77,8 @@ class WindowOverview : public ui::EventHandler {
// no overview window was found for |window|.
aura::Window* GetTargetedWindow(aura::Window* window);
- // Sets the opacity of all windows not in the overview to |opacity|.
- void SetOpacityOfNonOverviewWindows(float opacity);
+ // Hide and track all hidden windows not in overview.
+ void HideAndTrackNonOverviewWindows();
// Position all of the windows based on the current selection mode.
void PositionWindows();
@@ -119,6 +120,10 @@ class WindowOverview : public ui::EventHandler {
// The cursor client used to lock the current cursor during overview.
aura::client::CursorClient* cursor_client_;
+ // Tracks windows which were hidden because they were not part of the
+ // overview.
+ aura::WindowTracker hidden_windows_;
+
DISALLOW_COPY_AND_ASSIGN(WindowOverview);
};
diff --git a/ash/wm/overview/window_selector_panels.cc b/ash/wm/overview/window_selector_panels.cc
index a028de0..52642bf 100644
--- a/ash/wm/overview/window_selector_panels.cc
+++ b/ash/wm/overview/window_selector_panels.cc
@@ -152,10 +152,7 @@ void WindowSelectorPanels::SetItemBounds(aura::RootWindow* root_window,
gfx::Rect bounding_rect;
for (WindowList::iterator iter = transform_windows_.begin();
iter != transform_windows_.end(); ++iter) {
- aura::Window* panel = (*iter)->window();
- gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(
- panel->parent(), panel->GetTargetBounds());
- bounding_rect.Union(bounds);
+ bounding_rect.Union((*iter)->GetBoundsInScreen());
}
gfx::Transform bounding_transform =
ScopedTransformOverviewWindow::GetTransformForRectPreservingAspectRatio(
@@ -163,9 +160,7 @@ void WindowSelectorPanels::SetItemBounds(aura::RootWindow* root_window,
for (WindowList::iterator iter = transform_windows_.begin();
iter != transform_windows_.end(); ++iter) {
gfx::Transform transform;
- aura::Window* panel = (*iter)->window();
- gfx::Rect bounds = ScreenAsh::ConvertRectToScreen(
- panel->parent(), panel->GetTargetBounds());
+ gfx::Rect bounds = (*iter)->GetBoundsInScreen();
transform.Translate(bounding_rect.x() - bounds.x(),
bounding_rect.y() - bounds.y());
transform.PreconcatTransform(bounding_transform);
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 1b9f971..eda6a8a 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -510,12 +510,58 @@ TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) {
scoped_ptr<aura::Window> window1(CreateWindow(bounds));
scoped_ptr<aura::Window> window2(CreateWindow(bounds));
scoped_ptr<aura::Window> non_activatable_window(
- CreateNonActivatableWindow(bounds));
- EXPECT_EQ(1.0f, non_activatable_window->layer()->GetTargetOpacity());
+ CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds()));
+ EXPECT_TRUE(non_activatable_window->IsVisible());
ToggleOverview();
- EXPECT_EQ(0.0f, non_activatable_window->layer()->GetTargetOpacity());
+ EXPECT_FALSE(non_activatable_window->IsVisible());
ToggleOverview();
- EXPECT_EQ(1.0f, non_activatable_window->layer()->GetTargetOpacity());
+ EXPECT_TRUE(non_activatable_window->IsVisible());
+
+ // Test that a window behind the fullscreen non-activatable window can be
+ // clicked.
+ non_activatable_window->parent()->StackChildAtTop(
+ non_activatable_window.get());
+ ToggleOverview();
+ ClickWindow(window1.get());
+ EXPECT_FALSE(IsSelecting());
+ EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+}
+
+// Tests that windows with modal child windows are transformed with the modal
+// child even though not activatable themselves.
+TEST_F(WindowSelectorTest, ModalChild) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> child1(CreateWindow(bounds));
+ child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
+ window1->AddTransientChild(child1.get());
+ EXPECT_EQ(window1->parent(), child1->parent());
+ ToggleOverview();
+ EXPECT_TRUE(window1->IsVisible());
+ EXPECT_TRUE(child1->IsVisible());
+ EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
+ ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
+ ToggleOverview();
+}
+
+// Tests that clicking a modal window's parent activates the modal window in
+// overview.
+TEST_F(WindowSelectorTest, ClickModalWindowParent) {
+ scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
+ scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
+ child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
+ window1->AddTransientChild(child1.get());
+ EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
+ EXPECT_EQ(window1->parent(), child1->parent());
+ ToggleOverview();
+ // Given that their relative positions are preserved, the windows should still
+ // not overlap.
+ EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
+ ClickWindow(window1.get());
+ EXPECT_FALSE(IsSelecting());
+
+ // Clicking on window1 should activate child1.
+ EXPECT_TRUE(wm::IsActiveWindow(child1.get()));
}
// Tests that windows remain on the display they are currently on in overview
diff --git a/ash/wm/overview/window_selector_window.cc b/ash/wm/overview/window_selector_window.cc
index 1c1bfb0..d257d29 100644
--- a/ash/wm/overview/window_selector_window.cc
+++ b/ash/wm/overview/window_selector_window.cc
@@ -52,7 +52,7 @@ void WindowSelectorWindow::SetItemBounds(aura::RootWindow* root_window,
gfx::Rect bounding_rect = transform_window_.window()->GetBoundsInScreen();
transform_window_.SetTransform(root_window,
ScopedTransformOverviewWindow::GetTransformForRectPreservingAspectRatio(
- transform_window_.window()->GetBoundsInScreen(), target_bounds),
+ transform_window_.GetBoundsInScreen(), target_bounds),
animate);
}