Put WeakPtrFactory member last in USBEventRouter
[chromium-blink-merge.git] / ash / wm / overview / scoped_transform_overview_window.cc
blob41205bf64ff8fa666af1e75383bee1332d400f6a
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/scoped_window_copy.h"
14 #include "ash/wm/overview/window_selector_item.h"
15 #include "ash/wm/window_state.h"
16 #include "ash/wm/window_util.h"
17 #include "base/macros.h"
18 #include "ui/aura/client/aura_constants.h"
19 #include "ui/aura/client/screen_position_client.h"
20 #include "ui/aura/window.h"
21 #include "ui/compositor/scoped_layer_animation_settings.h"
22 #include "ui/gfx/animation/tween.h"
23 #include "ui/gfx/transform_util.h"
24 #include "ui/views/widget/widget.h"
25 #include "ui/wm/core/window_animations.h"
26 #include "ui/wm/core/window_util.h"
28 namespace ash {
30 namespace {
32 // The opacity level that windows will be set to when they are restored.
33 const float kRestoreWindowOpacity = 1.0f;
35 aura::Window* GetTransientRoot(aura::Window* window) {
36 while (::wm::GetTransientParent(window))
37 window = ::wm::GetTransientParent(window);
38 return window;
41 // An iterator class that traverses an aura::Window and all of it's transient
42 // descendants.
43 class TransientDescendantIterator {
44 public:
45 // Creates an empty iterator.
46 TransientDescendantIterator();
48 // Copy constructor required for iterator purposes.
49 TransientDescendantIterator(
50 const TransientDescendantIterator& other) = default;
52 // Iterates over |root_window| and all of its transient descendants.
53 // Note |root_window| must not have a transient parent.
54 explicit TransientDescendantIterator(aura::Window* root_window);
56 // Prefix increment operator. This assumes there are more items (i.e.
57 // *this != TransientDescendantIterator()).
58 const TransientDescendantIterator& operator++();
60 // Comparison for STL-based loops.
61 bool operator!=(const TransientDescendantIterator& other) const;
63 // Dereference operator for STL-compatible iterators.
64 aura::Window* operator*() const;
66 private:
67 // The current window that |this| refers to. A NULL |current_window_| denotes
68 // an empty iterator and is used as the last possible value in the traversal.
69 aura::Window* current_window_;
71 // Explicit assignment operator defined because an explicit copy constructor
72 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
73 TransientDescendantIterator& operator=(
74 const TransientDescendantIterator& other) = default;
77 // Provides a virtual container implementing begin() and end() for a sequence of
78 // TransientDescendantIterators. This can be used in range-based for loops.
79 class TransientDescendantIteratorRange {
80 public:
81 explicit TransientDescendantIteratorRange(
82 const TransientDescendantIterator& begin);
84 // Copy constructor required for iterator purposes.
85 TransientDescendantIteratorRange(
86 const TransientDescendantIteratorRange& other) = default;
88 const TransientDescendantIterator& begin() const { return begin_; }
89 const TransientDescendantIterator& end() const { return end_; }
91 private:
92 TransientDescendantIterator begin_;
93 TransientDescendantIterator end_;
95 // Explicit assignment operator defined because an explicit copy constructor
96 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
97 TransientDescendantIteratorRange& operator=(
98 const TransientDescendantIteratorRange& other) = default;
101 TransientDescendantIterator::TransientDescendantIterator()
102 : current_window_(nullptr) {
105 TransientDescendantIterator::TransientDescendantIterator(
106 aura::Window* root_window)
107 : current_window_(root_window) {
108 DCHECK(!::wm::GetTransientParent(root_window));
111 // Performs a pre-order traversal of the transient descendants.
112 const TransientDescendantIterator&
113 TransientDescendantIterator::operator++() {
114 DCHECK(current_window_);
116 const aura::Window::Windows& transient_children =
117 ::wm::GetTransientChildren(current_window_);
119 if (transient_children.size() > 0) {
120 current_window_ = transient_children.front();
121 } else {
122 while (current_window_) {
123 aura::Window* parent = ::wm::GetTransientParent(current_window_);
124 if (!parent) {
125 current_window_ = nullptr;
126 break;
128 const aura::Window::Windows& transient_siblings =
129 ::wm::GetTransientChildren(parent);
130 aura::Window::Windows::const_iterator iter = std::find(
131 transient_siblings.begin(),
132 transient_siblings.end(),
133 current_window_);
134 ++iter;
135 if (iter != transient_siblings.end()) {
136 current_window_ = *iter;
137 break;
139 current_window_ = ::wm::GetTransientParent(current_window_);
142 return *this;
145 bool TransientDescendantIterator::operator!=(
146 const TransientDescendantIterator& other) const {
147 return current_window_ != other.current_window_;
150 aura::Window* TransientDescendantIterator::operator*() const {
151 return current_window_;
154 TransientDescendantIteratorRange::TransientDescendantIteratorRange(
155 const TransientDescendantIterator& begin)
156 : begin_(begin) {
159 TransientDescendantIteratorRange GetTransientTreeIterator(
160 aura::Window* window) {
161 return TransientDescendantIteratorRange(
162 TransientDescendantIterator(GetTransientRoot(window)));
165 } // namespace
167 ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(
168 aura::Window* window)
169 : window_(window),
170 activate_button_(new TransparentActivateWindowButton(
171 window_->GetRootWindow(), this)),
172 minimized_(window->GetProperty(aura::client::kShowStateKey) ==
173 ui::SHOW_STATE_MINIMIZED),
174 ignored_by_shelf_(wm::GetWindowState(window)->ignored_by_shelf()),
175 overview_started_(false),
176 original_transform_(window->layer()->GetTargetTransform()),
177 original_opacity_(window->layer()->GetTargetOpacity()) {
180 ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
181 if (window_) {
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,
203 ui::SHOW_STATE_MINIMIZED);
205 wm::GetWindowState(window_)->set_ignored_by_shelf(ignored_by_shelf_);
206 SetOpacity(original_opacity_);
210 void ScopedTransformOverviewWindow::BeginScopedAnimation(
211 OverviewAnimationType animation_type,
212 ScopedAnimationSettings* animation_settings) {
213 for (const auto& window : GetTransientTreeIterator(window_)) {
214 animation_settings->push_back(
215 new ScopedOverviewAnimationSettings(animation_type, window));
219 bool ScopedTransformOverviewWindow::Contains(const aura::Window* target) const {
220 for (const auto& window : GetTransientTreeIterator(window_)) {
221 if (window->Contains(target))
222 return true;
224 return false;
227 gfx::Rect ScopedTransformOverviewWindow::GetTargetBoundsInScreen() const {
228 gfx::Rect bounds;
229 for (const auto& window : GetTransientTreeIterator(window_)) {
230 bounds.Union(ScreenUtil::ConvertRectToScreen(window->parent(),
231 window->GetTargetBounds()));
233 return bounds;
236 void ScopedTransformOverviewWindow::RestoreWindow() {
237 if (minimized_ && window_->GetProperty(aura::client::kShowStateKey) ==
238 ui::SHOW_STATE_MINIMIZED) {
239 window_->Show();
243 void ScopedTransformOverviewWindow::RestoreWindowOnExit() {
244 minimized_ = false;
245 original_transform_ = gfx::Transform();
246 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::Select() {
306 wm::GetWindowState(window_)->Activate();
309 void ScopedTransformOverviewWindow::Close() {
310 aura::Window* window = GetTransientRoot(window_);
311 views::Widget::GetWidgetForNativeView(window)->Close();
314 void ScopedTransformOverviewWindow::PrepareForOverview() {
315 DCHECK(!overview_started_);
316 overview_started_ = true;
317 wm::GetWindowState(window_)->set_ignored_by_shelf(true);
318 RestoreWindow();
321 } // namespace ash