Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / overview / scoped_transform_overview_window.cc
blob4e334d797f9628b6af1154cba7602fb287d7b6a3
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/overview/scoped_transform_overview_window.h"
7 #include "ash/screen_util.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/wm/overview/scoped_window_copy.h"
10 #include "ash/wm/overview/window_selector_item.h"
11 #include "ash/wm/window_state.h"
12 #include "ash/wm/window_util.h"
13 #include "ui/aura/client/aura_constants.h"
14 #include "ui/aura/client/screen_position_client.h"
15 #include "ui/aura/window.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h"
17 #include "ui/gfx/animation/tween.h"
18 #include "ui/views/widget/widget.h"
19 #include "ui/wm/core/window_animations.h"
20 #include "ui/wm/core/window_util.h"
22 namespace ash {
24 namespace {
26 // The animation settings used for window selector animations.
27 class WindowSelectorAnimationSettings
28 : public ui::ScopedLayerAnimationSettings {
29 public:
30 WindowSelectorAnimationSettings(aura::Window* window) :
31 ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
32 SetPreemptionStrategy(
33 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
34 SetTransitionDuration(base::TimeDelta::FromMilliseconds(
35 ScopedTransformOverviewWindow::kTransitionMilliseconds));
36 SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
39 virtual ~WindowSelectorAnimationSettings() {
43 void SetTransformOnWindow(aura::Window* window,
44 const gfx::Transform& transform,
45 bool animate) {
46 if (animate) {
47 WindowSelectorAnimationSettings animation_settings(window);
48 window->SetTransform(transform);
49 } else {
50 window->SetTransform(transform);
54 gfx::Transform TranslateTransformOrigin(const gfx::Vector2d& new_origin,
55 const gfx::Transform& transform) {
56 gfx::Transform result;
57 result.Translate(-new_origin.x(), -new_origin.y());
58 result.PreconcatTransform(transform);
59 result.Translate(new_origin.x(), new_origin.y());
60 return result;
63 void SetTransformOnWindowAndAllTransientChildren(
64 aura::Window* window,
65 const gfx::Transform& transform,
66 bool animate) {
67 SetTransformOnWindow(window, transform, animate);
69 aura::Window::Windows transient_children =
70 ::wm::GetTransientChildren(window);
71 for (aura::Window::Windows::iterator iter = transient_children.begin();
72 iter != transient_children.end(); ++iter) {
73 aura::Window* transient_child = *iter;
74 gfx::Rect window_bounds = window->bounds();
75 gfx::Rect child_bounds = transient_child->bounds();
76 gfx::Transform transient_window_transform(
77 TranslateTransformOrigin(child_bounds.origin() - window_bounds.origin(),
78 transform));
79 SetTransformOnWindow(transient_child, transient_window_transform, animate);
83 aura::Window* GetModalTransientParent(aura::Window* window) {
84 if (window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW)
85 return ::wm::GetTransientParent(window);
86 return NULL;
89 } // namespace
91 const int ScopedTransformOverviewWindow::kTransitionMilliseconds = 200;
93 ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
94 aura::Window* window)
95 : window_(window),
96 minimized_(window->GetProperty(aura::client::kShowStateKey) ==
97 ui::SHOW_STATE_MINIMIZED),
98 ignored_by_shelf_(ash::wm::GetWindowState(window)->ignored_by_shelf()),
99 overview_started_(false),
100 original_transform_(window->layer()->GetTargetTransform()),
101 opacity_(window->layer()->GetTargetOpacity()) {
104 ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
105 if (window_) {
106 WindowSelectorAnimationSettings animation_settings(window_);
107 gfx::Transform transform;
108 SetTransformOnWindowAndTransientChildren(original_transform_, true);
109 if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) !=
110 ui::SHOW_STATE_MINIMIZED) {
111 // Setting opacity 0 and visible false ensures that the property change
112 // to SHOW_STATE_MINIMIZED will not animate the window from its original
113 // bounds to the minimized position.
114 // Hiding the window needs to be done before the target opacity is 0,
115 // otherwise the layer's visibility will not be updated
116 // (See VisibilityController::UpdateLayerVisibility).
117 window_->Hide();
118 window_->layer()->SetOpacity(0);
119 window_->SetProperty(aura::client::kShowStateKey,
120 ui::SHOW_STATE_MINIMIZED);
122 ash::wm::GetWindowState(window_)->set_ignored_by_shelf(ignored_by_shelf_);
123 window_->layer()->SetOpacity(opacity_);
127 bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
128 for (ScopedVector<ScopedWindowCopy>::const_iterator iter =
129 window_copies_.begin(); iter != window_copies_.end(); ++iter) {
130 if ((*iter)->GetWindow()->Contains(target))
131 return true;
133 aura::Window* window = window_;
134 while (window) {
135 if (window->Contains(target))
136 return true;
137 window = GetModalTransientParent(window);
139 return false;
142 gfx::Rect ScopedTransformOverviewWindow::GetBoundsInScreen() const {
143 gfx::Rect bounds;
144 aura::Window* window = window_;
145 while (window) {
146 bounds.Union(ScreenUtil::ConvertRectToScreen(window->parent(),
147 window->GetTargetBounds()));
148 window = GetModalTransientParent(window);
150 return bounds;
153 void ScopedTransformOverviewWindow::RestoreWindow() {
154 if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) ==
155 ui::SHOW_STATE_MINIMIZED) {
156 window_->Show();
160 void ScopedTransformOverviewWindow::RestoreWindowOnExit() {
161 minimized_ = false;
162 original_transform_ = gfx::Transform();
163 opacity_ = 1;
166 void ScopedTransformOverviewWindow::OnWindowDestroyed() {
167 window_ = NULL;
170 gfx::Rect ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
171 const gfx::Rect& rect,
172 const gfx::Rect& bounds) {
173 DCHECK(!rect.IsEmpty());
174 DCHECK(!bounds.IsEmpty());
175 float scale = std::min(1.0f,
176 std::min(static_cast<float>(bounds.width()) / rect.width(),
177 static_cast<float>(bounds.height()) / rect.height()));
178 return gfx::Rect(bounds.x() + 0.5 * (bounds.width() - scale * rect.width()),
179 bounds.y() + 0.5 * (bounds.height() - scale * rect.height()),
180 rect.width() * scale,
181 rect.height() * scale);
184 gfx::Transform ScopedTransformOverviewWindow::GetTransformForRect(
185 const gfx::Rect& src_rect,
186 const gfx::Rect& dst_rect) {
187 DCHECK(!src_rect.IsEmpty());
188 DCHECK(!dst_rect.IsEmpty());
189 gfx::Transform transform;
190 transform.Translate(dst_rect.x() - src_rect.x(),
191 dst_rect.y() - src_rect.y());
192 transform.Scale(static_cast<float>(dst_rect.width()) / src_rect.width(),
193 static_cast<float>(dst_rect.height()) / src_rect.height());
194 return transform;
197 void ScopedTransformOverviewWindow::SetTransform(
198 aura::Window* root_window,
199 const gfx::Transform& transform,
200 bool animate) {
201 DCHECK(overview_started_);
203 if (root_window != window_->GetRootWindow()) {
204 if (!window_copies_.empty()) {
205 bool bounds_or_hierarchy_changed = false;
206 aura::Window* window = window_;
207 for (ScopedVector<ScopedWindowCopy>::reverse_iterator iter =
208 window_copies_.rbegin();
209 !bounds_or_hierarchy_changed && iter != window_copies_.rend();
210 ++iter, window = GetModalTransientParent(window)) {
211 if (!window) {
212 bounds_or_hierarchy_changed = true;
213 } else if ((*iter)->GetWindow()->GetBoundsInScreen() !=
214 window->GetBoundsInScreen()) {
215 bounds_or_hierarchy_changed = true;
218 // Clearing the window copies array will force it to be recreated.
219 // TODO(flackr): If only the position changed and not the size,
220 // update the existing window copy's position and continue to use it.
221 if (bounds_or_hierarchy_changed)
222 window_copies_.clear();
224 if (window_copies_.empty()) {
225 // TODO(flackr): Create copies of the transient children windows as well.
226 // Currently they will only be visible on the window's initial display.
227 CopyWindowAndTransientParents(root_window, window_);
230 SetTransformOnWindowAndTransientChildren(transform, animate);
233 void ScopedTransformOverviewWindow::CopyWindowAndTransientParents(
234 aura::Window* target_root,
235 aura::Window* window) {
236 aura::Window* modal_parent = GetModalTransientParent(window);
237 if (modal_parent)
238 CopyWindowAndTransientParents(target_root, modal_parent);
239 window_copies_.push_back(new ScopedWindowCopy(target_root, window));
242 void ScopedTransformOverviewWindow::SetTransformOnWindowAndTransientChildren(
243 const gfx::Transform& transform,
244 bool animate) {
245 gfx::Point origin(GetBoundsInScreen().origin());
246 aura::Window* window = window_;
247 while (::wm::GetTransientParent(window))
248 window = ::wm::GetTransientParent(window);
249 for (ScopedVector<ScopedWindowCopy>::const_iterator iter =
250 window_copies_.begin(); iter != window_copies_.end(); ++iter) {
251 SetTransformOnWindow(
252 (*iter)->GetWindow(),
253 TranslateTransformOrigin(ScreenUtil::ConvertRectToScreen(
254 (*iter)->GetWindow()->parent(),
255 (*iter)->GetWindow()->GetTargetBounds()).origin() - origin,
256 transform),
257 animate);
259 SetTransformOnWindowAndAllTransientChildren(
260 window,
261 TranslateTransformOrigin(ScreenUtil::ConvertRectToScreen(
262 window->parent(), window->GetTargetBounds()).origin() - origin,
263 transform),
264 animate);
267 void ScopedTransformOverviewWindow::PrepareForOverview() {
268 DCHECK(!overview_started_);
269 overview_started_ = true;
270 ash::wm::GetWindowState(window_)->set_ignored_by_shelf(true);
271 RestoreWindow();
274 } // namespace ash