| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/aura/window.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/bind_helpers.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/strings/string_number_conversions.h" | |
| 14 #include "base/strings/string_util.h" | |
| 15 #include "base/strings/stringprintf.h" | |
| 16 #include "ui/aura/client/capture_client.h" | |
| 17 #include "ui/aura/client/cursor_client.h" | |
| 18 #include "ui/aura/client/event_client.h" | |
| 19 #include "ui/aura/client/focus_client.h" | |
| 20 #include "ui/aura/client/screen_position_client.h" | |
| 21 #include "ui/aura/client/visibility_client.h" | |
| 22 #include "ui/aura/client/window_stacking_client.h" | |
| 23 #include "ui/aura/env.h" | |
| 24 #include "ui/aura/layout_manager.h" | |
| 25 #include "ui/aura/window_delegate.h" | |
| 26 #include "ui/aura/window_event_dispatcher.h" | |
| 27 #include "ui/aura/window_observer.h" | |
| 28 #include "ui/aura/window_tracker.h" | |
| 29 #include "ui/aura/window_tree_host.h" | |
| 30 #include "ui/compositor/compositor.h" | |
| 31 #include "ui/compositor/layer.h" | |
| 32 #include "ui/events/event_target_iterator.h" | |
| 33 #include "ui/gfx/canvas.h" | |
| 34 #include "ui/gfx/path.h" | |
| 35 #include "ui/gfx/scoped_canvas.h" | |
| 36 #include "ui/gfx/screen.h" | |
| 37 | |
| 38 namespace aura { | |
| 39 | |
| 40 namespace { | |
| 41 | |
| 42 ui::LayerType WindowLayerTypeToUILayerType(WindowLayerType window_layer_type) { | |
| 43 switch (window_layer_type) { | |
| 44 case WINDOW_LAYER_NONE: | |
| 45 break; | |
| 46 case WINDOW_LAYER_NOT_DRAWN: | |
| 47 return ui::LAYER_NOT_DRAWN; | |
| 48 case WINDOW_LAYER_TEXTURED: | |
| 49 return ui::LAYER_TEXTURED; | |
| 50 case WINDOW_LAYER_SOLID_COLOR: | |
| 51 return ui::LAYER_SOLID_COLOR; | |
| 52 } | |
| 53 NOTREACHED(); | |
| 54 return ui::LAYER_NOT_DRAWN; | |
| 55 } | |
| 56 | |
| 57 // Used when searching for a Window to stack relative to. | |
| 58 template <class T> | |
| 59 T IteratorForDirectionBegin(aura::Window* window); | |
| 60 | |
| 61 template <> | |
| 62 Window::Windows::const_iterator IteratorForDirectionBegin( | |
| 63 aura::Window* window) { | |
| 64 return window->children().begin(); | |
| 65 } | |
| 66 | |
| 67 template <> | |
| 68 Window::Windows::const_reverse_iterator IteratorForDirectionBegin( | |
| 69 aura::Window* window) { | |
| 70 return window->children().rbegin(); | |
| 71 } | |
| 72 | |
| 73 template <class T> | |
| 74 T IteratorForDirectionEnd(aura::Window* window); | |
| 75 | |
| 76 template <> | |
| 77 Window::Windows::const_iterator IteratorForDirectionEnd(aura::Window* window) { | |
| 78 return window->children().end(); | |
| 79 } | |
| 80 | |
| 81 template <> | |
| 82 Window::Windows::const_reverse_iterator IteratorForDirectionEnd( | |
| 83 aura::Window* window) { | |
| 84 return window->children().rend(); | |
| 85 } | |
| 86 | |
| 87 // Depth first search for the first Window with a layer to stack relative | |
| 88 // to. Starts at target. Does not descend into |ignore|. | |
| 89 template <class T> | |
| 90 ui::Layer* FindStackingTargetLayerDown(aura::Window* target, | |
| 91 aura::Window* ignore) { | |
| 92 if (target == ignore) | |
| 93 return NULL; | |
| 94 | |
| 95 if (target->layer()) | |
| 96 return target->layer(); | |
| 97 | |
| 98 for (T i = IteratorForDirectionBegin<T>(target); | |
| 99 i != IteratorForDirectionEnd<T>(target); ++i) { | |
| 100 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore); | |
| 101 if (layer) | |
| 102 return layer; | |
| 103 } | |
| 104 return NULL; | |
| 105 } | |
| 106 | |
| 107 // Depth first search through the siblings of |target||. This does not search | |
| 108 // all the siblings, only those before/after |target| (depening upon the | |
| 109 // template type) and ignoring |ignore|. Returns the Layer of the first Window | |
| 110 // encountered with a Layer. | |
| 111 template <class T> | |
| 112 ui::Layer* FindStackingLayerInSiblings(aura::Window* target, | |
| 113 aura::Window* ignore) { | |
| 114 aura::Window* parent = target->parent(); | |
| 115 for (T i = std::find(IteratorForDirectionBegin<T>(parent), | |
| 116 IteratorForDirectionEnd<T>(parent), target); | |
| 117 i != IteratorForDirectionEnd<T>(parent); ++i) { | |
| 118 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore); | |
| 119 if (layer) | |
| 120 return layer; | |
| 121 } | |
| 122 return NULL; | |
| 123 } | |
| 124 | |
| 125 // Returns the first Window that has a Layer. This does a depth first search | |
| 126 // through the descendants of |target| first, then ascends up doing a depth | |
| 127 // first search through siblings of all ancestors until a Layer is found or an | |
| 128 // ancestor with a layer is found. This is intended to locate a layer to stack | |
| 129 // other layers relative to. | |
| 130 template <class T> | |
| 131 ui::Layer* FindStackingTargetLayer(aura::Window* target, aura::Window* ignore) { | |
| 132 ui::Layer* result = FindStackingTargetLayerDown<T>(target, ignore); | |
| 133 if (result) | |
| 134 return result; | |
| 135 while (target->parent()) { | |
| 136 ui::Layer* result = FindStackingLayerInSiblings<T>(target, ignore); | |
| 137 if (result) | |
| 138 return result; | |
| 139 target = target->parent(); | |
| 140 if (target->layer()) | |
| 141 return NULL; | |
| 142 } | |
| 143 return NULL; | |
| 144 } | |
| 145 | |
| 146 // Does a depth first search for all descendants of |child| that have layers. | |
| 147 // This stops at any descendants that have layers (and adds them to |layers|). | |
| 148 void GetLayersToStack(aura::Window* child, std::vector<ui::Layer*>* layers) { | |
| 149 if (child->layer()) { | |
| 150 layers->push_back(child->layer()); | |
| 151 return; | |
| 152 } | |
| 153 for (size_t i = 0; i < child->children().size(); ++i) | |
| 154 GetLayersToStack(child->children()[i], layers); | |
| 155 } | |
| 156 | |
| 157 } // namespace | |
| 158 | |
| 159 class ScopedCursorHider { | |
| 160 public: | |
| 161 explicit ScopedCursorHider(Window* window) | |
| 162 : window_(window), | |
| 163 hid_cursor_(false) { | |
| 164 if (!window_->IsRootWindow()) | |
| 165 return; | |
| 166 const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains( | |
| 167 Env::GetInstance()->last_mouse_location()); | |
| 168 client::CursorClient* cursor_client = client::GetCursorClient(window_); | |
| 169 if (cursor_is_in_bounds && cursor_client && | |
| 170 cursor_client->IsCursorVisible()) { | |
| 171 cursor_client->HideCursor(); | |
| 172 hid_cursor_ = true; | |
| 173 } | |
| 174 } | |
| 175 ~ScopedCursorHider() { | |
| 176 if (!window_->IsRootWindow()) | |
| 177 return; | |
| 178 | |
| 179 // Update the device scale factor of the cursor client only when the last | |
| 180 // mouse location is on this root window. | |
| 181 if (hid_cursor_) { | |
| 182 client::CursorClient* cursor_client = client::GetCursorClient(window_); | |
| 183 if (cursor_client) { | |
| 184 const gfx::Display& display = | |
| 185 gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow( | |
| 186 window_); | |
| 187 cursor_client->SetDisplay(display); | |
| 188 cursor_client->ShowCursor(); | |
| 189 } | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 private: | |
| 194 Window* window_; | |
| 195 bool hid_cursor_; | |
| 196 | |
| 197 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider); | |
| 198 }; | |
| 199 | |
| 200 Window::Window(WindowDelegate* delegate) | |
| 201 : host_(NULL), | |
| 202 type_(ui::wm::WINDOW_TYPE_UNKNOWN), | |
| 203 owned_by_parent_(true), | |
| 204 delegate_(delegate), | |
| 205 parent_(NULL), | |
| 206 visible_(false), | |
| 207 id_(-1), | |
| 208 transparent_(false), | |
| 209 user_data_(NULL), | |
| 210 ignore_events_(false), | |
| 211 // Don't notify newly added observers during notification. This causes | |
| 212 // problems for code that adds an observer as part of an observer | |
| 213 // notification (such as the workspace code). | |
| 214 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) { | |
| 215 set_target_handler(delegate_); | |
| 216 } | |
| 217 | |
| 218 Window::~Window() { | |
| 219 // |layer()| can be NULL during tests, or if this Window is layerless. | |
| 220 if (layer()) { | |
| 221 if (layer()->owner() == this) | |
| 222 layer()->CompleteAllAnimations(); | |
| 223 layer()->SuppressPaint(); | |
| 224 } | |
| 225 | |
| 226 // Let the delegate know we're in the processing of destroying. | |
| 227 if (delegate_) | |
| 228 delegate_->OnWindowDestroying(this); | |
| 229 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this)); | |
| 230 | |
| 231 // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be | |
| 232 // necessary but unfortunately is right now due to ordering | |
| 233 // peculiarities. WED must be notified _after_ other observers | |
| 234 // are notified of pending teardown but before the hierarchy | |
| 235 // is actually torn down. | |
| 236 WindowTreeHost* host = GetHost(); | |
| 237 if (host) | |
| 238 host->dispatcher()->OnPostNotifiedWindowDestroying(this); | |
| 239 | |
| 240 // The window should have already had its state cleaned up in | |
| 241 // WindowEventDispatcher::OnWindowHidden(), but there have been some crashes | |
| 242 // involving windows being destroyed without being hidden first. See | |
| 243 // crbug.com/342040. This should help us debug the issue. TODO(tdresser): | |
| 244 // remove this once we determine why we have windows that are destroyed | |
| 245 // without being hidden. | |
| 246 bool window_incorrectly_cleaned_up = CleanupGestureState(); | |
| 247 CHECK(!window_incorrectly_cleaned_up); | |
| 248 | |
| 249 // Then destroy the children. | |
| 250 RemoveOrDestroyChildren(); | |
| 251 | |
| 252 // The window needs to be removed from the parent before calling the | |
| 253 // WindowDestroyed callbacks of delegate and the observers. | |
| 254 if (parent_) | |
| 255 parent_->RemoveChild(this); | |
| 256 | |
| 257 if (delegate_) | |
| 258 delegate_->OnWindowDestroyed(this); | |
| 259 ObserverListBase<WindowObserver>::Iterator iter(observers_); | |
| 260 for (WindowObserver* observer = iter.GetNext(); observer; | |
| 261 observer = iter.GetNext()) { | |
| 262 RemoveObserver(observer); | |
| 263 observer->OnWindowDestroyed(this); | |
| 264 } | |
| 265 | |
| 266 // Clear properties. | |
| 267 for (std::map<const void*, Value>::const_iterator iter = prop_map_.begin(); | |
| 268 iter != prop_map_.end(); | |
| 269 ++iter) { | |
| 270 if (iter->second.deallocator) | |
| 271 (*iter->second.deallocator)(iter->second.value); | |
| 272 } | |
| 273 prop_map_.clear(); | |
| 274 | |
| 275 // If we have layer it will either be destroyed by |layer_owner_|'s dtor, or | |
| 276 // by whoever acquired it. We don't have a layer if Init() wasn't invoked or | |
| 277 // we are layerless. | |
| 278 if (layer()) | |
| 279 layer()->set_delegate(NULL); | |
| 280 DestroyLayer(); | |
| 281 } | |
| 282 | |
| 283 void Window::Init(WindowLayerType window_layer_type) { | |
| 284 if (window_layer_type != WINDOW_LAYER_NONE) { | |
| 285 SetLayer(new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type))); | |
| 286 layer()->SetVisible(false); | |
| 287 layer()->set_delegate(this); | |
| 288 UpdateLayerName(); | |
| 289 layer()->SetFillsBoundsOpaquely(!transparent_); | |
| 290 } | |
| 291 | |
| 292 Env::GetInstance()->NotifyWindowInitialized(this); | |
| 293 } | |
| 294 | |
| 295 void Window::SetType(ui::wm::WindowType type) { | |
| 296 // Cannot change type after the window is initialized. | |
| 297 DCHECK(!layer()); | |
| 298 type_ = type; | |
| 299 } | |
| 300 | |
| 301 void Window::SetName(const std::string& name) { | |
| 302 name_ = name; | |
| 303 | |
| 304 if (layer()) | |
| 305 UpdateLayerName(); | |
| 306 } | |
| 307 | |
| 308 void Window::SetTitle(const base::string16& title) { | |
| 309 title_ = title; | |
| 310 FOR_EACH_OBSERVER(WindowObserver, | |
| 311 observers_, | |
| 312 OnWindowTitleChanged(this)); | |
| 313 } | |
| 314 | |
| 315 void Window::SetTransparent(bool transparent) { | |
| 316 transparent_ = transparent; | |
| 317 if (layer()) | |
| 318 layer()->SetFillsBoundsOpaquely(!transparent_); | |
| 319 } | |
| 320 | |
| 321 void Window::SetFillsBoundsCompletely(bool fills_bounds) { | |
| 322 if (layer()) | |
| 323 layer()->SetFillsBoundsCompletely(fills_bounds); | |
| 324 } | |
| 325 | |
| 326 Window* Window::GetRootWindow() { | |
| 327 return const_cast<Window*>( | |
| 328 static_cast<const Window*>(this)->GetRootWindow()); | |
| 329 } | |
| 330 | |
| 331 const Window* Window::GetRootWindow() const { | |
| 332 return IsRootWindow() ? this : parent_ ? parent_->GetRootWindow() : NULL; | |
| 333 } | |
| 334 | |
| 335 WindowTreeHost* Window::GetHost() { | |
| 336 return const_cast<WindowTreeHost*>(const_cast<const Window*>(this)-> | |
| 337 GetHost()); | |
| 338 } | |
| 339 | |
| 340 const WindowTreeHost* Window::GetHost() const { | |
| 341 const Window* root_window = GetRootWindow(); | |
| 342 return root_window ? root_window->host_ : NULL; | |
| 343 } | |
| 344 | |
| 345 void Window::Show() { | |
| 346 if (layer()) { | |
| 347 DCHECK_EQ(visible_, layer()->GetTargetVisibility()); | |
| 348 // It is not allowed that a window is visible but the layers alpha is fully | |
| 349 // transparent since the window would still be considered to be active but | |
| 350 // could not be seen. | |
| 351 DCHECK(!(visible_ && layer()->GetTargetOpacity() == 0.0f)); | |
| 352 } | |
| 353 SetVisible(true); | |
| 354 } | |
| 355 | |
| 356 void Window::Hide() { | |
| 357 // RootWindow::OnVisibilityChanged will call ReleaseCapture. | |
| 358 SetVisible(false); | |
| 359 } | |
| 360 | |
| 361 bool Window::IsVisible() const { | |
| 362 // Layer visibility can be inconsistent with window visibility, for example | |
| 363 // when a Window is hidden, we want this function to return false immediately | |
| 364 // after, even though the client may decide to animate the hide effect (and | |
| 365 // so the layer will be visible for some time after Hide() is called). | |
| 366 for (const Window* window = this; window; window = window->parent()) { | |
| 367 if (!window->visible_) | |
| 368 return false; | |
| 369 if (window->layer()) | |
| 370 return window->layer()->IsDrawn(); | |
| 371 } | |
| 372 return false; | |
| 373 } | |
| 374 | |
| 375 gfx::Rect Window::GetBoundsInRootWindow() const { | |
| 376 // TODO(beng): There may be a better way to handle this, and the existing code | |
| 377 // is likely wrong anyway in a multi-display world, but this will | |
| 378 // do for now. | |
| 379 if (!GetRootWindow()) | |
| 380 return bounds(); | |
| 381 gfx::Point origin = bounds().origin(); | |
| 382 ConvertPointToTarget(parent_, GetRootWindow(), &origin); | |
| 383 return gfx::Rect(origin, bounds().size()); | |
| 384 } | |
| 385 | |
| 386 gfx::Rect Window::GetBoundsInScreen() const { | |
| 387 gfx::Rect bounds(GetBoundsInRootWindow()); | |
| 388 const Window* root = GetRootWindow(); | |
| 389 if (root) { | |
| 390 aura::client::ScreenPositionClient* screen_position_client = | |
| 391 aura::client::GetScreenPositionClient(root); | |
| 392 if (screen_position_client) { | |
| 393 gfx::Point origin = bounds.origin(); | |
| 394 screen_position_client->ConvertPointToScreen(root, &origin); | |
| 395 bounds.set_origin(origin); | |
| 396 } | |
| 397 } | |
| 398 return bounds; | |
| 399 } | |
| 400 | |
| 401 void Window::SetTransform(const gfx::Transform& transform) { | |
| 402 if (!layer()) { | |
| 403 // Transforms aren't supported on layerless windows. | |
| 404 NOTREACHED(); | |
| 405 return; | |
| 406 } | |
| 407 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 408 OnWindowTransforming(this)); | |
| 409 layer()->SetTransform(transform); | |
| 410 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 411 OnWindowTransformed(this)); | |
| 412 NotifyAncestorWindowTransformed(this); | |
| 413 } | |
| 414 | |
| 415 void Window::SetLayoutManager(LayoutManager* layout_manager) { | |
| 416 if (layout_manager == layout_manager_) | |
| 417 return; | |
| 418 layout_manager_.reset(layout_manager); | |
| 419 if (!layout_manager) | |
| 420 return; | |
| 421 // If we're changing to a new layout manager, ensure it is aware of all the | |
| 422 // existing child windows. | |
| 423 for (Windows::const_iterator it = children_.begin(); | |
| 424 it != children_.end(); | |
| 425 ++it) | |
| 426 layout_manager_->OnWindowAddedToLayout(*it); | |
| 427 } | |
| 428 | |
| 429 scoped_ptr<ui::EventTargeter> | |
| 430 Window::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) { | |
| 431 scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass(); | |
| 432 targeter_ = targeter.Pass(); | |
| 433 return old_targeter.Pass(); | |
| 434 } | |
| 435 | |
| 436 void Window::SetBounds(const gfx::Rect& new_bounds) { | |
| 437 if (parent_ && parent_->layout_manager()) | |
| 438 parent_->layout_manager()->SetChildBounds(this, new_bounds); | |
| 439 else { | |
| 440 // Ensure we don't go smaller than our minimum bounds. | |
| 441 gfx::Rect final_bounds(new_bounds); | |
| 442 if (delegate_) { | |
| 443 const gfx::Size& min_size = delegate_->GetMinimumSize(); | |
| 444 final_bounds.set_width(std::max(min_size.width(), final_bounds.width())); | |
| 445 final_bounds.set_height(std::max(min_size.height(), | |
| 446 final_bounds.height())); | |
| 447 } | |
| 448 SetBoundsInternal(final_bounds); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen, | |
| 453 const gfx::Display& dst_display) { | |
| 454 Window* root = GetRootWindow(); | |
| 455 if (root) { | |
| 456 gfx::Point origin = new_bounds_in_screen.origin(); | |
| 457 aura::client::ScreenPositionClient* screen_position_client = | |
| 458 aura::client::GetScreenPositionClient(root); | |
| 459 screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display); | |
| 460 return; | |
| 461 } | |
| 462 SetBounds(new_bounds_in_screen); | |
| 463 } | |
| 464 | |
| 465 gfx::Rect Window::GetTargetBounds() const { | |
| 466 if (!layer()) | |
| 467 return bounds(); | |
| 468 | |
| 469 if (!parent_ || parent_->layer()) | |
| 470 return layer()->GetTargetBounds(); | |
| 471 | |
| 472 // We have a layer but our parent (who is valid) doesn't. This means the | |
| 473 // coordinates of the layer are relative to the first ancestor with a layer; | |
| 474 // convert to be relative to parent. | |
| 475 gfx::Vector2d offset; | |
| 476 const aura::Window* ancestor_with_layer = | |
| 477 parent_->GetAncestorWithLayer(&offset); | |
| 478 if (!ancestor_with_layer) | |
| 479 return layer()->GetTargetBounds(); | |
| 480 | |
| 481 gfx::Rect layer_target_bounds = layer()->GetTargetBounds(); | |
| 482 layer_target_bounds -= offset; | |
| 483 return layer_target_bounds; | |
| 484 } | |
| 485 | |
| 486 void Window::SchedulePaintInRect(const gfx::Rect& rect) { | |
| 487 if (!layer() && parent_) { | |
| 488 // Notification of paint scheduled happens for the window with a layer. | |
| 489 gfx::Rect parent_rect(bounds().size()); | |
| 490 parent_rect.Intersect(rect); | |
| 491 if (!parent_rect.IsEmpty()) { | |
| 492 parent_rect.Offset(bounds().origin().OffsetFromOrigin()); | |
| 493 parent_->SchedulePaintInRect(parent_rect); | |
| 494 } | |
| 495 } else if (layer()) { | |
| 496 layer()->SchedulePaint(rect); | |
| 497 } | |
| 498 } | |
| 499 | |
| 500 void Window::StackChildAtTop(Window* child) { | |
| 501 if (children_.size() <= 1 || child == children_.back()) | |
| 502 return; // In the front already. | |
| 503 StackChildAbove(child, children_.back()); | |
| 504 } | |
| 505 | |
| 506 void Window::StackChildAbove(Window* child, Window* target) { | |
| 507 StackChildRelativeTo(child, target, STACK_ABOVE); | |
| 508 } | |
| 509 | |
| 510 void Window::StackChildAtBottom(Window* child) { | |
| 511 if (children_.size() <= 1 || child == children_.front()) | |
| 512 return; // At the bottom already. | |
| 513 StackChildBelow(child, children_.front()); | |
| 514 } | |
| 515 | |
| 516 void Window::StackChildBelow(Window* child, Window* target) { | |
| 517 StackChildRelativeTo(child, target, STACK_BELOW); | |
| 518 } | |
| 519 | |
| 520 void Window::AddChild(Window* child) { | |
| 521 WindowObserver::HierarchyChangeParams params; | |
| 522 params.target = child; | |
| 523 params.new_parent = this; | |
| 524 params.old_parent = child->parent(); | |
| 525 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; | |
| 526 NotifyWindowHierarchyChange(params); | |
| 527 | |
| 528 Window* old_root = child->GetRootWindow(); | |
| 529 | |
| 530 DCHECK(std::find(children_.begin(), children_.end(), child) == | |
| 531 children_.end()); | |
| 532 if (child->parent()) | |
| 533 child->parent()->RemoveChildImpl(child, this); | |
| 534 | |
| 535 gfx::Vector2d offset; | |
| 536 aura::Window* ancestor_with_layer = GetAncestorWithLayer(&offset); | |
| 537 | |
| 538 child->parent_ = this; | |
| 539 | |
| 540 if (ancestor_with_layer) { | |
| 541 offset += child->bounds().OffsetFromOrigin(); | |
| 542 child->ReparentLayers(ancestor_with_layer->layer(), offset); | |
| 543 } | |
| 544 | |
| 545 children_.push_back(child); | |
| 546 if (layout_manager_) | |
| 547 layout_manager_->OnWindowAddedToLayout(child); | |
| 548 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child)); | |
| 549 child->OnParentChanged(); | |
| 550 | |
| 551 Window* root_window = GetRootWindow(); | |
| 552 if (root_window && old_root != root_window) { | |
| 553 root_window->GetHost()->dispatcher()->OnWindowAddedToRootWindow(child); | |
| 554 child->NotifyAddedToRootWindow(); | |
| 555 } | |
| 556 | |
| 557 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; | |
| 558 NotifyWindowHierarchyChange(params); | |
| 559 } | |
| 560 | |
| 561 void Window::RemoveChild(Window* child) { | |
| 562 WindowObserver::HierarchyChangeParams params; | |
| 563 params.target = child; | |
| 564 params.new_parent = NULL; | |
| 565 params.old_parent = this; | |
| 566 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; | |
| 567 NotifyWindowHierarchyChange(params); | |
| 568 | |
| 569 RemoveChildImpl(child, NULL); | |
| 570 | |
| 571 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; | |
| 572 NotifyWindowHierarchyChange(params); | |
| 573 } | |
| 574 | |
| 575 bool Window::Contains(const Window* other) const { | |
| 576 for (const Window* parent = other; parent; parent = parent->parent_) { | |
| 577 if (parent == this) | |
| 578 return true; | |
| 579 } | |
| 580 return false; | |
| 581 } | |
| 582 | |
| 583 Window* Window::GetChildById(int id) { | |
| 584 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id)); | |
| 585 } | |
| 586 | |
| 587 const Window* Window::GetChildById(int id) const { | |
| 588 Windows::const_iterator i; | |
| 589 for (i = children_.begin(); i != children_.end(); ++i) { | |
| 590 if ((*i)->id() == id) | |
| 591 return *i; | |
| 592 const Window* result = (*i)->GetChildById(id); | |
| 593 if (result) | |
| 594 return result; | |
| 595 } | |
| 596 return NULL; | |
| 597 } | |
| 598 | |
| 599 // static | |
| 600 void Window::ConvertPointToTarget(const Window* source, | |
| 601 const Window* target, | |
| 602 gfx::Point* point) { | |
| 603 if (!source) | |
| 604 return; | |
| 605 if (source->GetRootWindow() != target->GetRootWindow()) { | |
| 606 client::ScreenPositionClient* source_client = | |
| 607 client::GetScreenPositionClient(source->GetRootWindow()); | |
| 608 // |source_client| can be NULL in tests. | |
| 609 if (source_client) | |
| 610 source_client->ConvertPointToScreen(source, point); | |
| 611 | |
| 612 client::ScreenPositionClient* target_client = | |
| 613 client::GetScreenPositionClient(target->GetRootWindow()); | |
| 614 // |target_client| can be NULL in tests. | |
| 615 if (target_client) | |
| 616 target_client->ConvertPointFromScreen(target, point); | |
| 617 } else if ((source != target) && (!source->layer() || !target->layer())) { | |
| 618 if (!source->layer()) { | |
| 619 gfx::Vector2d offset_to_layer; | |
| 620 source = source->GetAncestorWithLayer(&offset_to_layer); | |
| 621 *point += offset_to_layer; | |
| 622 } | |
| 623 if (!target->layer()) { | |
| 624 gfx::Vector2d offset_to_layer; | |
| 625 target = target->GetAncestorWithLayer(&offset_to_layer); | |
| 626 *point -= offset_to_layer; | |
| 627 } | |
| 628 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point); | |
| 629 } else { | |
| 630 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point); | |
| 631 } | |
| 632 } | |
| 633 | |
| 634 // static | |
| 635 void Window::ConvertRectToTarget(const Window* source, | |
| 636 const Window* target, | |
| 637 gfx::Rect* rect) { | |
| 638 DCHECK(rect); | |
| 639 gfx::Point origin = rect->origin(); | |
| 640 ConvertPointToTarget(source, target, &origin); | |
| 641 rect->set_origin(origin); | |
| 642 } | |
| 643 | |
| 644 void Window::MoveCursorTo(const gfx::Point& point_in_window) { | |
| 645 Window* root_window = GetRootWindow(); | |
| 646 DCHECK(root_window); | |
| 647 gfx::Point point_in_root(point_in_window); | |
| 648 ConvertPointToTarget(this, root_window, &point_in_root); | |
| 649 root_window->GetHost()->MoveCursorTo(point_in_root); | |
| 650 } | |
| 651 | |
| 652 gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const { | |
| 653 return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor; | |
| 654 } | |
| 655 | |
| 656 void Window::AddObserver(WindowObserver* observer) { | |
| 657 observer->OnObservingWindow(this); | |
| 658 observers_.AddObserver(observer); | |
| 659 } | |
| 660 | |
| 661 void Window::RemoveObserver(WindowObserver* observer) { | |
| 662 observer->OnUnobservingWindow(this); | |
| 663 observers_.RemoveObserver(observer); | |
| 664 } | |
| 665 | |
| 666 bool Window::HasObserver(WindowObserver* observer) { | |
| 667 return observers_.HasObserver(observer); | |
| 668 } | |
| 669 | |
| 670 bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const { | |
| 671 const Window* root_window = GetRootWindow(); | |
| 672 if (!root_window) | |
| 673 return false; | |
| 674 gfx::Point local_point(point_in_root); | |
| 675 ConvertPointToTarget(root_window, this, &local_point); | |
| 676 return gfx::Rect(GetTargetBounds().size()).Contains(local_point); | |
| 677 } | |
| 678 | |
| 679 bool Window::ContainsPoint(const gfx::Point& local_point) const { | |
| 680 return gfx::Rect(bounds().size()).Contains(local_point); | |
| 681 } | |
| 682 | |
| 683 Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) { | |
| 684 return GetWindowForPoint(local_point, true, true); | |
| 685 } | |
| 686 | |
| 687 Window* Window::GetTopWindowContainingPoint(const gfx::Point& local_point) { | |
| 688 return GetWindowForPoint(local_point, false, false); | |
| 689 } | |
| 690 | |
| 691 Window* Window::GetToplevelWindow() { | |
| 692 Window* topmost_window_with_delegate = NULL; | |
| 693 for (aura::Window* window = this; window != NULL; window = window->parent()) { | |
| 694 if (window->delegate()) | |
| 695 topmost_window_with_delegate = window; | |
| 696 } | |
| 697 return topmost_window_with_delegate; | |
| 698 } | |
| 699 | |
| 700 void Window::Focus() { | |
| 701 client::FocusClient* client = client::GetFocusClient(this); | |
| 702 DCHECK(client); | |
| 703 client->FocusWindow(this); | |
| 704 } | |
| 705 | |
| 706 void Window::Blur() { | |
| 707 client::FocusClient* client = client::GetFocusClient(this); | |
| 708 DCHECK(client); | |
| 709 client->FocusWindow(NULL); | |
| 710 } | |
| 711 | |
| 712 bool Window::HasFocus() const { | |
| 713 client::FocusClient* client = client::GetFocusClient(this); | |
| 714 return client && client->GetFocusedWindow() == this; | |
| 715 } | |
| 716 | |
| 717 bool Window::CanFocus() const { | |
| 718 if (IsRootWindow()) | |
| 719 return IsVisible(); | |
| 720 | |
| 721 // NOTE: as part of focusing the window the ActivationClient may make the | |
| 722 // window visible (by way of making a hidden ancestor visible). For this | |
| 723 // reason we can't check visibility here and assume the client is doing it. | |
| 724 if (!parent_ || (delegate_ && !delegate_->CanFocus())) | |
| 725 return false; | |
| 726 | |
| 727 // The client may forbid certain windows from receiving focus at a given point | |
| 728 // in time. | |
| 729 client::EventClient* client = client::GetEventClient(GetRootWindow()); | |
| 730 if (client && !client->CanProcessEventsWithinSubtree(this)) | |
| 731 return false; | |
| 732 | |
| 733 return parent_->CanFocus(); | |
| 734 } | |
| 735 | |
| 736 bool Window::CanReceiveEvents() const { | |
| 737 if (IsRootWindow()) | |
| 738 return IsVisible(); | |
| 739 | |
| 740 // The client may forbid certain windows from receiving events at a given | |
| 741 // point in time. | |
| 742 client::EventClient* client = client::GetEventClient(GetRootWindow()); | |
| 743 if (client && !client->CanProcessEventsWithinSubtree(this)) | |
| 744 return false; | |
| 745 | |
| 746 return parent_ && IsVisible() && parent_->CanReceiveEvents(); | |
| 747 } | |
| 748 | |
| 749 void Window::SetCapture() { | |
| 750 if (!IsVisible()) | |
| 751 return; | |
| 752 | |
| 753 Window* root_window = GetRootWindow(); | |
| 754 if (!root_window) | |
| 755 return; | |
| 756 client::CaptureClient* capture_client = client::GetCaptureClient(root_window); | |
| 757 if (!capture_client) | |
| 758 return; | |
| 759 client::GetCaptureClient(root_window)->SetCapture(this); | |
| 760 } | |
| 761 | |
| 762 void Window::ReleaseCapture() { | |
| 763 Window* root_window = GetRootWindow(); | |
| 764 if (!root_window) | |
| 765 return; | |
| 766 client::CaptureClient* capture_client = client::GetCaptureClient(root_window); | |
| 767 if (!capture_client) | |
| 768 return; | |
| 769 client::GetCaptureClient(root_window)->ReleaseCapture(this); | |
| 770 } | |
| 771 | |
| 772 bool Window::HasCapture() { | |
| 773 Window* root_window = GetRootWindow(); | |
| 774 if (!root_window) | |
| 775 return false; | |
| 776 client::CaptureClient* capture_client = client::GetCaptureClient(root_window); | |
| 777 return capture_client && capture_client->GetCaptureWindow() == this; | |
| 778 } | |
| 779 | |
| 780 void Window::SuppressPaint() { | |
| 781 if (layer()) | |
| 782 layer()->SuppressPaint(); | |
| 783 } | |
| 784 | |
| 785 // {Set,Get,Clear}Property are implemented in window_property.h. | |
| 786 | |
| 787 void Window::SetNativeWindowProperty(const char* key, void* value) { | |
| 788 SetPropertyInternal( | |
| 789 key, key, NULL, reinterpret_cast<int64>(value), 0); | |
| 790 } | |
| 791 | |
| 792 void* Window::GetNativeWindowProperty(const char* key) const { | |
| 793 return reinterpret_cast<void*>(GetPropertyInternal(key, 0)); | |
| 794 } | |
| 795 | |
| 796 void Window::OnDeviceScaleFactorChanged(float device_scale_factor) { | |
| 797 ScopedCursorHider hider(this); | |
| 798 if (delegate_) | |
| 799 delegate_->OnDeviceScaleFactorChanged(device_scale_factor); | |
| 800 } | |
| 801 | |
| 802 #if !defined(NDEBUG) | |
| 803 std::string Window::GetDebugInfo() const { | |
| 804 return base::StringPrintf( | |
| 805 "%s<%d> bounds(%d, %d, %d, %d) %s %s opacity=%.1f", | |
| 806 name().empty() ? "Unknown" : name().c_str(), id(), | |
| 807 bounds().x(), bounds().y(), bounds().width(), bounds().height(), | |
| 808 visible_ ? "WindowVisible" : "WindowHidden", | |
| 809 layer() ? | |
| 810 (layer()->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") : | |
| 811 "NoLayer", | |
| 812 layer() ? layer()->opacity() : 1.0f); | |
| 813 } | |
| 814 | |
| 815 void Window::PrintWindowHierarchy(int depth) const { | |
| 816 VLOG(0) << base::StringPrintf( | |
| 817 "%*s%s", depth * 2, "", GetDebugInfo().c_str()); | |
| 818 for (Windows::const_iterator it = children_.begin(); | |
| 819 it != children_.end(); ++it) { | |
| 820 Window* child = *it; | |
| 821 child->PrintWindowHierarchy(depth + 1); | |
| 822 } | |
| 823 } | |
| 824 #endif | |
| 825 | |
| 826 void Window::RemoveOrDestroyChildren() { | |
| 827 while (!children_.empty()) { | |
| 828 Window* child = children_[0]; | |
| 829 if (child->owned_by_parent_) { | |
| 830 delete child; | |
| 831 // Deleting the child so remove it from out children_ list. | |
| 832 DCHECK(std::find(children_.begin(), children_.end(), child) == | |
| 833 children_.end()); | |
| 834 } else { | |
| 835 // Even if we can't delete the child, we still need to remove it from the | |
| 836 // parent so that relevant bookkeeping (parent_ back-pointers etc) are | |
| 837 // updated. | |
| 838 RemoveChild(child); | |
| 839 } | |
| 840 } | |
| 841 } | |
| 842 | |
| 843 /////////////////////////////////////////////////////////////////////////////// | |
| 844 // Window, private: | |
| 845 | |
| 846 int64 Window::SetPropertyInternal(const void* key, | |
| 847 const char* name, | |
| 848 PropertyDeallocator deallocator, | |
| 849 int64 value, | |
| 850 int64 default_value) { | |
| 851 int64 old = GetPropertyInternal(key, default_value); | |
| 852 if (value == default_value) { | |
| 853 prop_map_.erase(key); | |
| 854 } else { | |
| 855 Value prop_value; | |
| 856 prop_value.name = name; | |
| 857 prop_value.value = value; | |
| 858 prop_value.deallocator = deallocator; | |
| 859 prop_map_[key] = prop_value; | |
| 860 } | |
| 861 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 862 OnWindowPropertyChanged(this, key, old)); | |
| 863 return old; | |
| 864 } | |
| 865 | |
| 866 int64 Window::GetPropertyInternal(const void* key, | |
| 867 int64 default_value) const { | |
| 868 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); | |
| 869 if (iter == prop_map_.end()) | |
| 870 return default_value; | |
| 871 return iter->second.value; | |
| 872 } | |
| 873 | |
| 874 bool Window::HitTest(const gfx::Point& local_point) { | |
| 875 gfx::Rect local_bounds(bounds().size()); | |
| 876 if (!delegate_ || !delegate_->HasHitTestMask()) | |
| 877 return local_bounds.Contains(local_point); | |
| 878 | |
| 879 gfx::Path mask; | |
| 880 delegate_->GetHitTestMask(&mask); | |
| 881 | |
| 882 SkRegion clip_region; | |
| 883 clip_region.setRect(local_bounds.x(), local_bounds.y(), | |
| 884 local_bounds.width(), local_bounds.height()); | |
| 885 SkRegion mask_region; | |
| 886 return mask_region.setPath(mask, clip_region) && | |
| 887 mask_region.contains(local_point.x(), local_point.y()); | |
| 888 } | |
| 889 | |
| 890 void Window::SetBoundsInternal(const gfx::Rect& new_bounds) { | |
| 891 gfx::Rect actual_new_bounds(new_bounds); | |
| 892 gfx::Rect old_bounds = GetTargetBounds(); | |
| 893 | |
| 894 // Always need to set the layer's bounds -- even if it is to the same thing. | |
| 895 // This may cause important side effects such as stopping animation. | |
| 896 if (!layer()) { | |
| 897 const gfx::Vector2d origin_delta = new_bounds.OffsetFromOrigin() - | |
| 898 bounds_.OffsetFromOrigin(); | |
| 899 bounds_ = new_bounds; | |
| 900 OffsetLayerBounds(origin_delta); | |
| 901 } else { | |
| 902 if (parent_ && !parent_->layer()) { | |
| 903 gfx::Vector2d offset; | |
| 904 const aura::Window* ancestor_with_layer = | |
| 905 parent_->GetAncestorWithLayer(&offset); | |
| 906 if (ancestor_with_layer) | |
| 907 actual_new_bounds.Offset(offset); | |
| 908 } | |
| 909 layer()->SetBounds(actual_new_bounds); | |
| 910 } | |
| 911 | |
| 912 // If we are currently not the layer's delegate, we will not get bounds | |
| 913 // changed notification from the layer (this typically happens after animating | |
| 914 // hidden). We must notify ourselves. | |
| 915 if (!layer() || layer()->delegate() != this) | |
| 916 OnWindowBoundsChanged(old_bounds); | |
| 917 } | |
| 918 | |
| 919 void Window::SetVisible(bool visible) { | |
| 920 if ((layer() && visible == layer()->GetTargetVisibility()) || | |
| 921 (!layer() && visible == visible_)) | |
| 922 return; // No change. | |
| 923 | |
| 924 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 925 OnWindowVisibilityChanging(this, visible)); | |
| 926 | |
| 927 client::VisibilityClient* visibility_client = | |
| 928 client::GetVisibilityClient(this); | |
| 929 if (visibility_client) | |
| 930 visibility_client->UpdateLayerVisibility(this, visible); | |
| 931 else if (layer()) | |
| 932 layer()->SetVisible(visible); | |
| 933 visible_ = visible; | |
| 934 SchedulePaint(); | |
| 935 if (parent_ && parent_->layout_manager_) | |
| 936 parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible); | |
| 937 | |
| 938 if (delegate_) | |
| 939 delegate_->OnWindowTargetVisibilityChanged(visible); | |
| 940 | |
| 941 NotifyWindowVisibilityChanged(this, visible); | |
| 942 } | |
| 943 | |
| 944 void Window::SchedulePaint() { | |
| 945 SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height())); | |
| 946 } | |
| 947 | |
| 948 void Window::Paint(gfx::Canvas* canvas) { | |
| 949 if (delegate_) | |
| 950 delegate_->OnPaint(canvas); | |
| 951 PaintLayerlessChildren(canvas); | |
| 952 } | |
| 953 | |
| 954 void Window::PaintLayerlessChildren(gfx::Canvas* canvas) { | |
| 955 for (size_t i = 0, count = children_.size(); i < count; ++i) { | |
| 956 Window* child = children_[i]; | |
| 957 if (!child->layer() && child->visible_) { | |
| 958 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 959 canvas->ClipRect(child->bounds()); | |
| 960 if (!canvas->IsClipEmpty()) { | |
| 961 canvas->Translate(child->bounds().OffsetFromOrigin()); | |
| 962 child->Paint(canvas); | |
| 963 } | |
| 964 } | |
| 965 } | |
| 966 } | |
| 967 | |
| 968 Window* Window::GetWindowForPoint(const gfx::Point& local_point, | |
| 969 bool return_tightest, | |
| 970 bool for_event_handling) { | |
| 971 if (!IsVisible()) | |
| 972 return NULL; | |
| 973 | |
| 974 if ((for_event_handling && !HitTest(local_point)) || | |
| 975 (!for_event_handling && !ContainsPoint(local_point))) | |
| 976 return NULL; | |
| 977 | |
| 978 // Check if I should claim this event and not pass it to my children because | |
| 979 // the location is inside my hit test override area. For details, see | |
| 980 // set_hit_test_bounds_override_inner(). | |
| 981 if (for_event_handling && !hit_test_bounds_override_inner_.empty()) { | |
| 982 gfx::Rect inset_local_bounds(gfx::Point(), bounds().size()); | |
| 983 inset_local_bounds.Inset(hit_test_bounds_override_inner_); | |
| 984 // We know we're inside the normal local bounds, so if we're outside the | |
| 985 // inset bounds we must be in the special hit test override area. | |
| 986 DCHECK(HitTest(local_point)); | |
| 987 if (!inset_local_bounds.Contains(local_point)) | |
| 988 return delegate_ ? this : NULL; | |
| 989 } | |
| 990 | |
| 991 if (!return_tightest && delegate_) | |
| 992 return this; | |
| 993 | |
| 994 for (Windows::const_reverse_iterator it = children_.rbegin(), | |
| 995 rend = children_.rend(); | |
| 996 it != rend; ++it) { | |
| 997 Window* child = *it; | |
| 998 | |
| 999 if (for_event_handling) { | |
| 1000 if (child->ignore_events_) | |
| 1001 continue; | |
| 1002 // The client may not allow events to be processed by certain subtrees. | |
| 1003 client::EventClient* client = client::GetEventClient(GetRootWindow()); | |
| 1004 if (client && !client->CanProcessEventsWithinSubtree(child)) | |
| 1005 continue; | |
| 1006 if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling( | |
| 1007 child, local_point)) | |
| 1008 continue; | |
| 1009 } | |
| 1010 | |
| 1011 gfx::Point point_in_child_coords(local_point); | |
| 1012 ConvertPointToTarget(this, child, &point_in_child_coords); | |
| 1013 Window* match = child->GetWindowForPoint(point_in_child_coords, | |
| 1014 return_tightest, | |
| 1015 for_event_handling); | |
| 1016 if (match) | |
| 1017 return match; | |
| 1018 } | |
| 1019 | |
| 1020 return delegate_ ? this : NULL; | |
| 1021 } | |
| 1022 | |
| 1023 void Window::RemoveChildImpl(Window* child, Window* new_parent) { | |
| 1024 if (layout_manager_) | |
| 1025 layout_manager_->OnWillRemoveWindowFromLayout(child); | |
| 1026 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child)); | |
| 1027 Window* root_window = child->GetRootWindow(); | |
| 1028 Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL; | |
| 1029 if (root_window && root_window != new_root_window) | |
| 1030 child->NotifyRemovingFromRootWindow(new_root_window); | |
| 1031 | |
| 1032 gfx::Vector2d offset; | |
| 1033 GetAncestorWithLayer(&offset); | |
| 1034 child->UnparentLayers(!layer(), offset); | |
| 1035 child->parent_ = NULL; | |
| 1036 Windows::iterator i = std::find(children_.begin(), children_.end(), child); | |
| 1037 DCHECK(i != children_.end()); | |
| 1038 children_.erase(i); | |
| 1039 child->OnParentChanged(); | |
| 1040 if (layout_manager_) | |
| 1041 layout_manager_->OnWindowRemovedFromLayout(child); | |
| 1042 } | |
| 1043 | |
| 1044 void Window::UnparentLayers(bool has_layerless_ancestor, | |
| 1045 const gfx::Vector2d& offset) { | |
| 1046 if (!layer()) { | |
| 1047 const gfx::Vector2d new_offset = offset + bounds().OffsetFromOrigin(); | |
| 1048 for (size_t i = 0; i < children_.size(); ++i) { | |
| 1049 children_[i]->UnparentLayers(true, new_offset); | |
| 1050 } | |
| 1051 } else { | |
| 1052 // Only remove the layer if we still own it. Someone else may have acquired | |
| 1053 // ownership of it via AcquireLayer() and may expect the hierarchy to go | |
| 1054 // unchanged as the Window is destroyed. | |
| 1055 if (OwnsLayer()) { | |
| 1056 if (layer()->parent()) | |
| 1057 layer()->parent()->Remove(layer()); | |
| 1058 if (has_layerless_ancestor) { | |
| 1059 const gfx::Rect real_bounds(bounds_); | |
| 1060 gfx::Rect layer_bounds(layer()->bounds()); | |
| 1061 layer_bounds.Offset(-offset); | |
| 1062 layer()->SetBounds(layer_bounds); | |
| 1063 bounds_ = real_bounds; | |
| 1064 } | |
| 1065 } | |
| 1066 } | |
| 1067 } | |
| 1068 | |
| 1069 void Window::ReparentLayers(ui::Layer* parent_layer, | |
| 1070 const gfx::Vector2d& offset) { | |
| 1071 if (!layer()) { | |
| 1072 for (size_t i = 0; i < children_.size(); ++i) { | |
| 1073 children_[i]->ReparentLayers( | |
| 1074 parent_layer, | |
| 1075 offset + children_[i]->bounds().OffsetFromOrigin()); | |
| 1076 } | |
| 1077 } else { | |
| 1078 const gfx::Rect real_bounds(bounds()); | |
| 1079 parent_layer->Add(layer()); | |
| 1080 gfx::Rect layer_bounds(layer()->bounds().size()); | |
| 1081 layer_bounds += offset; | |
| 1082 layer()->SetBounds(layer_bounds); | |
| 1083 bounds_ = real_bounds; | |
| 1084 } | |
| 1085 } | |
| 1086 | |
| 1087 void Window::OffsetLayerBounds(const gfx::Vector2d& offset) { | |
| 1088 if (!layer()) { | |
| 1089 for (size_t i = 0; i < children_.size(); ++i) | |
| 1090 children_[i]->OffsetLayerBounds(offset); | |
| 1091 } else { | |
| 1092 gfx::Rect layer_bounds(layer()->bounds()); | |
| 1093 layer_bounds += offset; | |
| 1094 layer()->SetBounds(layer_bounds); | |
| 1095 } | |
| 1096 } | |
| 1097 | |
| 1098 void Window::OnParentChanged() { | |
| 1099 FOR_EACH_OBSERVER( | |
| 1100 WindowObserver, observers_, OnWindowParentChanged(this, parent_)); | |
| 1101 } | |
| 1102 | |
| 1103 void Window::StackChildRelativeTo(Window* child, | |
| 1104 Window* target, | |
| 1105 StackDirection direction) { | |
| 1106 DCHECK_NE(child, target); | |
| 1107 DCHECK(child); | |
| 1108 DCHECK(target); | |
| 1109 DCHECK_EQ(this, child->parent()); | |
| 1110 DCHECK_EQ(this, target->parent()); | |
| 1111 | |
| 1112 client::WindowStackingClient* stacking_client = | |
| 1113 client::GetWindowStackingClient(); | |
| 1114 if (stacking_client && | |
| 1115 !stacking_client->AdjustStacking(&child, &target, &direction)) | |
| 1116 return; | |
| 1117 | |
| 1118 const size_t child_i = | |
| 1119 std::find(children_.begin(), children_.end(), child) - children_.begin(); | |
| 1120 const size_t target_i = | |
| 1121 std::find(children_.begin(), children_.end(), target) - children_.begin(); | |
| 1122 | |
| 1123 // Don't move the child if it is already in the right place. | |
| 1124 if ((direction == STACK_ABOVE && child_i == target_i + 1) || | |
| 1125 (direction == STACK_BELOW && child_i + 1 == target_i)) | |
| 1126 return; | |
| 1127 | |
| 1128 const size_t dest_i = | |
| 1129 direction == STACK_ABOVE ? | |
| 1130 (child_i < target_i ? target_i : target_i + 1) : | |
| 1131 (child_i < target_i ? target_i - 1 : target_i); | |
| 1132 children_.erase(children_.begin() + child_i); | |
| 1133 children_.insert(children_.begin() + dest_i, child); | |
| 1134 | |
| 1135 StackChildLayerRelativeTo(child, target, direction); | |
| 1136 | |
| 1137 child->OnStackingChanged(); | |
| 1138 } | |
| 1139 | |
| 1140 void Window::StackChildLayerRelativeTo(Window* child, | |
| 1141 Window* target, | |
| 1142 StackDirection direction) { | |
| 1143 Window* ancestor_with_layer = GetAncestorWithLayer(NULL); | |
| 1144 ui::Layer* ancestor_layer = | |
| 1145 ancestor_with_layer ? ancestor_with_layer->layer() : NULL; | |
| 1146 if (!ancestor_layer) | |
| 1147 return; | |
| 1148 | |
| 1149 if (child->layer() && target->layer()) { | |
| 1150 if (direction == STACK_ABOVE) | |
| 1151 ancestor_layer->StackAbove(child->layer(), target->layer()); | |
| 1152 else | |
| 1153 ancestor_layer->StackBelow(child->layer(), target->layer()); | |
| 1154 return; | |
| 1155 } | |
| 1156 typedef std::vector<ui::Layer*> Layers; | |
| 1157 Layers layers; | |
| 1158 GetLayersToStack(child, &layers); | |
| 1159 if (layers.empty()) | |
| 1160 return; | |
| 1161 | |
| 1162 ui::Layer* target_layer; | |
| 1163 if (direction == STACK_ABOVE) { | |
| 1164 target_layer = | |
| 1165 FindStackingTargetLayer<Windows::const_reverse_iterator>(target, child); | |
| 1166 } else { | |
| 1167 target_layer = | |
| 1168 FindStackingTargetLayer<Windows::const_iterator>(target, child); | |
| 1169 } | |
| 1170 | |
| 1171 if (!target_layer) { | |
| 1172 if (direction == STACK_ABOVE) { | |
| 1173 for (Layers::const_reverse_iterator i = layers.rbegin(), | |
| 1174 rend = layers.rend(); i != rend; ++i) { | |
| 1175 ancestor_layer->StackAtBottom(*i); | |
| 1176 } | |
| 1177 } else { | |
| 1178 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i) | |
| 1179 ancestor_layer->StackAtTop(*i); | |
| 1180 } | |
| 1181 return; | |
| 1182 } | |
| 1183 | |
| 1184 if (direction == STACK_ABOVE) { | |
| 1185 for (Layers::const_reverse_iterator i = layers.rbegin(), | |
| 1186 rend = layers.rend(); i != rend; ++i) { | |
| 1187 ancestor_layer->StackAbove(*i, target_layer); | |
| 1188 } | |
| 1189 } else { | |
| 1190 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i) | |
| 1191 ancestor_layer->StackBelow(*i, target_layer); | |
| 1192 } | |
| 1193 } | |
| 1194 | |
| 1195 void Window::OnStackingChanged() { | |
| 1196 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this)); | |
| 1197 } | |
| 1198 | |
| 1199 void Window::NotifyRemovingFromRootWindow(Window* new_root) { | |
| 1200 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1201 OnWindowRemovingFromRootWindow(this, new_root)); | |
| 1202 for (Window::Windows::const_iterator it = children_.begin(); | |
| 1203 it != children_.end(); ++it) { | |
| 1204 (*it)->NotifyRemovingFromRootWindow(new_root); | |
| 1205 } | |
| 1206 } | |
| 1207 | |
| 1208 void Window::NotifyAddedToRootWindow() { | |
| 1209 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1210 OnWindowAddedToRootWindow(this)); | |
| 1211 for (Window::Windows::const_iterator it = children_.begin(); | |
| 1212 it != children_.end(); ++it) { | |
| 1213 (*it)->NotifyAddedToRootWindow(); | |
| 1214 } | |
| 1215 } | |
| 1216 | |
| 1217 void Window::NotifyWindowHierarchyChange( | |
| 1218 const WindowObserver::HierarchyChangeParams& params) { | |
| 1219 params.target->NotifyWindowHierarchyChangeDown(params); | |
| 1220 switch (params.phase) { | |
| 1221 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING: | |
| 1222 if (params.old_parent) | |
| 1223 params.old_parent->NotifyWindowHierarchyChangeUp(params); | |
| 1224 break; | |
| 1225 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED: | |
| 1226 if (params.new_parent) | |
| 1227 params.new_parent->NotifyWindowHierarchyChangeUp(params); | |
| 1228 break; | |
| 1229 default: | |
| 1230 NOTREACHED(); | |
| 1231 break; | |
| 1232 } | |
| 1233 } | |
| 1234 | |
| 1235 void Window::NotifyWindowHierarchyChangeDown( | |
| 1236 const WindowObserver::HierarchyChangeParams& params) { | |
| 1237 NotifyWindowHierarchyChangeAtReceiver(params); | |
| 1238 for (Window::Windows::const_iterator it = children_.begin(); | |
| 1239 it != children_.end(); ++it) { | |
| 1240 (*it)->NotifyWindowHierarchyChangeDown(params); | |
| 1241 } | |
| 1242 } | |
| 1243 | |
| 1244 void Window::NotifyWindowHierarchyChangeUp( | |
| 1245 const WindowObserver::HierarchyChangeParams& params) { | |
| 1246 for (Window* window = this; window; window = window->parent()) | |
| 1247 window->NotifyWindowHierarchyChangeAtReceiver(params); | |
| 1248 } | |
| 1249 | |
| 1250 void Window::NotifyWindowHierarchyChangeAtReceiver( | |
| 1251 const WindowObserver::HierarchyChangeParams& params) { | |
| 1252 WindowObserver::HierarchyChangeParams local_params = params; | |
| 1253 local_params.receiver = this; | |
| 1254 | |
| 1255 switch (params.phase) { | |
| 1256 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING: | |
| 1257 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1258 OnWindowHierarchyChanging(local_params)); | |
| 1259 break; | |
| 1260 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED: | |
| 1261 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1262 OnWindowHierarchyChanged(local_params)); | |
| 1263 break; | |
| 1264 default: | |
| 1265 NOTREACHED(); | |
| 1266 break; | |
| 1267 } | |
| 1268 } | |
| 1269 | |
| 1270 void Window::NotifyWindowVisibilityChanged(aura::Window* target, | |
| 1271 bool visible) { | |
| 1272 if (!NotifyWindowVisibilityChangedDown(target, visible)) { | |
| 1273 return; // |this| has been deleted. | |
| 1274 } | |
| 1275 NotifyWindowVisibilityChangedUp(target, visible); | |
| 1276 } | |
| 1277 | |
| 1278 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target, | |
| 1279 bool visible) { | |
| 1280 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one | |
| 1281 // of the observers. We create an local observer for that. In that case we | |
| 1282 // exit without further access to any members. | |
| 1283 WindowTracker tracker; | |
| 1284 tracker.Add(this); | |
| 1285 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1286 OnWindowVisibilityChanged(target, visible)); | |
| 1287 return tracker.Contains(this); | |
| 1288 } | |
| 1289 | |
| 1290 bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target, | |
| 1291 bool visible) { | |
| 1292 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible)) | |
| 1293 return false; // |this| was deleted. | |
| 1294 std::set<const Window*> child_already_processed; | |
| 1295 bool child_destroyed = false; | |
| 1296 do { | |
| 1297 child_destroyed = false; | |
| 1298 for (Window::Windows::const_iterator it = children_.begin(); | |
| 1299 it != children_.end(); ++it) { | |
| 1300 if (!child_already_processed.insert(*it).second) | |
| 1301 continue; | |
| 1302 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) { | |
| 1303 // |*it| was deleted, |it| is invalid and |children_| has changed. | |
| 1304 // We exit the current for-loop and enter a new one. | |
| 1305 child_destroyed = true; | |
| 1306 break; | |
| 1307 } | |
| 1308 } | |
| 1309 } while (child_destroyed); | |
| 1310 return true; | |
| 1311 } | |
| 1312 | |
| 1313 void Window::NotifyWindowVisibilityChangedUp(aura::Window* target, | |
| 1314 bool visible) { | |
| 1315 // Start with the parent as we already notified |this| | |
| 1316 // in NotifyWindowVisibilityChangedDown. | |
| 1317 for (Window* window = parent(); window; window = window->parent()) { | |
| 1318 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible); | |
| 1319 DCHECK(ret); | |
| 1320 } | |
| 1321 } | |
| 1322 | |
| 1323 void Window::NotifyAncestorWindowTransformed(Window* source) { | |
| 1324 FOR_EACH_OBSERVER(WindowObserver, observers_, | |
| 1325 OnAncestorWindowTransformed(source, this)); | |
| 1326 for (Window::Windows::const_iterator it = children_.begin(); | |
| 1327 it != children_.end(); ++it) { | |
| 1328 (*it)->NotifyAncestorWindowTransformed(source); | |
| 1329 } | |
| 1330 } | |
| 1331 | |
| 1332 void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds) { | |
| 1333 if (layer()) { | |
| 1334 bounds_ = layer()->bounds(); | |
| 1335 if (parent_ && !parent_->layer()) { | |
| 1336 gfx::Vector2d offset; | |
| 1337 aura::Window* ancestor_with_layer = | |
| 1338 parent_->GetAncestorWithLayer(&offset); | |
| 1339 if (ancestor_with_layer) | |
| 1340 bounds_.Offset(-offset); | |
| 1341 } | |
| 1342 } | |
| 1343 | |
| 1344 if (layout_manager_) | |
| 1345 layout_manager_->OnWindowResized(); | |
| 1346 if (delegate_) | |
| 1347 delegate_->OnBoundsChanged(old_bounds, bounds()); | |
| 1348 FOR_EACH_OBSERVER(WindowObserver, | |
| 1349 observers_, | |
| 1350 OnWindowBoundsChanged(this, old_bounds, bounds())); | |
| 1351 } | |
| 1352 | |
| 1353 bool Window::CleanupGestureState() { | |
| 1354 bool state_modified = false; | |
| 1355 state_modified |= ui::GestureRecognizer::Get()->CancelActiveTouches(this); | |
| 1356 state_modified |= | |
| 1357 ui::GestureRecognizer::Get()->CleanupStateForConsumer(this); | |
| 1358 for (Window::Windows::iterator iter = children_.begin(); | |
| 1359 iter != children_.end(); | |
| 1360 ++iter) { | |
| 1361 state_modified |= (*iter)->CleanupGestureState(); | |
| 1362 } | |
| 1363 return state_modified; | |
| 1364 } | |
| 1365 | |
| 1366 void Window::OnPaintLayer(gfx::Canvas* canvas) { | |
| 1367 Paint(canvas); | |
| 1368 } | |
| 1369 | |
| 1370 void Window::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) { | |
| 1371 DCHECK(layer()); | |
| 1372 FOR_EACH_OBSERVER(WindowObserver, | |
| 1373 observers_, | |
| 1374 OnDelegatedFrameDamage(this, damage_rect_in_dip)); | |
| 1375 } | |
| 1376 | |
| 1377 base::Closure Window::PrepareForLayerBoundsChange() { | |
| 1378 return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this), | |
| 1379 bounds()); | |
| 1380 } | |
| 1381 | |
| 1382 bool Window::CanAcceptEvent(const ui::Event& event) { | |
| 1383 // The client may forbid certain windows from receiving events at a given | |
| 1384 // point in time. | |
| 1385 client::EventClient* client = client::GetEventClient(GetRootWindow()); | |
| 1386 if (client && !client->CanProcessEventsWithinSubtree(this)) | |
| 1387 return false; | |
| 1388 | |
| 1389 // We need to make sure that a touch cancel event and any gesture events it | |
| 1390 // creates can always reach the window. This ensures that we receive a valid | |
| 1391 // touch / gesture stream. | |
| 1392 if (event.IsEndingEvent()) | |
| 1393 return true; | |
| 1394 | |
| 1395 if (!IsVisible()) | |
| 1396 return false; | |
| 1397 | |
| 1398 // The top-most window can always process an event. | |
| 1399 if (!parent_) | |
| 1400 return true; | |
| 1401 | |
| 1402 // For located events (i.e. mouse, touch etc.), an assumption is made that | |
| 1403 // windows that don't have a default event-handler cannot process the event | |
| 1404 // (see more in GetWindowForPoint()). This assumption is not made for key | |
| 1405 // events. | |
| 1406 return event.IsKeyEvent() || target_handler(); | |
| 1407 } | |
| 1408 | |
| 1409 ui::EventTarget* Window::GetParentTarget() { | |
| 1410 if (IsRootWindow()) { | |
| 1411 return client::GetEventClient(this) ? | |
| 1412 client::GetEventClient(this)->GetToplevelEventTarget() : | |
| 1413 Env::GetInstance(); | |
| 1414 } | |
| 1415 return parent_; | |
| 1416 } | |
| 1417 | |
| 1418 scoped_ptr<ui::EventTargetIterator> Window::GetChildIterator() { | |
| 1419 return scoped_ptr<ui::EventTargetIterator>( | |
| 1420 new ui::EventTargetIteratorImpl<Window>(children())); | |
| 1421 } | |
| 1422 | |
| 1423 ui::EventTargeter* Window::GetEventTargeter() { | |
| 1424 return targeter_.get(); | |
| 1425 } | |
| 1426 | |
| 1427 void Window::ConvertEventToTarget(ui::EventTarget* target, | |
| 1428 ui::LocatedEvent* event) { | |
| 1429 event->ConvertLocationToTarget(this, | |
| 1430 static_cast<Window*>(target)); | |
| 1431 } | |
| 1432 | |
| 1433 void Window::UpdateLayerName() { | |
| 1434 #if !defined(NDEBUG) | |
| 1435 DCHECK(layer()); | |
| 1436 | |
| 1437 std::string layer_name(name_); | |
| 1438 if (layer_name.empty()) | |
| 1439 layer_name = "Unnamed Window"; | |
| 1440 | |
| 1441 if (id_ != -1) | |
| 1442 layer_name += " " + base::IntToString(id_); | |
| 1443 | |
| 1444 layer()->set_name(layer_name); | |
| 1445 #endif | |
| 1446 } | |
| 1447 | |
| 1448 bool Window::ContainsMouse() { | |
| 1449 bool contains_mouse = false; | |
| 1450 if (IsVisible()) { | |
| 1451 WindowTreeHost* host = GetHost(); | |
| 1452 contains_mouse = host && | |
| 1453 ContainsPointInRoot(host->dispatcher()->GetLastMouseLocationInRoot()); | |
| 1454 } | |
| 1455 return contains_mouse; | |
| 1456 } | |
| 1457 | |
| 1458 const Window* Window::GetAncestorWithLayer(gfx::Vector2d* offset) const { | |
| 1459 for (const aura::Window* window = this; window; window = window->parent()) { | |
| 1460 if (window->layer()) | |
| 1461 return window; | |
| 1462 if (offset) | |
| 1463 *offset += window->bounds().OffsetFromOrigin(); | |
| 1464 } | |
| 1465 if (offset) | |
| 1466 *offset = gfx::Vector2d(); | |
| 1467 return NULL; | |
| 1468 } | |
| 1469 | |
| 1470 } // namespace aura | |
| OLD | NEW |