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"
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"
36 Window::Window(WindowDelegate
* delegate
)
38 type_(client::WINDOW_TYPE_UNKNOWN
),
39 owned_by_parent_(true),
42 transient_parent_(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_
);
56 // layer_ can be NULL if Init() wasn't invoked, which can happen
59 layer_
->SuppressPaint();
61 // Let the delegate know we're in the processing of destroying.
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();
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
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.
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
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.
93 delegate_
->OnWindowDestroyed();
94 FOR_EACH_OBSERVER(WindowObserver
, observers_
, OnWindowDestroyed(this));
97 for (std::map
<const void*, Value
>::const_iterator iter
= prop_map_
.begin();
98 iter
!= prop_map_
.end();
100 if (iter
->second
.deallocator
)
101 (*iter
->second
.deallocator
)(iter
->second
.value
);
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.
109 layer_
->set_delegate(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();
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());
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();
155 ui::Layer
* child
= *it
;
161 void Window::SetType(client::WindowType type
) {
162 // Cannot change type after the window is initialized.
167 void Window::SetName(const std::string
& name
) {
171 UpdateLayerName(name_
);
174 void Window::SetTransparent(bool transparent
) {
175 transparent_
= transparent
;
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)->
194 const WindowEventDispatcher
* Window::GetDispatcher() const {
195 const Window
* root_window
= GetRootWindow();
196 return root_window
? root_window
->dispatcher_
: NULL
;
199 void Window::Show() {
203 void Window::Hide() {
204 for (Windows::iterator it
= transient_children_
.begin();
205 it
!= transient_children_
.end(); ++it
) {
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
224 if (!GetRootWindow())
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();
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
);
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
);
252 dispatcher
->OnWindowTransformed(this, contained_mouse
);
255 void Window::SetLayoutManager(LayoutManager
* layout_manager
) {
256 if (layout_manager
== layout_manager_
)
258 layout_manager_
.reset(layout_manager
);
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();
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
);
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();
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
);
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
)) {
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
) ==
337 child
->parent()->RemoveChildImpl(child
, this);
338 child
->parent_
= this;
340 layer_
->Add(child
->layer_
);
342 children_
.push_back(child
);
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_
) {
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
)
411 const Window
* result
= (*i
)->GetChildById(id
);
419 void Window::ConvertPointToTarget(const Window
* source
,
420 const Window
* target
,
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
);
433 ui::Layer::ConvertPointToLayer(source
->layer(), target
->layer(), point
);
437 void Window::MoveCursorTo(const gfx::Point
& point_in_window
) {
438 Window
* root_window
= GetRootWindow();
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
) {
451 RemovePreTargetHandler(event_filter_
.get());
452 event_filter_
.reset(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();
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
);
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);
524 client
->FocusWindow(this);
527 void Window::Blur() {
528 client::FocusClient
* client
= client::GetFocusClient(this);
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()))
545 // The client may forbid certain windows from receiving focus at a given point
547 client::EventClient
* client
= client::GetEventClient(GetRootWindow());
548 if (client
&& !client
->CanProcessEventsWithinSubtree(this))
551 return parent_
->CanFocus();
554 bool Window::CanReceiveEvents() const {
555 // The client may forbid certain windows from receiving events at a given
557 client::EventClient
* client
= client::GetEventClient(GetRootWindow());
558 if (client
&& !client
->CanProcessEventsWithinSubtree(this))
561 return parent_
&& IsVisible() && parent_
->CanReceiveEvents();
564 void Window::SetCapture() {
568 Window
* root_window
= GetRootWindow();
571 client::GetCaptureClient(root_window
)->SetCapture(this);
574 void Window::ReleaseCapture() {
575 Window
* root_window
= GetRootWindow();
578 client::GetCaptureClient(root_window
)->ReleaseCapture(this);
581 bool Window::HasCapture() {
582 Window
* root_window
= GetRootWindow();
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
) {
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
) {
606 delegate_
->OnDeviceScaleFactorChanged(device_scale_factor
);
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",
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
) {
625 child
->PrintWindowHierarchy(depth
+ 1);
630 void Window::RemoveOrDestroyChildren() {
631 while (!children_
.empty()) {
632 Window
* child
= children_
[0];
633 if (child
->owned_by_parent_
) {
635 // Deleting the child so remove it from out children_ list.
636 DCHECK(std::find(children_
.begin(), children_
.end(), child
) ==
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
647 ///////////////////////////////////////////////////////////////////////////////
650 int64
Window::SetPropertyInternal(const void* key
,
652 PropertyDeallocator deallocator
,
654 int64 default_value
) {
655 int64 old
= GetPropertyInternal(key
, default_value
);
656 if (value
== default_value
) {
657 prop_map_
.erase(key
);
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
));
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.
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();
712 dispatcher
->DispatchMouseExitToHidingWindow(this);
714 client::VisibilityClient
* visibility_client
=
715 client::GetVisibilityClient(this);
716 if (visibility_client
)
717 visibility_client
->UpdateLayerVisibility(this, visible
);
719 layer_
->SetVisible(visible
);
722 if (parent_
&& parent_
->layout_manager_
)
723 parent_
->layout_manager_
->OnChildWindowVisibilityChanged(this, visible
);
726 delegate_
->OnWindowTargetVisibilityChanged(visible
);
728 NotifyWindowVisibilityChanged(this, visible
);
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
) {
744 if ((for_event_handling
&& !HitTest(local_point
)) ||
745 (!for_event_handling
&& !ContainsPoint(local_point
)))
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_
)
764 for (Windows::const_reverse_iterator it
= children_
.rbegin(),
765 rend
= children_
.rend();
769 if (for_event_handling
) {
770 if (child
->ignore_events_
)
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
))
776 if (delegate_
&& !delegate_
->ShouldDescendIntoChildForEventHandling(
777 child
, local_point
)) {
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
,
791 return delegate_
? this : NULL
;
794 void Window::RemoveChildImpl(Window
* child
, Window
* new_parent
) {
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());
814 child
->OnParentChanged();
816 layout_manager_
->OnWindowRemovedFromLayout(child
);
819 void Window::OnParentChanged() {
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 {
838 // Assemble chains of ancestors of both windows.
841 if (!GetAllTransientAncestors(*window1
, &ancestors1
) ||
842 !GetAllTransientAncestors(*window2
, &ancestors2
)) {
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
) {
857 bool Window::HasTransientAncestor(const Window
* ancestor
) const {
858 if (transient_parent_
== ancestor
)
860 return transient_parent_
?
861 transient_parent_
->HasTransientAncestor(ancestor
) : false;
864 void Window::StackChildRelativeTo(Window
* child
,
866 StackDirection direction
) {
867 DCHECK_NE(child
, 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
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
)) {
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
) {
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
)
908 // Don't try to stack a child above itself.
909 if (child
== final_target
)
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
,
932 StackDirection direction
) {
933 DCHECK_NE(child
, 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
))
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());
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
);
994 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
:
995 if (params
.new_parent
)
996 params
.new_parent
->NotifyWindowHierarchyChangeUp(params
);
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
));
1029 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
:
1030 FOR_EACH_OBSERVER(WindowObserver
, observers_
,
1031 OnWindowHierarchyChanged(local_params
));
1039 void Window::NotifyWindowVisibilityChanged(aura::Window
* target
,
1041 if (!NotifyWindowVisibilityChangedDown(target
, visible
)) {
1042 return; // |this| has been deleted.
1044 NotifyWindowVisibilityChangedUp(target
, visible
);
1047 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window
* target
,
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
;
1054 FOR_EACH_OBSERVER(WindowObserver
, observers_
,
1055 OnWindowVisibilityChanged(target
, visible
));
1056 return tracker
.Contains(this);
1059 bool Window::NotifyWindowVisibilityChangedDown(aura::Window
* target
,
1061 if (!NotifyWindowVisibilityChangedAtReceiver(target
, visible
))
1062 return false; // |this| was deleted.
1063 std::set
<const Window
*> child_already_processed
;
1064 bool child_destroyed
= false;
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
)
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;
1078 } while (child_destroyed
);
1082 void Window::NotifyWindowVisibilityChangedUp(aura::Window
* target
,
1084 for (Window
* window
= this; window
; window
= window
->parent()) {
1085 bool ret
= window
->NotifyWindowVisibilityChangedAtReceiver(target
, visible
);
1090 void Window::OnLayerBoundsChanged(const gfx::Rect
& old_bounds
,
1091 bool contained_mouse
) {
1092 if (layout_manager_
)
1093 layout_manager_
->OnWindowResized();
1095 delegate_
->OnBoundsChanged(old_bounds
, bounds());
1096 FOR_EACH_OBSERVER(WindowObserver
,
1098 OnWindowBoundsChanged(this, old_bounds
, bounds()));
1099 WindowEventDispatcher
* dispatcher
= GetDispatcher();
1101 dispatcher
->OnWindowBoundsChanged(this, contained_mouse
);
1104 void Window::OnPaintLayer(gfx::Canvas
* canvas
) {
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
1117 client::EventClient
* client
= client::GetEventClient(GetRootWindow());
1118 if (client
&& !client
->CanProcessEventsWithinSubtree(this))
1121 bool visible
= event
.dispatch_to_hidden_targets() || IsVisible();
1122 return visible
&& (!parent_
|| parent_
->CanAcceptEvent(event
));
1125 ui::EventTarget
* Window::GetParentTarget() {
1129 void Window::UpdateLayerName(const std::string
& name
) {
1130 #if !defined(NDEBUG)
1133 std::string
layer_name(name_
);
1134 if (layer_name
.empty())
1135 layer_name
.append("Unnamed Window");
1139 base::snprintf(id_buf
, sizeof(id_buf
), " %d", id_
);
1140 layer_name
.append(id_buf
);
1142 layer()->set_name(layer_name
);
1146 bool Window::ContainsMouse() {
1147 bool contains_mouse
= false;
1149 WindowEventDispatcher
* dispatcher
= GetDispatcher();
1150 contains_mouse
= dispatcher
&&
1151 ContainsPointInRoot(dispatcher
->GetLastMouseLocationInRoot());
1153 return contains_mouse
;