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