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