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/stl_util.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/event_client.h" 18 #include "ui/aura/client/screen_position_client.h" 19 #include "ui/aura/client/stacking_client.h" 20 #include "ui/aura/client/visibility_client.h" 21 #include "ui/aura/env.h" 22 #include "ui/aura/focus_manager.h" 23 #include "ui/aura/layout_manager.h" 24 #include "ui/aura/root_window.h" 25 #include "ui/aura/window_delegate.h" 26 #include "ui/aura/window_observer.h" 27 #include "ui/aura/window_tracker.h" 28 #include "ui/base/animation/multi_animation.h" 29 #include "ui/compositor/compositor.h" 30 #include "ui/compositor/layer.h" 31 #include "ui/gfx/canvas.h" 32 #include "ui/gfx/path.h" 33 #include "ui/gfx/screen.h" 34 35 namespace aura { 36 37 namespace { 38 39 void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory, 40 unsigned sync_point, bool lost_resource) { 41 // NOTE: shared_memory will get released when we go out of scope. 42 } 43 44 } // namespace 45 46 Window::Window(WindowDelegate* delegate) 47 : type_(client::WINDOW_TYPE_UNKNOWN), 48 owned_by_parent_(true), 49 delegate_(delegate), 50 parent_(NULL), 51 transient_parent_(NULL), 52 visible_(false), 53 id_(-1), 54 transparent_(false), 55 user_data_(NULL), 56 ignore_events_(false), 57 // Don't notify newly added observers during notification. This causes 58 // problems for code that adds an observer as part of an observer 59 // notification (such as the workspace code). 60 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) { 61 set_target_handler(delegate_); 62 } 63 64 Window::~Window() { 65 // layer_ can be NULL if Init() wasn't invoked, which can happen 66 // only in tests. 67 if (layer_) 68 layer_->SuppressPaint(); 69 70 // Let the delegate know we're in the processing of destroying. 71 if (delegate_) 72 delegate_->OnWindowDestroying(); 73 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this)); 74 75 // Let the root know so that it can remove any references to us. 76 RootWindow* root_window = GetRootWindow(); 77 if (root_window) 78 root_window->OnWindowDestroying(this); 79 80 // Then destroy the children. 81 while (!children_.empty()) { 82 Window* child = children_[0]; 83 if (child->owned_by_parent_) { 84 delete child; 85 // Deleting the child so remove it from out children_ list. 86 DCHECK(std::find(children_.begin(), children_.end(), child) == 87 children_.end()); 88 } else { 89 // Even if we can't delete the child, we still need to remove it from the 90 // parent so that relevant bookkeeping (parent_ back-pointers etc) are 91 // updated. 92 RemoveChild(child); 93 } 94 } 95 96 // Removes ourselves from our transient parent (if it hasn't been done by the 97 // RootWindow). 98 if (transient_parent_) 99 transient_parent_->RemoveTransientChild(this); 100 101 // The window needs to be removed from the parent before calling the 102 // WindowDestroyed callbacks of delegate and the observers. 103 if (parent_) 104 parent_->RemoveChild(this); 105 106 // And let the delegate do any post cleanup. 107 // TODO(beng): Figure out if this notification needs to happen here, or if it 108 // can be moved down adjacent to the observer notification. If it has to be 109 // done here, the reason why should be documented. 110 if (delegate_) 111 delegate_->OnWindowDestroyed(); 112 113 // Destroy transient children, only after we've removed ourselves from our 114 // parent, as destroying an active transient child may otherwise attempt to 115 // refocus us. 116 Windows transient_children(transient_children_); 117 STLDeleteElements(&transient_children); 118 DCHECK(transient_children_.empty()); 119 120 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroyed(this)); 121 122 // Clear properties. 123 for (std::map<const void*, Value>::const_iterator iter = prop_map_.begin(); 124 iter != prop_map_.end(); 125 ++iter) { 126 if (iter->second.deallocator) 127 (*iter->second.deallocator)(iter->second.value); 128 } 129 prop_map_.clear(); 130 131 // If we have layer it will either be destroyed by layer_owner_'s dtor, or by 132 // whoever acquired it. We don't have a layer if Init() wasn't invoked, which 133 // can happen in tests. 134 if (layer_) 135 layer_->set_delegate(NULL); 136 layer_ = NULL; 137 } 138 139 void Window::Init(ui::LayerType layer_type) { 140 layer_ = new ui::Layer(layer_type); 141 layer_owner_.reset(layer_); 142 layer_->SetVisible(false); 143 layer_->set_delegate(this); 144 UpdateLayerName(name_); 145 layer_->SetFillsBoundsOpaquely(!transparent_); 146 147 Env::GetInstance()->NotifyWindowInitialized(this); 148 } 149 150 ui::Layer* Window::RecreateLayer() { 151 // Disconnect the old layer, but don't delete it. 152 ui::Layer* old_layer = AcquireLayer(); 153 if (!old_layer) 154 return NULL; 155 156 old_layer->set_delegate(NULL); 157 float mailbox_scale_factor; 158 cc::TextureMailbox old_mailbox = 159 old_layer->GetTextureMailbox(&mailbox_scale_factor); 160 scoped_refptr<ui::Texture> old_texture = old_layer->external_texture(); 161 if (delegate_ && old_texture.get()) 162 old_layer->SetExternalTexture(delegate_->CopyTexture().get()); 163 164 layer_ = new ui::Layer(old_layer->type()); 165 layer_owner_.reset(layer_); 166 layer_->SetVisible(old_layer->visible()); 167 layer_->set_scale_content(old_layer->scale_content()); 168 layer_->set_delegate(this); 169 layer_->SetMasksToBounds(old_layer->GetMasksToBounds()); 170 // Move the original texture to the new layer if the old layer has a 171 // texture and we could copy it into the old layer, 172 // crbug.com/175211. 173 if (delegate_ && old_texture.get()) { 174 layer_->SetExternalTexture(old_texture.get()); 175 } else if (old_mailbox.IsSharedMemory()) { 176 base::SharedMemory* old_buffer = old_mailbox.shared_memory(); 177 const size_t size = old_mailbox.shared_memory_size_in_bytes(); 178 179 scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory); 180 new_buffer->CreateAndMapAnonymous(size); 181 182 if (old_buffer->memory() && new_buffer->memory()) { 183 memcpy(new_buffer->memory(), old_buffer->memory(), size); 184 base::SharedMemory* new_buffer_raw_ptr = new_buffer.get(); 185 cc::TextureMailbox::ReleaseCallback callback = 186 base::Bind(MailboxReleaseCallback, Passed(&new_buffer)); 187 cc::TextureMailbox new_mailbox(new_buffer_raw_ptr, 188 old_mailbox.shared_memory_size(), 189 callback); 190 layer_->SetTextureMailbox(new_mailbox, mailbox_scale_factor); 191 } 192 } 193 194 UpdateLayerName(name_); 195 layer_->SetFillsBoundsOpaquely(!transparent_); 196 // Install new layer as a sibling of the old layer, stacked below it. 197 if (old_layer->parent()) { 198 old_layer->parent()->Add(layer_); 199 old_layer->parent()->StackBelow(layer_, old_layer); 200 } 201 // Migrate all the child layers over to the new layer. Copy the list because 202 // the items are removed during iteration. 203 std::vector<ui::Layer*> children_copy = old_layer->children(); 204 for (std::vector<ui::Layer*>::const_iterator it = children_copy.begin(); 205 it != children_copy.end(); 206 ++it) { 207 ui::Layer* child = *it; 208 layer_->Add(child); 209 } 210 return old_layer; 211 } 212 213 void Window::SetType(client::WindowType type) { 214 // Cannot change type after the window is initialized. 215 DCHECK(!layer()); 216 type_ = type; 217 } 218 219 void Window::SetName(const std::string& name) { 220 name_ = name; 221 222 if (layer()) 223 UpdateLayerName(name_); 224 } 225 226 void Window::SetTransparent(bool transparent) { 227 // Cannot change transparent flag after the window is initialized. 228 DCHECK(!layer()); 229 transparent_ = transparent; 230 } 231 232 RootWindow* Window::GetRootWindow() { 233 return const_cast<RootWindow*>( 234 static_cast<const Window*>(this)->GetRootWindow()); 235 } 236 237 const RootWindow* Window::GetRootWindow() const { 238 return parent_ ? parent_->GetRootWindow() : NULL; 239 } 240 241 void Window::Show() { 242 SetVisible(true); 243 } 244 245 void Window::Hide() { 246 for (Windows::iterator it = transient_children_.begin(); 247 it != transient_children_.end(); ++it) { 248 (*it)->Hide(); 249 } 250 SetVisible(false); 251 ReleaseCapture(); 252 } 253 254 bool Window::IsVisible() const { 255 // Layer visibility can be inconsistent with window visibility, for example 256 // when a Window is hidden, we want this function to return false immediately 257 // after, even though the client may decide to animate the hide effect (and 258 // so the layer will be visible for some time after Hide() is called). 259 return visible_ && layer_ && layer_->IsDrawn(); 260 } 261 262 gfx::Rect Window::GetBoundsInRootWindow() const { 263 // TODO(beng): There may be a better way to handle this, and the existing code 264 // is likely wrong anyway in a multi-display world, but this will 265 // do for now. 266 if (!GetRootWindow()) 267 return bounds(); 268 gfx::Point origin = bounds().origin(); 269 ConvertPointToTarget(parent_, GetRootWindow(), &origin); 270 return gfx::Rect(origin, bounds().size()); 271 } 272 273 gfx::Rect Window::GetBoundsInScreen() const { 274 gfx::Rect bounds(GetBoundsInRootWindow()); 275 const RootWindow* root = GetRootWindow(); 276 if (root) { 277 aura::client::ScreenPositionClient* screen_position_client = 278 aura::client::GetScreenPositionClient(root); 279 if (screen_position_client) { 280 gfx::Point origin = bounds.origin(); 281 screen_position_client->ConvertPointToScreen(root, &origin); 282 bounds.set_origin(origin); 283 } 284 } 285 return bounds; 286 } 287 288 void Window::SetTransform(const gfx::Transform& transform) { 289 RootWindow* root_window = GetRootWindow(); 290 bool contained_mouse = IsVisible() && root_window && 291 ContainsPointInRoot(root_window->GetLastMouseLocationInRoot()); 292 layer()->SetTransform(transform); 293 if (root_window) 294 root_window->OnWindowTransformed(this, contained_mouse); 295 } 296 297 void Window::SetLayoutManager(LayoutManager* layout_manager) { 298 if (layout_manager == layout_manager_) 299 return; 300 layout_manager_.reset(layout_manager); 301 if (!layout_manager) 302 return; 303 // If we're changing to a new layout manager, ensure it is aware of all the 304 // existing child windows. 305 for (Windows::const_iterator it = children_.begin(); 306 it != children_.end(); 307 ++it) 308 layout_manager_->OnWindowAddedToLayout(*it); 309 } 310 311 void Window::SetBounds(const gfx::Rect& new_bounds) { 312 if (parent_ && parent_->layout_manager()) 313 parent_->layout_manager()->SetChildBounds(this, new_bounds); 314 else 315 SetBoundsInternal(new_bounds); 316 } 317 318 void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen, 319 const gfx::Display& dst_display) { 320 RootWindow* root = GetRootWindow(); 321 if (root) { 322 gfx::Point origin = new_bounds_in_screen.origin(); 323 aura::client::ScreenPositionClient* screen_position_client = 324 aura::client::GetScreenPositionClient(root); 325 screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display); 326 return; 327 } 328 SetBounds(new_bounds_in_screen); 329 } 330 331 gfx::Rect Window::GetTargetBounds() const { 332 return layer_->GetTargetBounds(); 333 } 334 335 const gfx::Rect& Window::bounds() const { 336 return layer_->bounds(); 337 } 338 339 void Window::SchedulePaintInRect(const gfx::Rect& rect) { 340 if (layer_->SchedulePaint(rect)) { 341 FOR_EACH_OBSERVER( 342 WindowObserver, observers_, OnWindowPaintScheduled(this, rect)); 343 } 344 } 345 346 void Window::SetDefaultParentByRootWindow(RootWindow* root_window, 347 const gfx::Rect& bounds_in_screen) { 348 DCHECK(root_window); 349 350 // Stacking clients are mandatory on RootWindow objects. 351 client::StackingClient* client = client::GetStackingClient(root_window); 352 DCHECK(client); 353 354 aura::Window* default_parent = client->GetDefaultParent( 355 root_window, this, bounds_in_screen); 356 default_parent->AddChild(this); 357 } 358 359 void Window::StackChildAtTop(Window* child) { 360 if (children_.size() <= 1 || child == children_.back()) 361 return; // In the front already. 362 StackChildAbove(child, children_.back()); 363 } 364 365 void Window::StackChildAbove(Window* child, Window* target) { 366 StackChildRelativeTo(child, target, STACK_ABOVE); 367 } 368 369 void Window::StackChildAtBottom(Window* child) { 370 if (children_.size() <= 1 || child == children_.front()) 371 return; // At the bottom already. 372 StackChildBelow(child, children_.front()); 373 } 374 375 void Window::StackChildBelow(Window* child, Window* target) { 376 StackChildRelativeTo(child, target, STACK_BELOW); 377 } 378 379 void Window::AddChild(Window* child) { 380 WindowObserver::HierarchyChangeParams params; 381 params.target = child; 382 params.new_parent = this; 383 params.old_parent = child->parent(); 384 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 385 NotifyWindowHierarchyChange(params); 386 387 RootWindow* old_root = child->GetRootWindow(); 388 389 DCHECK(std::find(children_.begin(), children_.end(), child) == 390 children_.end()); 391 if (child->parent()) 392 child->parent()->RemoveChildImpl(child, this); 393 child->parent_ = this; 394 395 layer_->Add(child->layer_); 396 397 children_.push_back(child); 398 if (layout_manager_) 399 layout_manager_->OnWindowAddedToLayout(child); 400 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child)); 401 child->OnParentChanged(); 402 403 RootWindow* root_window = GetRootWindow(); 404 if (root_window && old_root != root_window) { 405 root_window->OnWindowAddedToRootWindow(child); 406 child->NotifyAddedToRootWindow(); 407 } 408 409 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 410 NotifyWindowHierarchyChange(params); 411 } 412 413 void Window::RemoveChild(Window* child) { 414 WindowObserver::HierarchyChangeParams params; 415 params.target = child; 416 params.new_parent = NULL; 417 params.old_parent = this; 418 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 419 NotifyWindowHierarchyChange(params); 420 421 RemoveChildImpl(child, NULL); 422 423 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 424 NotifyWindowHierarchyChange(params); 425 } 426 427 bool Window::Contains(const Window* other) const { 428 for (const Window* parent = other; parent; parent = parent->parent_) { 429 if (parent == this) 430 return true; 431 } 432 return false; 433 } 434 435 void Window::AddTransientChild(Window* child) { 436 if (child->transient_parent_) 437 child->transient_parent_->RemoveTransientChild(child); 438 DCHECK(std::find(transient_children_.begin(), transient_children_.end(), 439 child) == transient_children_.end()); 440 transient_children_.push_back(child); 441 child->transient_parent_ = this; 442 FOR_EACH_OBSERVER(WindowObserver, observers_, 443 OnAddTransientChild(this, child)); 444 } 445 446 void Window::RemoveTransientChild(Window* child) { 447 Windows::iterator i = 448 std::find(transient_children_.begin(), transient_children_.end(), child); 449 DCHECK(i != transient_children_.end()); 450 transient_children_.erase(i); 451 if (child->transient_parent_ == this) 452 child->transient_parent_ = NULL; 453 FOR_EACH_OBSERVER(WindowObserver, observers_, 454 OnRemoveTransientChild(this, child)); 455 } 456 457 Window* Window::GetChildById(int id) { 458 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id)); 459 } 460 461 const Window* Window::GetChildById(int id) const { 462 Windows::const_iterator i; 463 for (i = children_.begin(); i != children_.end(); ++i) { 464 if ((*i)->id() == id) 465 return *i; 466 const Window* result = (*i)->GetChildById(id); 467 if (result) 468 return result; 469 } 470 return NULL; 471 } 472 473 // static 474 void Window::ConvertPointToTarget(const Window* source, 475 const Window* target, 476 gfx::Point* point) { 477 if (!source) 478 return; 479 if (source->GetRootWindow() != target->GetRootWindow()) { 480 client::ScreenPositionClient* source_client = 481 GetScreenPositionClient(source->GetRootWindow()); 482 source_client->ConvertPointToScreen(source, point); 483 484 client::ScreenPositionClient* target_client = 485 GetScreenPositionClient(target->GetRootWindow()); 486 target_client->ConvertPointFromScreen(target, point); 487 } else { 488 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point); 489 } 490 } 491 492 void Window::MoveCursorTo(const gfx::Point& point_in_window) { 493 RootWindow* root_window = GetRootWindow(); 494 DCHECK(root_window); 495 gfx::Point point_in_root(point_in_window); 496 ConvertPointToTarget(this, root_window, &point_in_root); 497 root_window->MoveCursorTo(point_in_root); 498 } 499 500 gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const { 501 return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor; 502 } 503 504 void Window::SetEventFilter(ui::EventHandler* event_filter) { 505 if (event_filter_) 506 RemovePreTargetHandler(event_filter_.get()); 507 event_filter_.reset(event_filter); 508 if (event_filter) 509 AddPreTargetHandler(event_filter); 510 } 511 512 void Window::AddObserver(WindowObserver* observer) { 513 observers_.AddObserver(observer); 514 } 515 516 void Window::RemoveObserver(WindowObserver* observer) { 517 observers_.RemoveObserver(observer); 518 } 519 520 bool Window::HasObserver(WindowObserver* observer) { 521 return observers_.HasObserver(observer); 522 } 523 524 bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const { 525 const Window* root_window = GetRootWindow(); 526 if (!root_window) 527 return false; 528 gfx::Point local_point(point_in_root); 529 ConvertPointToTarget(root_window, this, &local_point); 530 return gfx::Rect(GetTargetBounds().size()).Contains(local_point); 531 } 532 533 bool Window::ContainsPoint(const gfx::Point& local_point) const { 534 return gfx::Rect(bounds().size()).Contains(local_point); 535 } 536 537 bool Window::HitTest(const gfx::Point& local_point) { 538 // Expand my bounds for hit testing (override is usually zero but it's 539 // probably cheaper to do the math every time than to branch). 540 gfx::Rect local_bounds(gfx::Point(), bounds().size()); 541 local_bounds.Inset(aura::Env::GetInstance()->is_touch_down() ? 542 hit_test_bounds_override_outer_touch_ : 543 hit_test_bounds_override_outer_mouse_); 544 545 if (!delegate_ || !delegate_->HasHitTestMask()) 546 return local_bounds.Contains(local_point); 547 548 gfx::Path mask; 549 delegate_->GetHitTestMask(&mask); 550 551 SkRegion clip_region; 552 clip_region.setRect(local_bounds.x(), local_bounds.y(), 553 local_bounds.width(), local_bounds.height()); 554 SkRegion mask_region; 555 return mask_region.setPath(mask, clip_region) && 556 mask_region.contains(local_point.x(), local_point.y()); 557 } 558 559 Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) { 560 return GetWindowForPoint(local_point, true, true); 561 } 562 563 Window* Window::GetTopWindowContainingPoint(const gfx::Point& local_point) { 564 return GetWindowForPoint(local_point, false, false); 565 } 566 567 Window* Window::GetToplevelWindow() { 568 Window* topmost_window_with_delegate = NULL; 569 for (aura::Window* window = this; window != NULL; window = window->parent()) { 570 if (window->delegate()) 571 topmost_window_with_delegate = window; 572 } 573 return topmost_window_with_delegate; 574 } 575 576 void Window::Focus() { 577 client::FocusClient* client = client::GetFocusClient(this); 578 DCHECK(client); 579 client->FocusWindow(this); 580 } 581 582 void Window::Blur() { 583 client::FocusClient* client = client::GetFocusClient(this); 584 DCHECK(client); 585 client->FocusWindow(NULL); 586 } 587 588 bool Window::HasFocus() const { 589 client::FocusClient* client = client::GetFocusClient(this); 590 return client && client->GetFocusedWindow() == this; 591 } 592 593 bool Window::CanFocus() const { 594 // NOTE: as part of focusing the window the ActivationClient may make the 595 // window visible (by way of making a hidden ancestor visible). For this 596 // reason we can't check visibility here and assume the client is doing it. 597 if (!parent_ || (delegate_ && !delegate_->CanFocus())) 598 return false; 599 600 // The client may forbid certain windows from receiving focus at a given point 601 // in time. 602 client::EventClient* client = client::GetEventClient(GetRootWindow()); 603 if (client && !client->CanProcessEventsWithinSubtree(this)) 604 return false; 605 606 return parent_->CanFocus(); 607 } 608 609 bool Window::CanReceiveEvents() const { 610 // The client may forbid certain windows from receiving events at a given 611 // point in time. 612 client::EventClient* client = client::GetEventClient(GetRootWindow()); 613 if (client && !client->CanProcessEventsWithinSubtree(this)) 614 return false; 615 616 return parent_ && IsVisible() && parent_->CanReceiveEvents(); 617 } 618 619 void Window::SetCapture() { 620 if (!IsVisible()) 621 return; 622 623 RootWindow* root_window = GetRootWindow(); 624 if (!root_window) 625 return; 626 client::GetCaptureClient(root_window)->SetCapture(this); 627 } 628 629 void Window::ReleaseCapture() { 630 RootWindow* root_window = GetRootWindow(); 631 if (!root_window) 632 return; 633 client::GetCaptureClient(root_window)->ReleaseCapture(this); 634 } 635 636 bool Window::HasCapture() { 637 RootWindow* root_window = GetRootWindow(); 638 return root_window && 639 client::GetCaptureClient(root_window)->GetCaptureWindow() == this; 640 } 641 642 void Window::SuppressPaint() { 643 layer_->SuppressPaint(); 644 } 645 646 // {Set,Get,Clear}Property are implemented in window_property.h. 647 648 void Window::SetNativeWindowProperty(const char* key, void* value) { 649 SetPropertyInternal( 650 key, key, NULL, reinterpret_cast<int64>(value), 0); 651 } 652 653 void* Window::GetNativeWindowProperty(const char* key) const { 654 return reinterpret_cast<void*>(GetPropertyInternal(key, 0)); 655 } 656 657 void Window::OnDeviceScaleFactorChanged(float device_scale_factor) { 658 if (delegate_) 659 delegate_->OnDeviceScaleFactorChanged(device_scale_factor); 660 } 661 662 #ifndef NDEBUG 663 std::string Window::GetDebugInfo() const { 664 return base::StringPrintf( 665 "%s<%d> bounds(%d, %d, %d, %d) %s %s opacity=%.1f", 666 name().empty() ? "Unknown" : name().c_str(), id(), 667 bounds().x(), bounds().y(), bounds().width(), bounds().height(), 668 visible_ ? "WindowVisible" : "WindowHidden", 669 layer_->GetTargetVisibility() ? "LayerVisible" : "LayerHidden", 670 layer_->opacity()); 671 } 672 673 void Window::PrintWindowHierarchy(int depth) const { 674 printf("%*s%s\n", depth * 2, "", GetDebugInfo().c_str()); 675 for (Windows::const_iterator it = children_.begin(); 676 it != children_.end(); ++it) { 677 Window* child = *it; 678 child->PrintWindowHierarchy(depth + 1); 679 } 680 } 681 #endif 682 683 /////////////////////////////////////////////////////////////////////////////// 684 // Window, private: 685 686 int64 Window::SetPropertyInternal(const void* key, 687 const char* name, 688 PropertyDeallocator deallocator, 689 int64 value, 690 int64 default_value) { 691 int64 old = GetPropertyInternal(key, default_value); 692 if (value == default_value) { 693 prop_map_.erase(key); 694 } else { 695 Value prop_value; 696 prop_value.name = name; 697 prop_value.value = value; 698 prop_value.deallocator = deallocator; 699 prop_map_[key] = prop_value; 700 } 701 FOR_EACH_OBSERVER(WindowObserver, observers_, 702 OnWindowPropertyChanged(this, key, old)); 703 return old; 704 } 705 706 int64 Window::GetPropertyInternal(const void* key, 707 int64 default_value) const { 708 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); 709 if (iter == prop_map_.end()) 710 return default_value; 711 return iter->second.value; 712 } 713 714 void Window::SetBoundsInternal(const gfx::Rect& new_bounds) { 715 gfx::Rect actual_new_bounds(new_bounds); 716 717 // Ensure we don't go smaller than our minimum bounds. 718 if (delegate_) { 719 const gfx::Size& min_size = delegate_->GetMinimumSize(); 720 actual_new_bounds.set_width( 721 std::max(min_size.width(), actual_new_bounds.width())); 722 actual_new_bounds.set_height( 723 std::max(min_size.height(), actual_new_bounds.height())); 724 } 725 726 gfx::Rect old_bounds = GetTargetBounds(); 727 728 // Always need to set the layer's bounds -- even if it is to the same thing. 729 // This may cause important side effects such as stopping animation. 730 layer_->SetBounds(actual_new_bounds); 731 732 // If we are currently not the layer's delegate, we will not get bounds 733 // changed notification from the layer (this typically happens after animating 734 // hidden). We must notify ourselves. 735 if (layer_->delegate() != this) 736 OnLayerBoundsChanged(old_bounds, ContainsMouse()); 737 } 738 739 void Window::SetVisible(bool visible) { 740 if (visible == layer_->GetTargetVisibility()) 741 return; // No change. 742 743 FOR_EACH_OBSERVER(WindowObserver, observers_, 744 OnWindowVisibilityChanging(this, visible)); 745 746 RootWindow* root_window = GetRootWindow(); 747 if (root_window) 748 root_window->DispatchMouseExitToHidingWindow(this); 749 750 client::VisibilityClient* visibility_client = 751 client::GetVisibilityClient(this); 752 if (visibility_client) 753 visibility_client->UpdateLayerVisibility(this, visible); 754 else 755 layer_->SetVisible(visible); 756 visible_ = visible; 757 SchedulePaint(); 758 if (parent_ && parent_->layout_manager_) 759 parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible); 760 761 if (delegate_) 762 delegate_->OnWindowTargetVisibilityChanged(visible); 763 764 NotifyWindowVisibilityChanged(this, visible); 765 766 if (root_window) 767 root_window->OnWindowVisibilityChanged(this, visible); 768 } 769 770 void Window::SchedulePaint() { 771 SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height())); 772 } 773 774 Window* Window::GetWindowForPoint(const gfx::Point& local_point, 775 bool return_tightest, 776 bool for_event_handling) { 777 if (!IsVisible()) 778 return NULL; 779 780 if ((for_event_handling && !HitTest(local_point)) || 781 (!for_event_handling && !ContainsPoint(local_point))) 782 return NULL; 783 784 // Check if I should claim this event and not pass it to my children because 785 // the location is inside my hit test override area. For details, see 786 // set_hit_test_bounds_override_inner(). 787 if (for_event_handling && !hit_test_bounds_override_inner_.empty()) { 788 gfx::Rect inset_local_bounds(gfx::Point(), bounds().size()); 789 inset_local_bounds.Inset(hit_test_bounds_override_inner_); 790 // We know we're inside the normal local bounds, so if we're outside the 791 // inset bounds we must be in the special hit test override area. 792 DCHECK(HitTest(local_point)); 793 if (!inset_local_bounds.Contains(local_point)) 794 return delegate_ ? this : NULL; 795 } 796 797 if (!return_tightest && delegate_) 798 return this; 799 800 for (Windows::const_reverse_iterator it = children_.rbegin(), 801 rend = children_.rend(); 802 it != rend; ++it) { 803 Window* child = *it; 804 805 if (for_event_handling) { 806 if (child->ignore_events_) 807 continue; 808 // The client may not allow events to be processed by certain subtrees. 809 client::EventClient* client = client::GetEventClient(GetRootWindow()); 810 if (client && !client->CanProcessEventsWithinSubtree(child)) 811 continue; 812 if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling( 813 child, local_point)) { 814 continue; 815 } 816 } 817 818 gfx::Point point_in_child_coords(local_point); 819 ConvertPointToTarget(this, child, &point_in_child_coords); 820 Window* match = child->GetWindowForPoint(point_in_child_coords, 821 return_tightest, 822 for_event_handling); 823 if (match) 824 return match; 825 } 826 827 return delegate_ ? this : NULL; 828 } 829 830 void Window::RemoveChildImpl(Window* child, Window* new_parent) { 831 if (layout_manager_) 832 layout_manager_->OnWillRemoveWindowFromLayout(child); 833 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child)); 834 RootWindow* root_window = child->GetRootWindow(); 835 RootWindow* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL; 836 if (root_window && root_window != new_root_window) { 837 root_window->OnWindowRemovedFromRootWindow(child, new_root_window); 838 child->NotifyRemovingFromRootWindow(); 839 } 840 child->parent_ = NULL; 841 // We should only remove the child's layer if the child still owns that layer. 842 // Someone else may have acquired ownership of it via AcquireLayer() and may 843 // expect the hierarchy to go unchanged as the Window is destroyed. 844 if (child->layer_owner_) 845 layer_->Remove(child->layer_); 846 Windows::iterator i = std::find(children_.begin(), children_.end(), child); 847 DCHECK(i != children_.end()); 848 children_.erase(i); 849 child->OnParentChanged(); 850 if (layout_manager_) 851 layout_manager_->OnWindowRemovedFromLayout(child); 852 } 853 854 void Window::OnParentChanged() { 855 FOR_EACH_OBSERVER( 856 WindowObserver, observers_, OnWindowParentChanged(this, parent_)); 857 } 858 859 void Window::StackChildRelativeTo(Window* child, 860 Window* target, 861 StackDirection direction) { 862 DCHECK_NE(child, target); 863 DCHECK(child); 864 DCHECK(target); 865 DCHECK_EQ(this, child->parent()); 866 DCHECK_EQ(this, target->parent()); 867 868 const size_t target_i = 869 std::find(children_.begin(), children_.end(), target) - children_.begin(); 870 871 // By convention we don't stack on top of windows with layers with NULL 872 // delegates. Walk backward to find a valid target window. 873 // See tests WindowTest.StackingMadrigal and StackOverClosingTransient 874 // for an explanation of this. 875 size_t final_target_i = target_i; 876 while (final_target_i > 0 && 877 children_[final_target_i]->layer()->delegate() == NULL) { 878 --final_target_i; 879 } 880 881 // Allow stacking immediately below a window with a NULL layer. 882 if (direction == STACK_BELOW && target_i != final_target_i) 883 direction = STACK_ABOVE; 884 885 Window* final_target = children_[final_target_i]; 886 887 // If we couldn't find a valid target position, don't move anything. 888 if (final_target->layer()->delegate() == NULL) 889 return; 890 891 // Don't try to stack a child above itself. 892 if (child == final_target) 893 return; 894 895 // Move the child and all its transients. 896 StackChildRelativeToImpl(child, final_target, direction); 897 } 898 899 void Window::StackChildRelativeToImpl(Window* child, 900 Window* target, 901 StackDirection direction) { 902 DCHECK_NE(child, target); 903 DCHECK(child); 904 DCHECK(target); 905 DCHECK_EQ(this, child->parent()); 906 DCHECK_EQ(this, target->parent()); 907 908 const size_t child_i = 909 std::find(children_.begin(), children_.end(), child) - children_.begin(); 910 const size_t target_i = 911 std::find(children_.begin(), children_.end(), target) - children_.begin(); 912 913 // Don't move the child if it is already in the right place. 914 if ((direction == STACK_ABOVE && child_i == target_i + 1) || 915 (direction == STACK_BELOW && child_i + 1 == target_i)) 916 return; 917 918 const size_t dest_i = 919 direction == STACK_ABOVE ? 920 (child_i < target_i ? target_i : target_i + 1) : 921 (child_i < target_i ? target_i - 1 : target_i); 922 children_.erase(children_.begin() + child_i); 923 children_.insert(children_.begin() + dest_i, child); 924 925 if (direction == STACK_ABOVE) 926 layer()->StackAbove(child->layer(), target->layer()); 927 else 928 layer()->StackBelow(child->layer(), target->layer()); 929 930 // Stack any transient children that share the same parent to be in front of 931 // 'child'. 932 Window* last_transient = child; 933 for (Windows::iterator it = child->transient_children_.begin(); 934 it != child->transient_children_.end(); ++it) { 935 Window* transient_child = *it; 936 if (transient_child->parent_ == this) { 937 StackChildRelativeToImpl(transient_child, last_transient, STACK_ABOVE); 938 last_transient = transient_child; 939 } 940 } 941 942 child->OnStackingChanged(); 943 } 944 945 void Window::OnStackingChanged() { 946 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this)); 947 } 948 949 void Window::NotifyRemovingFromRootWindow() { 950 FOR_EACH_OBSERVER(WindowObserver, observers_, 951 OnWindowRemovingFromRootWindow(this)); 952 for (Window::Windows::const_iterator it = children_.begin(); 953 it != children_.end(); ++it) { 954 (*it)->NotifyRemovingFromRootWindow(); 955 } 956 } 957 958 void Window::NotifyAddedToRootWindow() { 959 FOR_EACH_OBSERVER(WindowObserver, observers_, 960 OnWindowAddedToRootWindow(this)); 961 for (Window::Windows::const_iterator it = children_.begin(); 962 it != children_.end(); ++it) { 963 (*it)->NotifyAddedToRootWindow(); 964 } 965 } 966 967 void Window::NotifyWindowHierarchyChange( 968 const WindowObserver::HierarchyChangeParams& params) { 969 params.target->NotifyWindowHierarchyChangeDown(params); 970 switch (params.phase) { 971 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING: 972 if (params.old_parent) 973 params.old_parent->NotifyWindowHierarchyChangeUp(params); 974 break; 975 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED: 976 if (params.new_parent) 977 params.new_parent->NotifyWindowHierarchyChangeUp(params); 978 break; 979 default: 980 NOTREACHED(); 981 break; 982 } 983 } 984 985 void Window::NotifyWindowHierarchyChangeDown( 986 const WindowObserver::HierarchyChangeParams& params) { 987 NotifyWindowHierarchyChangeAtReceiver(params); 988 for (Window::Windows::const_iterator it = children_.begin(); 989 it != children_.end(); ++it) { 990 (*it)->NotifyWindowHierarchyChangeDown(params); 991 } 992 } 993 994 void Window::NotifyWindowHierarchyChangeUp( 995 const WindowObserver::HierarchyChangeParams& params) { 996 for (Window* window = this; window; window = window->parent()) 997 window->NotifyWindowHierarchyChangeAtReceiver(params); 998 } 999 1000 void Window::NotifyWindowHierarchyChangeAtReceiver( 1001 const WindowObserver::HierarchyChangeParams& params) { 1002 WindowObserver::HierarchyChangeParams local_params = params; 1003 local_params.receiver = this; 1004 1005 switch (params.phase) { 1006 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING: 1007 FOR_EACH_OBSERVER(WindowObserver, observers_, 1008 OnWindowHierarchyChanging(local_params)); 1009 break; 1010 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED: 1011 FOR_EACH_OBSERVER(WindowObserver, observers_, 1012 OnWindowHierarchyChanged(local_params)); 1013 break; 1014 default: 1015 NOTREACHED(); 1016 break; 1017 } 1018 } 1019 1020 void Window::NotifyWindowVisibilityChanged(aura::Window* target, 1021 bool visible) { 1022 if (!NotifyWindowVisibilityChangedDown(target, visible)) { 1023 return; // |this| has been deleted. 1024 } 1025 NotifyWindowVisibilityChangedUp(target, visible); 1026 } 1027 1028 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target, 1029 bool visible) { 1030 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one 1031 // of the observers. We create an local observer for that. In that case we 1032 // exit without further access to any members. 1033 WindowTracker tracker; 1034 tracker.Add(this); 1035 FOR_EACH_OBSERVER(WindowObserver, observers_, 1036 OnWindowVisibilityChanged(target, visible)); 1037 return tracker.Contains(this); 1038 } 1039 1040 bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target, 1041 bool visible) { 1042 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible)) 1043 return false; // |this| was deleted. 1044 std::set<const Window*> child_already_processed; 1045 bool child_destroyed = false; 1046 do { 1047 child_destroyed = false; 1048 for (Window::Windows::const_iterator it = children_.begin(); 1049 it != children_.end(); ++it) { 1050 if (!child_already_processed.insert(*it).second) 1051 continue; 1052 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) { 1053 // |*it| was deleted, |it| is invalid and |children_| has changed. 1054 // We exit the current for-loop and enter a new one. 1055 child_destroyed = true; 1056 break; 1057 } 1058 } 1059 } while (child_destroyed); 1060 return true; 1061 } 1062 1063 void Window::NotifyWindowVisibilityChangedUp(aura::Window* target, 1064 bool visible) { 1065 for (Window* window = this; window; window = window->parent()) { 1066 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible); 1067 DCHECK(ret); 1068 } 1069 } 1070 1071 void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds, 1072 bool contained_mouse) { 1073 if (layout_manager_) 1074 layout_manager_->OnWindowResized(); 1075 if (delegate_) 1076 delegate_->OnBoundsChanged(old_bounds, bounds()); 1077 FOR_EACH_OBSERVER(WindowObserver, 1078 observers_, 1079 OnWindowBoundsChanged(this, old_bounds, bounds())); 1080 RootWindow* root_window = GetRootWindow(); 1081 if (root_window) 1082 root_window->OnWindowBoundsChanged(this, contained_mouse); 1083 } 1084 1085 void Window::OnPaintLayer(gfx::Canvas* canvas) { 1086 if (delegate_) 1087 delegate_->OnPaint(canvas); 1088 } 1089 1090 base::Closure Window::PrepareForLayerBoundsChange() { 1091 return base::Bind(&Window::OnLayerBoundsChanged, base::Unretained(this), 1092 bounds(), ContainsMouse()); 1093 } 1094 1095 bool Window::CanAcceptEvent(const ui::Event& event) { 1096 // The client may forbid certain windows from receiving events at a given 1097 // point in time. 1098 client::EventClient* client = client::GetEventClient(GetRootWindow()); 1099 if (client && !client->CanProcessEventsWithinSubtree(this)) 1100 return false; 1101 1102 bool visible = event.dispatch_to_hidden_targets() || IsVisible(); 1103 return visible && (!parent_ || parent_->CanAcceptEvent(event)); 1104 } 1105 1106 ui::EventTarget* Window::GetParentTarget() { 1107 return parent_; 1108 } 1109 1110 void Window::UpdateLayerName(const std::string& name) { 1111 #if !defined(NDEBUG) 1112 DCHECK(layer()); 1113 1114 std::string layer_name(name_); 1115 if (layer_name.empty()) 1116 layer_name.append("Unnamed Window"); 1117 1118 if (id_ != -1) { 1119 char id_buf[10]; 1120 base::snprintf(id_buf, sizeof(id_buf), " %d", id_); 1121 layer_name.append(id_buf); 1122 } 1123 layer()->set_name(layer_name); 1124 #endif 1125 } 1126 1127 bool Window::ContainsMouse() { 1128 bool contains_mouse = false; 1129 if (IsVisible()) { 1130 RootWindow* root_window = GetRootWindow(); 1131 contains_mouse = root_window && 1132 ContainsPointInRoot(root_window->GetLastMouseLocationInRoot()); 1133 } 1134 return contains_mouse; 1135 } 1136 1137 } // namespace aura 1138