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