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/aura/window.h" | 5 #include "ui/aura/window.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/stl_util.h" | |
14 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
16 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
17 #include "ui/aura/client/capture_client.h" | 16 #include "ui/aura/client/capture_client.h" |
18 #include "ui/aura/client/cursor_client.h" | 17 #include "ui/aura/client/cursor_client.h" |
19 #include "ui/aura/client/event_client.h" | 18 #include "ui/aura/client/event_client.h" |
20 #include "ui/aura/client/focus_client.h" | 19 #include "ui/aura/client/focus_client.h" |
21 #include "ui/aura/client/screen_position_client.h" | 20 #include "ui/aura/client/screen_position_client.h" |
22 #include "ui/aura/client/visibility_client.h" | 21 #include "ui/aura/client/visibility_client.h" |
23 #include "ui/aura/client/window_stacking_client.h" | 22 #include "ui/aura/client/window_stacking_client.h" |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 | 210 |
212 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider); | 211 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider); |
213 }; | 212 }; |
214 | 213 |
215 Window::Window(WindowDelegate* delegate) | 214 Window::Window(WindowDelegate* delegate) |
216 : dispatcher_(NULL), | 215 : dispatcher_(NULL), |
217 type_(client::WINDOW_TYPE_UNKNOWN), | 216 type_(client::WINDOW_TYPE_UNKNOWN), |
218 owned_by_parent_(true), | 217 owned_by_parent_(true), |
219 delegate_(delegate), | 218 delegate_(delegate), |
220 parent_(NULL), | 219 parent_(NULL), |
221 transient_parent_(NULL), | |
222 visible_(false), | 220 visible_(false), |
223 id_(-1), | 221 id_(-1), |
224 transparent_(false), | 222 transparent_(false), |
225 user_data_(NULL), | 223 user_data_(NULL), |
226 ignore_events_(false), | 224 ignore_events_(false), |
227 // Don't notify newly added observers during notification. This causes | 225 // Don't notify newly added observers during notification. This causes |
228 // problems for code that adds an observer as part of an observer | 226 // problems for code that adds an observer as part of an observer |
229 // notification (such as the workspace code). | 227 // notification (such as the workspace code). |
230 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) { | 228 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) { |
231 set_target_handler(delegate_); | 229 set_target_handler(delegate_); |
(...skipping 10 matching lines...) Expand all Loading... |
242 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this)); | 240 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this)); |
243 | 241 |
244 // Let the root know so that it can remove any references to us. | 242 // Let the root know so that it can remove any references to us. |
245 WindowEventDispatcher* dispatcher = GetDispatcher(); | 243 WindowEventDispatcher* dispatcher = GetDispatcher(); |
246 if (dispatcher) | 244 if (dispatcher) |
247 dispatcher->OnWindowDestroying(this); | 245 dispatcher->OnWindowDestroying(this); |
248 | 246 |
249 // Then destroy the children. | 247 // Then destroy the children. |
250 RemoveOrDestroyChildren(); | 248 RemoveOrDestroyChildren(); |
251 | 249 |
252 // Removes ourselves from our transient parent (if it hasn't been done by the | |
253 // RootWindow). | |
254 if (transient_parent_) | |
255 transient_parent_->RemoveTransientChild(this); | |
256 | |
257 // The window needs to be removed from the parent before calling the | 250 // The window needs to be removed from the parent before calling the |
258 // WindowDestroyed callbacks of delegate and the observers. | 251 // WindowDestroyed callbacks of delegate and the observers. |
259 if (parent_) | 252 if (parent_) |
260 parent_->RemoveChild(this); | 253 parent_->RemoveChild(this); |
261 | 254 |
262 // Destroy transient children, only after we've removed ourselves from our | |
263 // parent, as destroying an active transient child may otherwise attempt to | |
264 // refocus us. | |
265 Windows transient_children(transient_children_); | |
266 STLDeleteElements(&transient_children); | |
267 DCHECK(transient_children_.empty()); | |
268 | |
269 // Delegate and observers need to be notified after transients are deleted. | |
270 if (delegate_) | 255 if (delegate_) |
271 delegate_->OnWindowDestroyed(); | 256 delegate_->OnWindowDestroyed(); |
272 ObserverListBase<WindowObserver>::Iterator iter(observers_); | 257 ObserverListBase<WindowObserver>::Iterator iter(observers_); |
273 WindowObserver* observer; | 258 WindowObserver* observer; |
274 while ((observer = iter.GetNext())) { | 259 while ((observer = iter.GetNext())) { |
275 RemoveObserver(observer); | 260 RemoveObserver(observer); |
276 observer->OnWindowDestroyed(this); | 261 observer->OnWindowDestroyed(this); |
277 } | 262 } |
278 | 263 |
279 // Clear properties. | 264 // Clear properties. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 const WindowEventDispatcher* Window::GetDispatcher() const { | 369 const WindowEventDispatcher* Window::GetDispatcher() const { |
385 const Window* root_window = GetRootWindow(); | 370 const Window* root_window = GetRootWindow(); |
386 return root_window ? root_window->dispatcher_ : NULL; | 371 return root_window ? root_window->dispatcher_ : NULL; |
387 } | 372 } |
388 | 373 |
389 void Window::Show() { | 374 void Window::Show() { |
390 SetVisible(true); | 375 SetVisible(true); |
391 } | 376 } |
392 | 377 |
393 void Window::Hide() { | 378 void Window::Hide() { |
394 for (Windows::iterator it = transient_children_.begin(); | |
395 it != transient_children_.end(); ++it) { | |
396 (*it)->Hide(); | |
397 } | |
398 SetVisible(false); | 379 SetVisible(false); |
399 ReleaseCapture(); | 380 ReleaseCapture(); |
400 } | 381 } |
401 | 382 |
402 bool Window::IsVisible() const { | 383 bool Window::IsVisible() const { |
403 // Layer visibility can be inconsistent with window visibility, for example | 384 // Layer visibility can be inconsistent with window visibility, for example |
404 // when a Window is hidden, we want this function to return false immediately | 385 // when a Window is hidden, we want this function to return false immediately |
405 // after, even though the client may decide to animate the hide effect (and | 386 // after, even though the client may decide to animate the hide effect (and |
406 // so the layer will be visible for some time after Hide() is called). | 387 // so the layer will be visible for some time after Hide() is called). |
407 for (const Window* window = this; window; window = window->parent()) { | 388 for (const Window* window = this; window; window = window->parent()) { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 579 } |
599 | 580 |
600 bool Window::Contains(const Window* other) const { | 581 bool Window::Contains(const Window* other) const { |
601 for (const Window* parent = other; parent; parent = parent->parent_) { | 582 for (const Window* parent = other; parent; parent = parent->parent_) { |
602 if (parent == this) | 583 if (parent == this) |
603 return true; | 584 return true; |
604 } | 585 } |
605 return false; | 586 return false; |
606 } | 587 } |
607 | 588 |
608 void Window::AddTransientChild(Window* child) { | |
609 if (child->transient_parent_) | |
610 child->transient_parent_->RemoveTransientChild(child); | |
611 DCHECK(std::find(transient_children_.begin(), transient_children_.end(), | |
612 child) == transient_children_.end()); | |
613 transient_children_.push_back(child); | |
614 child->transient_parent_ = this; | |
615 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
616 OnAddTransientChild(this, child)); | |
617 } | |
618 | |
619 void Window::RemoveTransientChild(Window* child) { | |
620 Windows::iterator i = | |
621 std::find(transient_children_.begin(), transient_children_.end(), child); | |
622 DCHECK(i != transient_children_.end()); | |
623 transient_children_.erase(i); | |
624 if (child->transient_parent_ == this) | |
625 child->transient_parent_ = NULL; | |
626 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
627 OnRemoveTransientChild(this, child)); | |
628 } | |
629 | |
630 Window* Window::GetChildById(int id) { | 589 Window* Window::GetChildById(int id) { |
631 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id)); | 590 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id)); |
632 } | 591 } |
633 | 592 |
634 const Window* Window::GetChildById(int id) const { | 593 const Window* Window::GetChildById(int id) const { |
635 Windows::const_iterator i; | 594 Windows::const_iterator i; |
636 for (i = children_.begin(); i != children_.end(); ++i) { | 595 for (i = children_.begin(); i != children_.end(); ++i) { |
637 if ((*i)->id() == id) | 596 if ((*i)->id() == id) |
638 return *i; | 597 return *i; |
639 const Window* result = (*i)->GetChildById(id); | 598 const Window* result = (*i)->GetChildById(id); |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 layer_bounds += offset; | 1112 layer_bounds += offset; |
1154 layer_->SetBounds(layer_bounds); | 1113 layer_->SetBounds(layer_bounds); |
1155 } | 1114 } |
1156 } | 1115 } |
1157 | 1116 |
1158 void Window::OnParentChanged() { | 1117 void Window::OnParentChanged() { |
1159 FOR_EACH_OBSERVER( | 1118 FOR_EACH_OBSERVER( |
1160 WindowObserver, observers_, OnWindowParentChanged(this, parent_)); | 1119 WindowObserver, observers_, OnWindowParentChanged(this, parent_)); |
1161 } | 1120 } |
1162 | 1121 |
1163 bool Window::HasTransientAncestor(const Window* ancestor) const { | |
1164 if (transient_parent_ == ancestor) | |
1165 return true; | |
1166 return transient_parent_ ? | |
1167 transient_parent_->HasTransientAncestor(ancestor) : false; | |
1168 } | |
1169 | |
1170 void Window::SkipNullDelegatesForStacking(StackDirection direction, | |
1171 Window** target) const { | |
1172 DCHECK_EQ(this, (*target)->parent()); | |
1173 size_t target_i = | |
1174 std::find(children_.begin(), children_.end(), *target) - | |
1175 children_.begin(); | |
1176 | |
1177 // By convention we don't stack on top of windows with layers with NULL | |
1178 // delegates. Walk backward to find a valid target window. | |
1179 // See tests WindowTest.StackingMadrigal and StackOverClosingTransient | |
1180 // for an explanation of this. | |
1181 while (target_i > 0) { | |
1182 const size_t index = direction == STACK_ABOVE ? target_i : target_i - 1; | |
1183 if (!children_[index]->layer_ || | |
1184 children_[index]->layer_->delegate() != NULL) | |
1185 break; | |
1186 --target_i; | |
1187 } | |
1188 *target = children_[target_i]; | |
1189 } | |
1190 | |
1191 void Window::StackChildRelativeTo(Window* child, | 1122 void Window::StackChildRelativeTo(Window* child, |
1192 Window* target, | 1123 Window* target, |
1193 StackDirection direction) { | 1124 StackDirection direction) { |
1194 DCHECK_NE(child, target); | 1125 DCHECK_NE(child, target); |
1195 DCHECK(child); | 1126 DCHECK(child); |
1196 DCHECK(target); | 1127 DCHECK(target); |
1197 DCHECK_EQ(this, child->parent()); | 1128 DCHECK_EQ(this, child->parent()); |
1198 DCHECK_EQ(this, target->parent()); | 1129 DCHECK_EQ(this, target->parent()); |
1199 | 1130 |
1200 client::WindowStackingClient* stacking_client = | 1131 client::WindowStackingClient* stacking_client = |
1201 client::GetWindowStackingClient(); | 1132 client::GetWindowStackingClient(); |
1202 if (stacking_client) | 1133 if (stacking_client && |
1203 stacking_client->AdjustStacking(&child, &target, &direction); | 1134 !stacking_client->AdjustStacking(&child, &target, &direction)) |
1204 | |
1205 SkipNullDelegatesForStacking(direction, &target); | |
1206 | |
1207 // If we couldn't find a valid target position, don't move anything. | |
1208 if (direction == STACK_ABOVE && | |
1209 (target->layer_ && target->layer_->delegate() == NULL)) | |
1210 return; | 1135 return; |
1211 | 1136 |
1212 // Don't try to stack a child above itself. | |
1213 if (child == target) | |
1214 return; | |
1215 | |
1216 // Move the child. | |
1217 StackChildRelativeToImpl(child, target, direction); | |
1218 | |
1219 // Stack any transient children that share the same parent to be in front of | |
1220 // 'child'. Preserve the existing stacking order by iterating in the order | |
1221 // those children appear in children_ array. | |
1222 Window* last_transient = child; | |
1223 Windows children(children_); | |
1224 for (Windows::iterator it = children.begin(); it != children.end(); ++it) { | |
1225 Window* transient_child = *it; | |
1226 if (transient_child != last_transient && | |
1227 transient_child->HasTransientAncestor(child)) { | |
1228 StackChildRelativeToImpl(transient_child, last_transient, STACK_ABOVE); | |
1229 last_transient = transient_child; | |
1230 } | |
1231 } | |
1232 } | |
1233 | |
1234 void Window::StackChildRelativeToImpl(Window* child, | |
1235 Window* target, | |
1236 StackDirection direction) { | |
1237 DCHECK_NE(child, target); | |
1238 DCHECK(child); | |
1239 DCHECK(target); | |
1240 DCHECK_EQ(this, child->parent()); | |
1241 DCHECK_EQ(this, target->parent()); | |
1242 | |
1243 const size_t child_i = | 1137 const size_t child_i = |
1244 std::find(children_.begin(), children_.end(), child) - children_.begin(); | 1138 std::find(children_.begin(), children_.end(), child) - children_.begin(); |
1245 const size_t target_i = | 1139 const size_t target_i = |
1246 std::find(children_.begin(), children_.end(), target) - children_.begin(); | 1140 std::find(children_.begin(), children_.end(), target) - children_.begin(); |
1247 | 1141 |
1248 // Don't move the child if it is already in the right place. | 1142 // Don't move the child if it is already in the right place. |
1249 if ((direction == STACK_ABOVE && child_i == target_i + 1) || | 1143 if ((direction == STACK_ABOVE && child_i == target_i + 1) || |
1250 (direction == STACK_BELOW && child_i + 1 == target_i)) | 1144 (direction == STACK_BELOW && child_i + 1 == target_i)) |
1251 return; | 1145 return; |
1252 | 1146 |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1558 return window; | 1452 return window; |
1559 if (offset) | 1453 if (offset) |
1560 *offset += window->bounds().OffsetFromOrigin(); | 1454 *offset += window->bounds().OffsetFromOrigin(); |
1561 } | 1455 } |
1562 if (offset) | 1456 if (offset) |
1563 *offset = gfx::Vector2d(); | 1457 *offset = gfx::Vector2d(); |
1564 return NULL; | 1458 return NULL; |
1565 } | 1459 } |
1566 | 1460 |
1567 } // namespace aura | 1461 } // namespace aura |
OLD | NEW |