OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/corewm/window_animations.h" | 5 #include "ui/views/corewm/window_animations.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <set> | |
11 #include <vector> | 10 #include <vector> |
12 | 11 |
13 #include "base/command_line.h" | 12 #include "base/command_line.h" |
14 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
15 #include "base/debug/crash_logging.h" | |
16 #include "base/logging.h" | 14 #include "base/logging.h" |
17 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
18 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
19 #include "base/time/time.h" | 17 #include "base/time/time.h" |
20 #include "ui/aura/client/animation_host.h" | 18 #include "ui/aura/client/animation_host.h" |
21 #include "ui/aura/client/aura_constants.h" | 19 #include "ui/aura/client/aura_constants.h" |
22 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
23 #include "ui/aura/window_delegate.h" | 21 #include "ui/aura/window_delegate.h" |
24 #include "ui/aura/window_observer.h" | 22 #include "ui/aura/window_observer.h" |
25 #include "ui/aura/window_property.h" | 23 #include "ui/aura/window_property.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // destroyed when the stack unwinds. To handle this case, we start the hide | 118 // destroyed when the stack unwinds. To handle this case, we start the hide |
121 // animation immediately when the window is hidden, then when the window is | 119 // animation immediately when the window is hidden, then when the window is |
122 // subsequently destroyed this object acquires ownership of the window's layer, | 120 // subsequently destroyed this object acquires ownership of the window's layer, |
123 // so that it can continue animating it until the animation completes. | 121 // so that it can continue animating it until the animation completes. |
124 // Regardless of whether or not the window is destroyed, this object deletes | 122 // Regardless of whether or not the window is destroyed, this object deletes |
125 // itself when the animation completes. | 123 // itself when the animation completes. |
126 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, | 124 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, |
127 public aura::WindowObserver { | 125 public aura::WindowObserver { |
128 public: | 126 public: |
129 explicit HidingWindowAnimationObserver(aura::Window* window) | 127 explicit HidingWindowAnimationObserver(aura::Window* window) |
130 : topmost_window_(window) { | 128 : window_(window) { |
131 topmost_window_->AddObserver(this); | 129 window_->AddObserver(this); |
132 observed_.insert(topmost_window_); | |
133 } | 130 } |
134 virtual ~HidingWindowAnimationObserver() { | 131 virtual ~HidingWindowAnimationObserver() { |
135 STLDeleteElements(&layers_); | 132 STLDeleteElements(&layers_); |
136 | |
137 #if defined(OS_CHROMEOS) | |
138 // |topmost_window_| should either be not destroyed or |topmost_window_| | |
139 // and all of its children should be destroyed. | |
140 // TODO(pkotwicz): Remove CHECK once it has been determined whether a child | |
141 // window outliving the end of |topmost_window_|'s animation is the source | |
142 // of the crash in crbug.com/338788 | |
143 if (!topmost_window_ && !observed_.empty()) { | |
144 aura::Window* first_observed = *observed_.begin(); | |
145 std::string name = first_observed->name(); | |
146 base::debug::SetCrashKeyValue("window_destroyed_layer", name); | |
147 CHECK(false); | |
148 } | |
149 #endif // defined(OS_CHROMEOS) | |
150 | |
151 for (std::set<aura::Window*>::const_iterator it = observed_.begin(); | |
152 it != observed_.end(); | |
153 ++it) { | |
154 (*it)->RemoveObserver(this); | |
155 } | |
156 } | 133 } |
157 | 134 |
158 private: | 135 private: |
159 // Overridden from ui::ImplicitAnimationObserver: | 136 // Overridden from ui::ImplicitAnimationObserver: |
160 virtual void OnImplicitAnimationsCompleted() OVERRIDE { | 137 virtual void OnImplicitAnimationsCompleted() OVERRIDE { |
161 // Window may have been destroyed by this point. | 138 // Window may have been destroyed by this point. |
162 if (topmost_window_) { | 139 if (window_) { |
163 aura::client::AnimationHost* animation_host = | 140 aura::client::AnimationHost* animation_host = |
164 aura::client::GetAnimationHost(topmost_window_); | 141 aura::client::GetAnimationHost(window_); |
165 if (animation_host) | 142 if (animation_host) |
166 animation_host->OnWindowHidingAnimationCompleted(); | 143 animation_host->OnWindowHidingAnimationCompleted(); |
| 144 window_->RemoveObserver(this); |
167 } | 145 } |
168 delete this; | 146 delete this; |
169 } | 147 } |
170 | 148 |
171 // Overridden from aura::WindowObserver: | 149 // Overridden from aura::WindowObserver: |
172 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { | 150 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { |
173 window->RemoveObserver(this); | 151 DCHECK_EQ(window, window_); |
174 observed_.erase(window); | |
175 | |
176 if (window != topmost_window_) | |
177 return; | |
178 | |
179 // We acquire the layers of all of |topmost_window_|'s children with the | |
180 // assumption that they will be destroyed by the time that the animation | |
181 // terminates. Observe |topmost_window_|'s children to verify the | |
182 // assumption. | |
183 ObserveAllChildren(topmost_window_); | |
184 | |
185 DCHECK(layers_.empty()); | 152 DCHECK(layers_.empty()); |
186 AcquireAllLayers(topmost_window_); | 153 AcquireAllLayers(window_); |
187 | 154 |
188 // If the Widget has views with layers, then it is necessary to take | 155 // If the Widget has views with layers, then it is necessary to take |
189 // ownership of those layers too. | 156 // ownership of those layers too. |
190 views::Widget* widget = views::Widget::GetWidgetForNativeWindow( | 157 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_); |
191 topmost_window_); | |
192 const views::Widget* const_widget = widget; | 158 const views::Widget* const_widget = widget; |
193 if (widget && const_widget->GetRootView() && widget->GetContentsView()) | 159 if (widget && const_widget->GetRootView() && widget->GetContentsView()) |
194 AcquireAllViewLayers(widget->GetContentsView()); | 160 AcquireAllViewLayers(widget->GetContentsView()); |
195 topmost_window_ = NULL; | 161 window_->RemoveObserver(this); |
196 } | 162 window_ = NULL; |
197 | |
198 // Starts observing all of the windows in a subtree rooted at |window| | |
199 // excluding |window|. | |
200 void ObserveAllChildren(aura::Window* window) { | |
201 for (aura::Window::Windows::const_iterator it = window->children().begin(); | |
202 it != window->children().end(); | |
203 ++it) { | |
204 aura::Window* child = *it; | |
205 child->AddObserver(this); | |
206 observed_.insert(child); | |
207 ObserveAllChildren(child); | |
208 } | |
209 } | 163 } |
210 | 164 |
211 void AcquireAllLayers(aura::Window* window) { | 165 void AcquireAllLayers(aura::Window* window) { |
212 ui::Layer* layer = window->AcquireLayer(); | 166 ui::Layer* layer = window->AcquireLayer(); |
213 DCHECK(layer); | 167 DCHECK(layer); |
214 layers_.push_back(layer); | 168 layers_.push_back(layer); |
215 for (aura::Window::Windows::const_iterator it = window->children().begin(); | 169 for (aura::Window::Windows::const_iterator it = window->children().begin(); |
216 it != window->children().end(); | 170 it != window->children().end(); |
217 ++it) | 171 ++it) |
218 AcquireAllLayers(*it); | 172 AcquireAllLayers(*it); |
219 } | 173 } |
220 | 174 |
221 void AcquireAllViewLayers(views::View* view) { | 175 void AcquireAllViewLayers(views::View* view) { |
222 for (int i = 0; i < view->child_count(); ++i) | 176 for (int i = 0; i < view->child_count(); ++i) |
223 AcquireAllViewLayers(view->child_at(i)); | 177 AcquireAllViewLayers(view->child_at(i)); |
224 if (view->layer()) { | 178 if (view->layer()) { |
225 ui::Layer* layer = view->RecreateLayer(); | 179 ui::Layer* layer = view->RecreateLayer(); |
226 if (layer) { | 180 if (layer) { |
227 layer->SuppressPaint(); | 181 layer->SuppressPaint(); |
228 layers_.push_back(layer); | 182 layers_.push_back(layer); |
229 } | 183 } |
230 } | 184 } |
231 } | 185 } |
232 | 186 |
233 aura::Window* topmost_window_; | 187 aura::Window* window_; |
234 | |
235 // The set of windows observed by this class. | |
236 std::set<aura::Window*> observed_; | |
237 | |
238 std::vector<ui::Layer*> layers_; | 188 std::vector<ui::Layer*> layers_; |
239 | 189 |
240 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); | 190 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); |
241 }; | 191 }; |
242 | 192 |
243 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { | 193 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { |
244 const Layer* root = layer; | 194 const Layer* root = layer; |
245 while (root->parent()) | 195 while (root->parent()) |
246 root = root->parent(); | 196 root = root->parent(); |
247 layer->GetTargetTransformRelativeTo(root, transform); | 197 layer->GetTargetTransformRelativeTo(root, transform); |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 | 569 |
620 bool WindowAnimationsDisabled(aura::Window* window) { | 570 bool WindowAnimationsDisabled(aura::Window* window) { |
621 return (!gfx::Animation::ShouldRenderRichAnimation() || (window && | 571 return (!gfx::Animation::ShouldRenderRichAnimation() || (window && |
622 window->GetProperty(aura::client::kAnimationsDisabledKey)) || | 572 window->GetProperty(aura::client::kAnimationsDisabledKey)) || |
623 CommandLine::ForCurrentProcess()->HasSwitch( | 573 CommandLine::ForCurrentProcess()->HasSwitch( |
624 switches::kWindowAnimationsDisabled)); | 574 switches::kWindowAnimationsDisabled)); |
625 } | 575 } |
626 | 576 |
627 } // namespace corewm | 577 } // namespace corewm |
628 } // namespace views | 578 } // namespace views |
OLD | NEW |