Added llvm into exceptions as we can't add README.chromium into 3rd party repository
[chromium-blink-merge.git] / ash / wm / overview / scoped_transform_overview_window.cc
bloba3ebe83cf2cbab43f440fcfd09f3d0b869e4ea20
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 <algorithm>
8 #include <vector>
10 #include "ash/screen_util.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/overview/scoped_overview_animation_settings.h"
13 #include "ash/wm/overview/window_selector_item.h"
14 #include "ash/wm/window_state.h"
15 #include "ash/wm/window_util.h"
16 #include "base/macros.h"
17 #include "ui/aura/client/aura_constants.h"
18 #include "ui/aura/client/screen_position_client.h"
19 #include "ui/aura/window.h"
20 #include "ui/compositor/scoped_layer_animation_settings.h"
21 #include "ui/gfx/animation/tween.h"
22 #include "ui/gfx/transform_util.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/wm/core/window_animations.h"
25 #include "ui/wm/core/window_util.h"
27 namespace ash {
29 namespace {
31 // The opacity level that windows will be set to when they are restored.
32 const float kRestoreWindowOpacity = 1.0f;
34 aura::Window* GetTransientRoot(aura::Window* window) {
35 while (::wm::GetTransientParent(window))
36 window = ::wm::GetTransientParent(window);
37 return window;
40 // An iterator class that traverses an aura::Window and all of it's transient
41 // descendants.
42 class TransientDescendantIterator {
43 public:
44 // Creates an empty iterator.
45 TransientDescendantIterator();
47 // Copy constructor required for iterator purposes.
48 TransientDescendantIterator(
49 const TransientDescendantIterator& other) = default;
51 // Iterates over |root_window| and all of its transient descendants.
52 // Note |root_window| must not have a transient parent.
53 explicit TransientDescendantIterator(aura::Window* root_window);
55 // Prefix increment operator. This assumes there are more items (i.e.
56 // *this != TransientDescendantIterator()).
57 const TransientDescendantIterator& operator++();
59 // Comparison for STL-based loops.
60 bool operator!=(const TransientDescendantIterator& other) const;
62 // Dereference operator for STL-compatible iterators.
63 aura::Window* operator*() const;
65 private:
66 // The current window that |this| refers to. A NULL |current_window_| denotes
67 // an empty iterator and is used as the last possible value in the traversal.
68 aura::Window* current_window_;
70 // Explicit assignment operator defined because an explicit copy constructor
71 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
72 TransientDescendantIterator& operator=(
73 const TransientDescendantIterator& other) = default;
76 // Provides a virtual container implementing begin() and end() for a sequence of
77 // TransientDescendantIterators. This can be used in range-based for loops.
78 class TransientDescendantIteratorRange {
79 public:
80 explicit TransientDescendantIteratorRange(
81 const TransientDescendantIterator& begin);
83 // Copy constructor required for iterator purposes.
84 TransientDescendantIteratorRange(
85 const TransientDescendantIteratorRange& other) = default;
87 const TransientDescendantIterator& begin() const { return begin_; }
88 const TransientDescendantIterator& end() const { return end_; }
90 private:
91 TransientDescendantIterator begin_;
92 TransientDescendantIterator end_;
94 // Explicit assignment operator defined because an explicit copy constructor
95 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
96 TransientDescendantIteratorRange& operator=(
97 const TransientDescendantIteratorRange& other) = default;
100 TransientDescendantIterator::TransientDescendantIterator()
101 : current_window_(nullptr) {
104 TransientDescendantIterator::TransientDescendantIterator(
105 aura::Window* root_window)
106 : current_window_(root_window) {
107 DCHECK(!::wm::GetTransientParent(root_window));
110 // Performs a pre-order traversal of the transient descendants.
111 const TransientDescendantIterator&
112 TransientDescendantIterator::operator++() {
113 DCHECK(current_window_);
115 const aura::Window::Windows& transient_children =
116 ::wm::GetTransientChildren(current_window_);
118 if (transient_children.size() > 0) {
119 current_window_ = transient_children.front();
120 } else {
121 while (current_window_) {
122 aura::Window* parent = ::wm::GetTransientParent(current_window_);
123 if (!parent) {
124 current_window_ = nullptr;
125 break;
127 const aura::Window::Windows& transient_siblings =
128 ::wm::GetTransientChildren(parent);
129 aura::Window::Windows::const_iterator iter = std::find(
130 transient_siblings.begin(),
131 transient_siblings.end(),
132 current_window_);
133 ++iter;
134 if (iter != transient_siblings.end()) {
135 current_window_ = *iter;
136 break;
138 current_window_ = ::wm::GetTransientParent(current_window_);
141 return *this;
144 bool TransientDescendantIterator::operator!=(
145 const TransientDescendantIterator& other) const {
146 return current_window_ != other.current_window_;
149 aura::Window* TransientDescendantIterator::operator*() const {
150 return current_window_;
153 TransientDescendantIteratorRange::TransientDescendantIteratorRange(
154 const TransientDescendantIterator& begin)
155 : begin_(begin) {
158 TransientDescendantIteratorRange GetTransientTreeIterator(
159 aura::Window* window) {
160 return TransientDescendantIteratorRange(
161 TransientDescendantIterator(GetTransientRoot(window)));
164 } // namespace
166 ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
167 aura::Window* window)
168 : window_(window),
169 minimized_(window->GetProperty(aura::client::kShowStateKey) ==
170 ui::SHOW_STATE_MINIMIZED),
171 ignored_by_shelf_(wm::GetWindowState(window)->ignored_by_shelf()),
172 overview_started_(false),
173 original_transform_(window->layer()->GetTargetTransform()),
174 original_opacity_(window->layer()->GetTargetOpacity()) {
175 DCHECK(window_);
178 ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
181 void ScopedTransformOverviewWindow::RestoreWindow() {
182 ScopedAnimationSettings animation_settings_list;
183 BeginScopedAnimation(
184 OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW,
185 &animation_settings_list);
186 SetTransform(window()->GetRootWindow(), original_transform_);
188 ScopedOverviewAnimationSettings animation_settings(
189 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS,
190 window_);
191 gfx::Transform transform;
192 if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) !=
193 ui::SHOW_STATE_MINIMIZED) {
194 // Setting opacity 0 and visible false ensures that the property change
195 // to SHOW_STATE_MINIMIZED will not animate the window from its original
196 // bounds to the minimized position.
197 // Hiding the window needs to be done before the target opacity is 0,
198 // otherwise the layer's visibility will not be updated
199 // (See VisibilityController::UpdateLayerVisibility).
200 window_->Hide();
201 window_->layer()->SetOpacity(0);
202 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
204 wm::GetWindowState(window_)->set_ignored_by_shelf(ignored_by_shelf_);
205 SetOpacity(original_opacity_);
208 void ScopedTransformOverviewWindow::BeginScopedAnimation(
209 OverviewAnimationType animation_type,
210 ScopedAnimationSettings* animation_settings) {
211 for (const auto& window : GetTransientTreeIterator(window_)) {
212 animation_settings->push_back(
213 new ScopedOverviewAnimationSettings(animation_type, window));
217 bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
218 for (const auto& window : GetTransientTreeIterator(window_)) {
219 if (window->Contains(target))
220 return true;
222 return false;
225 gfx::Rect ScopedTransformOverviewWindow::GetTargetBoundsInScreen() const {
226 gfx::Rect bounds;
227 for (const auto& window : GetTransientTreeIterator(window_)) {
228 bounds.Union(ScreenUtil::ConvertRectToScreen(window->parent(),
229 window->GetTargetBounds()));
231 return bounds;
234 void ScopedTransformOverviewWindow::ShowWindowIfMinimized() {
235 if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) ==
236 ui::SHOW_STATE_MINIMIZED) {
237 window_->Show();
241 void ScopedTransformOverviewWindow::ShowWindowOnExit() {
242 if (minimized_) {
243 minimized_ = false;
244 original_transform_ = gfx::Transform();
245 original_opacity_ = kRestoreWindowOpacity;
249 void ScopedTransformOverviewWindow::OnWindowDestroyed() {
250 window_ = nullptr;
253 gfx::Rect ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
254 const gfx::Rect& rect,
255 const gfx::Rect& bounds) {
256 DCHECK(!rect.IsEmpty());
257 DCHECK(!bounds.IsEmpty());
258 float scale = std::min(1.0f,
259 std::min(static_cast<float>(bounds.width()) / rect.width(),
260 static_cast<float>(bounds.height()) / rect.height()));
261 return gfx::Rect(bounds.x() + 0.5 * (bounds.width() - scale * rect.width()),
262 bounds.y() + 0.5 * (bounds.height() - scale * rect.height()),
263 rect.width() * scale,
264 rect.height() * scale);
267 gfx::Transform ScopedTransformOverviewWindow::GetTransformForRect(
268 const gfx::Rect& src_rect,
269 const gfx::Rect& dst_rect) {
270 DCHECK(!src_rect.IsEmpty());
271 DCHECK(!dst_rect.IsEmpty());
272 gfx::Transform transform;
273 transform.Translate(dst_rect.x() - src_rect.x(),
274 dst_rect.y() - src_rect.y());
275 transform.Scale(static_cast<float>(dst_rect.width()) / src_rect.width(),
276 static_cast<float>(dst_rect.height()) / src_rect.height());
277 return transform;
280 void ScopedTransformOverviewWindow::SetTransform(
281 aura::Window* root_window,
282 const gfx::Transform& transform) {
283 DCHECK(overview_started_);
285 gfx::Point target_origin(GetTargetBoundsInScreen().origin());
287 for (const auto& window : GetTransientTreeIterator(window_)) {
288 aura::Window* parent_window = window->parent();
289 gfx::Point original_origin = ScreenUtil::ConvertRectToScreen(
290 parent_window, window->GetTargetBounds()).origin();
291 gfx::Transform new_transform = TransformAboutPivot(
292 gfx::Point(target_origin.x() - original_origin.x(),
293 target_origin.y() - original_origin.y()),
294 transform);
295 window->SetTransform(new_transform);
299 void ScopedTransformOverviewWindow::SetOpacity(float opacity) {
300 for (const auto& window : GetTransientTreeIterator(window_)) {
301 window->layer()->SetOpacity(opacity);
305 void ScopedTransformOverviewWindow::Close() {
306 aura::Window* window = GetTransientRoot(window_);
307 views::Widget::GetWidgetForNativeView(window)->Close();
310 void ScopedTransformOverviewWindow::PrepareForOverview() {
311 DCHECK(!overview_started_);
312 overview_started_ = true;
313 wm::GetWindowState(window_)->set_ignored_by_shelf(true);
314 ShowWindowIfMinimized();
317 } // namespace ash