| 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_(ui::wm::WINDOW_TYPE_UNKNOWN), | 216 type_(ui::wm::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 |