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