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/strings/string_number_conversions.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/cursor_client.h"
18 #include "ui/aura/client/event_client.h"
19 #include "ui/aura/client/focus_client.h"
20 #include "ui/aura/client/screen_position_client.h"
21 #include "ui/aura/client/visibility_client.h"
22 #include "ui/aura/client/window_stacking_client.h"
23 #include "ui/aura/env.h"
24 #include "ui/aura/layout_manager.h"
25 #include "ui/aura/window_delegate.h"
26 #include "ui/aura/window_event_dispatcher.h"
27 #include "ui/aura/window_observer.h"
28 #include "ui/aura/window_tracker.h"
29 #include "ui/aura/window_tree_host.h"
30 #include "ui/compositor/compositor.h"
31 #include "ui/compositor/layer.h"
32 #include "ui/events/event_target_iterator.h"
33 #include "ui/gfx/animation/multi_animation.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/path.h"
36 #include "ui/gfx/scoped_canvas.h"
37 #include "ui/gfx/screen.h"
43 ui::LayerType WindowLayerTypeToUILayerType(WindowLayerType window_layer_type) {
44 switch (window_layer_type) {
45 case WINDOW_LAYER_NONE:
47 case WINDOW_LAYER_NOT_DRAWN:
48 return ui::LAYER_NOT_DRAWN;
49 case WINDOW_LAYER_TEXTURED:
50 return ui::LAYER_TEXTURED;
51 case WINDOW_LAYER_SOLID_COLOR:
52 return ui::LAYER_SOLID_COLOR;
55 return ui::LAYER_NOT_DRAWN;
58 // Used when searching for a Window to stack relative to.
60 T IteratorForDirectionBegin(aura::Window* window);
63 Window::Windows::const_iterator IteratorForDirectionBegin(
64 aura::Window* window) {
65 return window->children().begin();
69 Window::Windows::const_reverse_iterator IteratorForDirectionBegin(
70 aura::Window* window) {
71 return window->children().rbegin();
75 T IteratorForDirectionEnd(aura::Window* window);
78 Window::Windows::const_iterator IteratorForDirectionEnd(aura::Window* window) {
79 return window->children().end();
83 Window::Windows::const_reverse_iterator IteratorForDirectionEnd(
84 aura::Window* window) {
85 return window->children().rend();
88 // Depth first search for the first Window with a layer to stack relative
89 // to. Starts at target. Does not descend into |ignore|.
91 ui::Layer* FindStackingTargetLayerDown(aura::Window* target,
92 aura::Window* ignore) {
97 return target->layer();
99 for (T i = IteratorForDirectionBegin<T>(target);
100 i != IteratorForDirectionEnd<T>(target); ++i) {
101 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore);
108 // Depth first search through the siblings of |target||. This does not search
109 // all the siblings, only those before/after |target| (depening upon the
110 // template type) and ignoring |ignore|. Returns the Layer of the first Window
111 // encountered with a Layer.
113 ui::Layer* FindStackingLayerInSiblings(aura::Window* target,
114 aura::Window* ignore) {
115 aura::Window* parent = target->parent();
116 for (T i = std::find(IteratorForDirectionBegin<T>(parent),
117 IteratorForDirectionEnd<T>(parent), target);
118 i != IteratorForDirectionEnd<T>(parent); ++i) {
119 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore);
126 // Returns the first Window that has a Layer. This does a depth first search
127 // through the descendants of |target| first, then ascends up doing a depth
128 // first search through siblings of all ancestors until a Layer is found or an
129 // ancestor with a layer is found. This is intended to locate a layer to stack
130 // other layers relative to.
132 ui::Layer* FindStackingTargetLayer(aura::Window* target, aura::Window* ignore) {
133 ui::Layer* result = FindStackingTargetLayerDown<T>(target, ignore);
136 while (target->parent()) {
137 ui::Layer* result = FindStackingLayerInSiblings<T>(target, ignore);
140 target = target->parent();
147 // Does a depth first search for all descendants of |child| that have layers.
148 // This stops at any descendants that have layers (and adds them to |layers|).
149 void GetLayersToStack(aura::Window* child, std::vector<ui::Layer*>* layers) {
150 if (child->layer()) {
151 layers->push_back(child->layer());
154 for (size_t i = 0; i < child->children().size(); ++i)
155 GetLayersToStack(child->children()[i], layers);
160 class ScopedCursorHider {
162 explicit ScopedCursorHider(Window* window)
165 if (!window_->IsRootWindow())
167 const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
168 Env::GetInstance()->last_mouse_location());
169 client::CursorClient* cursor_client = client::GetCursorClient(window_);
170 if (cursor_is_in_bounds && cursor_client &&
171 cursor_client->IsCursorVisible()) {
172 cursor_client->HideCursor();
176 ~ScopedCursorHider() {
177 if (!window_->IsRootWindow())
180 // Update the device scale factor of the cursor client only when the last
181 // mouse location is on this root window.
183 client::CursorClient* cursor_client = client::GetCursorClient(window_);
185 const gfx::Display& display =
186 gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(
188 cursor_client->SetDisplay(display);
189 cursor_client->ShowCursor();
198 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider);
201 Window::Window(WindowDelegate* delegate)
203 type_(ui::wm::WINDOW_TYPE_UNKNOWN),
204 owned_by_parent_(true),
211 ignore_events_(false),
212 // Don't notify newly added observers during notification. This causes
213 // problems for code that adds an observer as part of an observer
214 // notification (such as the workspace code).
215 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) {
216 set_target_handler(delegate_);
220 // |layer()| can be NULL during tests, or if this Window is layerless.
222 layer()->SuppressPaint();
224 // Let the delegate know we're in the processing of destroying.
226 delegate_->OnWindowDestroying(this);
227 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this));
229 // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
230 // necessary but unfortunately is right now due to ordering
231 // peculiarities. WED must be notified _after_ other observers
232 // are notified of pending teardown but before the hierarchy
233 // is actually torn down.
234 WindowTreeHost* host = GetHost();
236 host->dispatcher()->OnPostNotifiedWindowDestroying(this);
238 // Then destroy the children.
239 RemoveOrDestroyChildren();
241 // The window needs to be removed from the parent before calling the
242 // WindowDestroyed callbacks of delegate and the observers.
244 parent_->RemoveChild(this);
247 delegate_->OnWindowDestroyed(this);
248 ObserverListBase<WindowObserver>::Iterator iter(observers_);
249 WindowObserver* observer;
250 while ((observer = iter.GetNext())) {
251 RemoveObserver(observer);
252 observer->OnWindowDestroyed(this);
256 for (std::map<const void*, Value>::const_iterator iter = prop_map_.begin();
257 iter != prop_map_.end();
259 if (iter->second.deallocator)
260 (*iter->second.deallocator)(iter->second.value);
264 // If we have layer it will either be destroyed by |layer_owner_|'s dtor, or
265 // by whoever acquired it. We don't have a layer if Init() wasn't invoked or
268 layer()->set_delegate(NULL);
272 void Window::Init(WindowLayerType window_layer_type) {
273 if (window_layer_type != WINDOW_LAYER_NONE) {
274 SetLayer(new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type)));
275 layer()->SetVisible(false);
276 layer()->set_delegate(this);
278 layer()->SetFillsBoundsOpaquely(!transparent_);
281 Env::GetInstance()->NotifyWindowInitialized(this);
284 void Window::SetType(ui::wm::WindowType type) {
285 // Cannot change type after the window is initialized.
290 void Window::SetName(const std::string& name) {
297 void Window::SetTransparent(bool transparent) {
298 transparent_ = transparent;
300 layer()->SetFillsBoundsOpaquely(!transparent_);
303 void Window::SetFillsBoundsCompletely(bool fills_bounds) {
305 layer()->SetFillsBoundsCompletely(fills_bounds);
308 Window* Window::GetRootWindow() {
309 return const_cast<Window*>(
310 static_cast<const Window*>(this)->GetRootWindow());
313 const Window* Window::GetRootWindow() const {
314 return IsRootWindow() ? this : parent_ ? parent_->GetRootWindow() : NULL;
317 WindowTreeHost* Window::GetHost() {
318 return const_cast<WindowTreeHost*>(const_cast<const Window*>(this)->
322 const WindowTreeHost* Window::GetHost() const {
323 const Window* root_window = GetRootWindow();
324 return root_window ? root_window->host_ : NULL;
327 void Window::Show() {
329 DCHECK_EQ(visible_, layer()->GetTargetVisibility());
330 // It is not allowed that a window is visible but the layers alpha is fully
331 // transparent since the window would still be considered to be active but
332 // could not be seen.
333 // TODO(skuhne): uncomment and fix issue 351553.
334 // DCHECK(!(visible_ && layer()->GetTargetOpacity() == 0.0f));
339 void Window::Hide() {
340 // RootWindow::OnVisibilityChanged will call ReleaseCapture.
344 bool Window::IsVisible() const {
345 // Layer visibility can be inconsistent with window visibility, for example
346 // when a Window is hidden, we want this function to return false immediately
347 // after, even though the client may decide to animate the hide effect (and
348 // so the layer will be visible for some time after Hide() is called).
349 for (const Window* window = this; window; window = window->parent()) {
350 if (!window->visible_)
353 return window->layer()->IsDrawn();
358 gfx::Rect Window::GetBoundsInRootWindow() const {
359 // TODO(beng): There may be a better way to handle this, and the existing code
360 // is likely wrong anyway in a multi-display world, but this will
362 if (!GetRootWindow())
364 gfx::Point origin = bounds().origin();
365 ConvertPointToTarget(parent_, GetRootWindow(), &origin);
366 return gfx::Rect(origin, bounds().size());
369 gfx::Rect Window::GetBoundsInScreen() const {
370 gfx::Rect bounds(GetBoundsInRootWindow());
371 const Window* root = GetRootWindow();
373 aura::client::ScreenPositionClient* screen_position_client =
374 aura::client::GetScreenPositionClient(root);
375 if (screen_position_client) {
376 gfx::Point origin = bounds.origin();
377 screen_position_client->ConvertPointToScreen(root, &origin);
378 bounds.set_origin(origin);
384 void Window::SetTransform(const gfx::Transform& transform) {
386 // Transforms aren't supported on layerless windows.
390 FOR_EACH_OBSERVER(WindowObserver, observers_,
391 OnWindowTransforming(this));
392 layer()->SetTransform(transform);
393 FOR_EACH_OBSERVER(WindowObserver, observers_,
394 OnWindowTransformed(this));
397 void Window::SetLayoutManager(LayoutManager* layout_manager) {
398 if (layout_manager == layout_manager_)
400 layout_manager_.reset(layout_manager);
403 // If we're changing to a new layout manager, ensure it is aware of all the
404 // existing child windows.
405 for (Windows::const_iterator it = children_.begin();
406 it != children_.end();
408 layout_manager_->OnWindowAddedToLayout(*it);
411 scoped_ptr<ui::EventTargeter>
412 Window::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) {
413 scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass();
414 targeter_ = targeter.Pass();
415 return old_targeter.Pass();
418 void Window::SetBounds(const gfx::Rect& new_bounds) {
419 if (parent_ && parent_->layout_manager())
420 parent_->layout_manager()->SetChildBounds(this, new_bounds);
422 SetBoundsInternal(new_bounds);
425 void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
426 const gfx::Display& dst_display) {
427 Window* root = GetRootWindow();
429 gfx::Point origin = new_bounds_in_screen.origin();
430 aura::client::ScreenPositionClient* screen_position_client =
431 aura::client::GetScreenPositionClient(root);
432 screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display);
435 SetBounds(new_bounds_in_screen);
438 gfx::Rect Window::GetTargetBounds() const {
442 if (!parent_ || parent_->layer())
443 return layer()->GetTargetBounds();
445 // We have a layer but our parent (who is valid) doesn't. This means the
446 // coordinates of the layer are relative to the first ancestor with a layer;
447 // convert to be relative to parent.
448 gfx::Vector2d offset;
449 const aura::Window* ancestor_with_layer =
450 parent_->GetAncestorWithLayer(&offset);
451 if (!ancestor_with_layer)
452 return layer()->GetTargetBounds();
454 gfx::Rect layer_target_bounds = layer()->GetTargetBounds();
455 layer_target_bounds -= offset;
456 return layer_target_bounds;
459 void Window::SchedulePaintInRect(const gfx::Rect& rect) {
460 if (!layer() && parent_) {
461 // Notification of paint scheduled happens for the window with a layer.
462 gfx::Rect parent_rect(bounds().size());
463 parent_rect.Intersect(rect);
464 if (!parent_rect.IsEmpty()) {
465 parent_rect.Offset(bounds().origin().OffsetFromOrigin());
466 parent_->SchedulePaintInRect(parent_rect);
468 } else if (layer() && layer()->SchedulePaint(rect)) {
470 WindowObserver, observers_, OnWindowPaintScheduled(this, rect));
474 void Window::StackChildAtTop(Window* child) {
475 if (children_.size() <= 1 || child == children_.back())
476 return; // In the front already.
477 StackChildAbove(child, children_.back());
480 void Window::StackChildAbove(Window* child, Window* target) {
481 StackChildRelativeTo(child, target, STACK_ABOVE);
484 void Window::StackChildAtBottom(Window* child) {
485 if (children_.size() <= 1 || child == children_.front())
486 return; // At the bottom already.
487 StackChildBelow(child, children_.front());
490 void Window::StackChildBelow(Window* child, Window* target) {
491 StackChildRelativeTo(child, target, STACK_BELOW);
494 void Window::AddChild(Window* child) {
495 WindowObserver::HierarchyChangeParams params;
496 params.target = child;
497 params.new_parent = this;
498 params.old_parent = child->parent();
499 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
500 NotifyWindowHierarchyChange(params);
502 Window* old_root = child->GetRootWindow();
504 DCHECK(std::find(children_.begin(), children_.end(), child) ==
507 child->parent()->RemoveChildImpl(child, this);
509 gfx::Vector2d offset;
510 aura::Window* ancestor_with_layer = GetAncestorWithLayer(&offset);
512 child->parent_ = this;
514 if (ancestor_with_layer) {
515 offset += child->bounds().OffsetFromOrigin();
516 child->ReparentLayers(ancestor_with_layer->layer(), offset);
519 children_.push_back(child);
521 layout_manager_->OnWindowAddedToLayout(child);
522 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child));
523 child->OnParentChanged();
525 Window* root_window = GetRootWindow();
526 if (root_window && old_root != root_window) {
527 root_window->GetHost()->dispatcher()->OnWindowAddedToRootWindow(child);
528 child->NotifyAddedToRootWindow();
531 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
532 NotifyWindowHierarchyChange(params);
535 void Window::RemoveChild(Window* child) {
536 WindowObserver::HierarchyChangeParams params;
537 params.target = child;
538 params.new_parent = NULL;
539 params.old_parent = this;
540 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
541 NotifyWindowHierarchyChange(params);
543 RemoveChildImpl(child, NULL);
545 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
546 NotifyWindowHierarchyChange(params);
549 bool Window::Contains(const Window* other) const {
550 for (const Window* parent = other; parent; parent = parent->parent_) {
557 Window* Window::GetChildById(int id) {
558 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id));
561 const Window* Window::GetChildById(int id) const {
562 Windows::const_iterator i;
563 for (i = children_.begin(); i != children_.end(); ++i) {
564 if ((*i)->id() == id)
566 const Window* result = (*i)->GetChildById(id);
574 void Window::ConvertPointToTarget(const Window* source,
575 const Window* target,
579 if (source->GetRootWindow() != target->GetRootWindow()) {
580 client::ScreenPositionClient* source_client =
581 client::GetScreenPositionClient(source->GetRootWindow());
582 // |source_client| can be NULL in tests.
584 source_client->ConvertPointToScreen(source, point);
586 client::ScreenPositionClient* target_client =
587 client::GetScreenPositionClient(target->GetRootWindow());
588 // |target_client| can be NULL in tests.
590 target_client->ConvertPointFromScreen(target, point);
591 } else if ((source != target) && (!source->layer() || !target->layer())) {
592 if (!source->layer()) {
593 gfx::Vector2d offset_to_layer;
594 source = source->GetAncestorWithLayer(&offset_to_layer);
595 *point += offset_to_layer;
597 if (!target->layer()) {
598 gfx::Vector2d offset_to_layer;
599 target = target->GetAncestorWithLayer(&offset_to_layer);
600 *point -= offset_to_layer;
602 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
604 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
609 void Window::ConvertRectToTarget(const Window* source,
610 const Window* target,
613 gfx::Point origin = rect->origin();
614 ConvertPointToTarget(source, target, &origin);
615 rect->set_origin(origin);
618 void Window::MoveCursorTo(const gfx::Point& point_in_window) {
619 Window* root_window = GetRootWindow();
621 gfx::Point point_in_root(point_in_window);
622 ConvertPointToTarget(this, root_window, &point_in_root);
623 root_window->GetHost()->MoveCursorTo(point_in_root);
626 gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const {
627 return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor;
630 void Window::SetEventFilter(ui::EventHandler* event_filter) {
632 RemovePreTargetHandler(event_filter_.get());
633 event_filter_.reset(event_filter);
635 AddPreTargetHandler(event_filter);
638 void Window::AddObserver(WindowObserver* observer) {
639 observers_.AddObserver(observer);
642 void Window::RemoveObserver(WindowObserver* observer) {
643 observers_.RemoveObserver(observer);
646 bool Window::HasObserver(WindowObserver* observer) {
647 return observers_.HasObserver(observer);
650 bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const {
651 const Window* root_window = GetRootWindow();
654 gfx::Point local_point(point_in_root);
655 ConvertPointToTarget(root_window, this, &local_point);
656 return gfx::Rect(GetTargetBounds().size()).Contains(local_point);
659 bool Window::ContainsPoint(const gfx::Point& local_point) const {
660 return gfx::Rect(bounds().size()).Contains(local_point);
663 Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) {
664 return GetWindowForPoint(local_point, true, true);
667 Window* Window::GetTopWindowContainingPoint(const gfx::Point& local_point) {
668 return GetWindowForPoint(local_point, false, false);
671 Window* Window::GetToplevelWindow() {
672 Window* topmost_window_with_delegate = NULL;
673 for (aura::Window* window = this; window != NULL; window = window->parent()) {
674 if (window->delegate())
675 topmost_window_with_delegate = window;
677 return topmost_window_with_delegate;
680 void Window::Focus() {
681 client::FocusClient* client = client::GetFocusClient(this);
683 client->FocusWindow(this);
686 void Window::Blur() {
687 client::FocusClient* client = client::GetFocusClient(this);
689 client->FocusWindow(NULL);
692 bool Window::HasFocus() const {
693 client::FocusClient* client = client::GetFocusClient(this);
694 return client && client->GetFocusedWindow() == this;
697 bool Window::CanFocus() const {
701 // NOTE: as part of focusing the window the ActivationClient may make the
702 // window visible (by way of making a hidden ancestor visible). For this
703 // reason we can't check visibility here and assume the client is doing it.
704 if (!parent_ || (delegate_ && !delegate_->CanFocus()))
707 // The client may forbid certain windows from receiving focus at a given point
709 client::EventClient* client = client::GetEventClient(GetRootWindow());
710 if (client && !client->CanProcessEventsWithinSubtree(this))
713 return parent_->CanFocus();
716 bool Window::CanReceiveEvents() const {
720 // The client may forbid certain windows from receiving events at a given
722 client::EventClient* client = client::GetEventClient(GetRootWindow());
723 if (client && !client->CanProcessEventsWithinSubtree(this))
726 return parent_ && IsVisible() && parent_->CanReceiveEvents();
729 void Window::SetCapture() {
733 Window* root_window = GetRootWindow();
736 client::GetCaptureClient(root_window)->SetCapture(this);
739 void Window::ReleaseCapture() {
740 Window* root_window = GetRootWindow();
743 client::GetCaptureClient(root_window)->ReleaseCapture(this);
746 bool Window::HasCapture() {
747 Window* root_window = GetRootWindow();
750 client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
751 return capture_client && capture_client->GetCaptureWindow() == this;
754 void Window::SuppressPaint() {
756 layer()->SuppressPaint();
759 // {Set,Get,Clear}Property are implemented in window_property.h.
761 void Window::SetNativeWindowProperty(const char* key, void* value) {
763 key, key, NULL, reinterpret_cast<int64>(value), 0);
766 void* Window::GetNativeWindowProperty(const char* key) const {
767 return reinterpret_cast<void*>(GetPropertyInternal(key, 0));
770 void Window::OnDeviceScaleFactorChanged(float device_scale_factor) {
771 ScopedCursorHider hider(this);
773 host_->OnDeviceScaleFactorChanged(device_scale_factor);
775 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
779 std::string Window::GetDebugInfo() const {
780 return base::StringPrintf(
781 "%s<%d> bounds(%d, %d, %d, %d) %s %s opacity=%.1f",
782 name().empty() ? "Unknown" : name().c_str(), id(),
783 bounds().x(), bounds().y(), bounds().width(), bounds().height(),
784 visible_ ? "WindowVisible" : "WindowHidden",
786 (layer()->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") :
788 layer() ? layer()->opacity() : 1.0f);
791 void Window::PrintWindowHierarchy(int depth) const {
792 VLOG(0) << base::StringPrintf(
793 "%*s%s", depth * 2, "", GetDebugInfo().c_str());
794 for (Windows::const_iterator it = children_.begin();
795 it != children_.end(); ++it) {
797 child->PrintWindowHierarchy(depth + 1);
802 void Window::RemoveOrDestroyChildren() {
803 while (!children_.empty()) {
804 Window* child = children_[0];
805 if (child->owned_by_parent_) {
807 // Deleting the child so remove it from out children_ list.
808 DCHECK(std::find(children_.begin(), children_.end(), child) ==
811 // Even if we can't delete the child, we still need to remove it from the
812 // parent so that relevant bookkeeping (parent_ back-pointers etc) are
819 ///////////////////////////////////////////////////////////////////////////////
822 int64 Window::SetPropertyInternal(const void* key,
824 PropertyDeallocator deallocator,
826 int64 default_value) {
827 int64 old = GetPropertyInternal(key, default_value);
828 if (value == default_value) {
829 prop_map_.erase(key);
832 prop_value.name = name;
833 prop_value.value = value;
834 prop_value.deallocator = deallocator;
835 prop_map_[key] = prop_value;
837 FOR_EACH_OBSERVER(WindowObserver, observers_,
838 OnWindowPropertyChanged(this, key, old));
842 int64 Window::GetPropertyInternal(const void* key,
843 int64 default_value) const {
844 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
845 if (iter == prop_map_.end())
846 return default_value;
847 return iter->second.value;
850 bool Window::HitTest(const gfx::Point& local_point) {
851 gfx::Rect local_bounds(bounds().size());
852 if (!delegate_ || !delegate_->HasHitTestMask())
853 return local_bounds.Contains(local_point);
856 delegate_->GetHitTestMask(&mask);
858 SkRegion clip_region;
859 clip_region.setRect(local_bounds.x(), local_bounds.y(),
860 local_bounds.width(), local_bounds.height());
861 SkRegion mask_region;
862 return mask_region.setPath(mask, clip_region) &&
863 mask_region.contains(local_point.x(), local_point.y());
866 void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
867 gfx::Rect actual_new_bounds(new_bounds);
869 // Ensure we don't go smaller than our minimum bounds.
871 const gfx::Size& min_size = delegate_->GetMinimumSize();
872 actual_new_bounds.set_width(
873 std::max(min_size.width(), actual_new_bounds.width()));
874 actual_new_bounds.set_height(
875 std::max(min_size.height(), actual_new_bounds.height()));
878 gfx::Rect old_bounds = GetTargetBounds();
880 // Always need to set the layer's bounds -- even if it is to the same thing.
881 // This may cause important side effects such as stopping animation.
883 const gfx::Vector2d origin_delta = new_bounds.OffsetFromOrigin() -
884 bounds_.OffsetFromOrigin();
885 bounds_ = new_bounds;
886 OffsetLayerBounds(origin_delta);
888 if (parent_ && !parent_->layer()) {
889 gfx::Vector2d offset;
890 const aura::Window* ancestor_with_layer =
891 parent_->GetAncestorWithLayer(&offset);
892 if (ancestor_with_layer)
893 actual_new_bounds.Offset(offset);
895 layer()->SetBounds(actual_new_bounds);
898 // If we are currently not the layer's delegate, we will not get bounds
899 // changed notification from the layer (this typically happens after animating
900 // hidden). We must notify ourselves.
901 if (!layer() || layer()->delegate() != this)
902 OnWindowBoundsChanged(old_bounds);
905 void Window::SetVisible(bool visible) {
906 if ((layer() && visible == layer()->GetTargetVisibility()) ||
907 (!layer() && visible == visible_))
908 return; // No change.
910 FOR_EACH_OBSERVER(WindowObserver, observers_,
911 OnWindowVisibilityChanging(this, visible));
913 client::VisibilityClient* visibility_client =
914 client::GetVisibilityClient(this);
915 if (visibility_client)
916 visibility_client->UpdateLayerVisibility(this, visible);
918 layer()->SetVisible(visible);
921 if (parent_ && parent_->layout_manager_)
922 parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible);
925 delegate_->OnWindowTargetVisibilityChanged(visible);
927 NotifyWindowVisibilityChanged(this, visible);
930 void Window::SchedulePaint() {
931 SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height()));
934 void Window::Paint(gfx::Canvas* canvas) {
936 delegate_->OnPaint(canvas);
937 PaintLayerlessChildren(canvas);
940 void Window::PaintLayerlessChildren(gfx::Canvas* canvas) {
941 for (size_t i = 0, count = children_.size(); i < count; ++i) {
942 Window* child = children_[i];
943 if (!child->layer() && child->visible_) {
944 gfx::ScopedCanvas scoped_canvas(canvas);
945 canvas->ClipRect(child->bounds());
946 if (!canvas->IsClipEmpty()) {
947 canvas->Translate(child->bounds().OffsetFromOrigin());
948 child->Paint(canvas);
954 Window* Window::GetWindowForPoint(const gfx::Point& local_point,
955 bool return_tightest,
956 bool for_event_handling) {
960 if ((for_event_handling && !HitTest(local_point)) ||
961 (!for_event_handling && !ContainsPoint(local_point)))
964 // Check if I should claim this event and not pass it to my children because
965 // the location is inside my hit test override area. For details, see
966 // set_hit_test_bounds_override_inner().
967 if (for_event_handling && !hit_test_bounds_override_inner_.empty()) {
968 gfx::Rect inset_local_bounds(gfx::Point(), bounds().size());
969 inset_local_bounds.Inset(hit_test_bounds_override_inner_);
970 // We know we're inside the normal local bounds, so if we're outside the
971 // inset bounds we must be in the special hit test override area.
972 DCHECK(HitTest(local_point));
973 if (!inset_local_bounds.Contains(local_point))
974 return delegate_ ? this : NULL;
977 if (!return_tightest && delegate_)
980 for (Windows::const_reverse_iterator it = children_.rbegin(),
981 rend = children_.rend();
985 if (for_event_handling) {
986 if (child->ignore_events_)
988 // The client may not allow events to be processed by certain subtrees.
989 client::EventClient* client = client::GetEventClient(GetRootWindow());
990 if (client && !client->CanProcessEventsWithinSubtree(child))
992 if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling(
997 gfx::Point point_in_child_coords(local_point);
998 ConvertPointToTarget(this, child, &point_in_child_coords);
999 Window* match = child->GetWindowForPoint(point_in_child_coords,
1001 for_event_handling);
1006 return delegate_ ? this : NULL;
1009 void Window::RemoveChildImpl(Window* child, Window* new_parent) {
1010 if (layout_manager_)
1011 layout_manager_->OnWillRemoveWindowFromLayout(child);
1012 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child));
1013 Window* root_window = child->GetRootWindow();
1014 Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL;
1015 if (root_window && root_window != new_root_window)
1016 child->NotifyRemovingFromRootWindow(new_root_window);
1018 gfx::Vector2d offset;
1019 GetAncestorWithLayer(&offset);
1020 child->UnparentLayers(!layer(), offset);
1021 child->parent_ = NULL;
1022 Windows::iterator i = std::find(children_.begin(), children_.end(), child);
1023 DCHECK(i != children_.end());
1025 child->OnParentChanged();
1026 if (layout_manager_)
1027 layout_manager_->OnWindowRemovedFromLayout(child);
1030 void Window::UnparentLayers(bool has_layerless_ancestor,
1031 const gfx::Vector2d& offset) {
1033 const gfx::Vector2d new_offset = offset + bounds().OffsetFromOrigin();
1034 for (size_t i = 0; i < children_.size(); ++i) {
1035 children_[i]->UnparentLayers(true, new_offset);
1038 // Only remove the layer if we still own it. Someone else may have acquired
1039 // ownership of it via AcquireLayer() and may expect the hierarchy to go
1040 // unchanged as the Window is destroyed.
1042 if (layer()->parent())
1043 layer()->parent()->Remove(layer());
1044 if (has_layerless_ancestor) {
1045 const gfx::Rect real_bounds(bounds_);
1046 gfx::Rect layer_bounds(layer()->bounds());
1047 layer_bounds.Offset(-offset);
1048 layer()->SetBounds(layer_bounds);
1049 bounds_ = real_bounds;
1055 void Window::ReparentLayers(ui::Layer* parent_layer,
1056 const gfx::Vector2d& offset) {
1058 for (size_t i = 0; i < children_.size(); ++i) {
1059 children_[i]->ReparentLayers(
1061 offset + children_[i]->bounds().OffsetFromOrigin());
1064 const gfx::Rect real_bounds(bounds());
1065 parent_layer->Add(layer());
1066 gfx::Rect layer_bounds(layer()->bounds().size());
1067 layer_bounds += offset;
1068 layer()->SetBounds(layer_bounds);
1069 bounds_ = real_bounds;
1073 void Window::OffsetLayerBounds(const gfx::Vector2d& offset) {
1075 for (size_t i = 0; i < children_.size(); ++i)
1076 children_[i]->OffsetLayerBounds(offset);
1078 gfx::Rect layer_bounds(layer()->bounds());
1079 layer_bounds += offset;
1080 layer()->SetBounds(layer_bounds);
1084 void Window::OnParentChanged() {
1086 WindowObserver, observers_, OnWindowParentChanged(this, parent_));
1089 void Window::StackChildRelativeTo(Window* child,
1091 StackDirection direction) {
1092 DCHECK_NE(child, target);
1095 DCHECK_EQ(this, child->parent());
1096 DCHECK_EQ(this, target->parent());
1098 client::WindowStackingClient* stacking_client =
1099 client::GetWindowStackingClient();
1100 if (stacking_client &&
1101 !stacking_client->AdjustStacking(&child, &target, &direction))
1104 const size_t child_i =
1105 std::find(children_.begin(), children_.end(), child) - children_.begin();
1106 const size_t target_i =
1107 std::find(children_.begin(), children_.end(), target) - children_.begin();
1109 // Don't move the child if it is already in the right place.
1110 if ((direction == STACK_ABOVE && child_i == target_i + 1) ||
1111 (direction == STACK_BELOW && child_i + 1 == target_i))
1114 const size_t dest_i =
1115 direction == STACK_ABOVE ?
1116 (child_i < target_i ? target_i : target_i + 1) :
1117 (child_i < target_i ? target_i - 1 : target_i);
1118 children_.erase(children_.begin() + child_i);
1119 children_.insert(children_.begin() + dest_i, child);
1121 StackChildLayerRelativeTo(child, target, direction);
1123 child->OnStackingChanged();
1126 void Window::StackChildLayerRelativeTo(Window* child,
1128 StackDirection direction) {
1129 Window* ancestor_with_layer = GetAncestorWithLayer(NULL);
1130 ui::Layer* ancestor_layer =
1131 ancestor_with_layer ? ancestor_with_layer->layer() : NULL;
1132 if (!ancestor_layer)
1135 if (child->layer() && target->layer()) {
1136 if (direction == STACK_ABOVE)
1137 ancestor_layer->StackAbove(child->layer(), target->layer());
1139 ancestor_layer->StackBelow(child->layer(), target->layer());
1142 typedef std::vector<ui::Layer*> Layers;
1144 GetLayersToStack(child, &layers);
1148 ui::Layer* target_layer;
1149 if (direction == STACK_ABOVE) {
1151 FindStackingTargetLayer<Windows::const_reverse_iterator>(target, child);
1154 FindStackingTargetLayer<Windows::const_iterator>(target, child);
1157 if (!target_layer) {
1158 if (direction == STACK_ABOVE) {
1159 for (Layers::const_reverse_iterator i = layers.rbegin(),
1160 rend = layers.rend(); i != rend; ++i) {
1161 ancestor_layer->StackAtBottom(*i);
1164 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i)
1165 ancestor_layer->StackAtTop(*i);
1170 if (direction == STACK_ABOVE) {
1171 for (Layers::const_reverse_iterator i = layers.rbegin(),
1172 rend = layers.rend(); i != rend; ++i) {
1173 ancestor_layer->StackAbove(*i, target_layer);
1176 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i)
1177 ancestor_layer->StackBelow(*i, target_layer);
1181 void Window::OnStackingChanged() {
1182 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
1185 void Window::NotifyRemovingFromRootWindow(Window* new_root) {
1186 FOR_EACH_OBSERVER(WindowObserver, observers_,
1187 OnWindowRemovingFromRootWindow(this, new_root));
1188 for (Window::Windows::const_iterator it = children_.begin();
1189 it != children_.end(); ++it) {
1190 (*it)->NotifyRemovingFromRootWindow(new_root);
1194 void Window::NotifyAddedToRootWindow() {
1195 FOR_EACH_OBSERVER(WindowObserver, observers_,
1196 OnWindowAddedToRootWindow(this));
1197 for (Window::Windows::const_iterator it = children_.begin();
1198 it != children_.end(); ++it) {
1199 (*it)->NotifyAddedToRootWindow();
1203 void Window::NotifyWindowHierarchyChange(
1204 const WindowObserver::HierarchyChangeParams& params) {
1205 params.target->NotifyWindowHierarchyChangeDown(params);
1206 switch (params.phase) {
1207 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
1208 if (params.old_parent)
1209 params.old_parent->NotifyWindowHierarchyChangeUp(params);
1211 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
1212 if (params.new_parent)
1213 params.new_parent->NotifyWindowHierarchyChangeUp(params);
1221 void Window::NotifyWindowHierarchyChangeDown(
1222 const WindowObserver::HierarchyChangeParams& params) {
1223 NotifyWindowHierarchyChangeAtReceiver(params);
1224 for (Window::Windows::const_iterator it = children_.begin();
1225 it != children_.end(); ++it) {
1226 (*it)->NotifyWindowHierarchyChangeDown(params);
1230 void Window::NotifyWindowHierarchyChangeUp(
1231 const WindowObserver::HierarchyChangeParams& params) {
1232 for (Window* window = this; window; window = window->parent())
1233 window->NotifyWindowHierarchyChangeAtReceiver(params);
1236 void Window::NotifyWindowHierarchyChangeAtReceiver(
1237 const WindowObserver::HierarchyChangeParams& params) {
1238 WindowObserver::HierarchyChangeParams local_params = params;
1239 local_params.receiver = this;
1241 switch (params.phase) {
1242 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
1243 FOR_EACH_OBSERVER(WindowObserver, observers_,
1244 OnWindowHierarchyChanging(local_params));
1246 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
1247 FOR_EACH_OBSERVER(WindowObserver, observers_,
1248 OnWindowHierarchyChanged(local_params));
1256 void Window::NotifyWindowVisibilityChanged(aura::Window* target,
1258 if (!NotifyWindowVisibilityChangedDown(target, visible)) {
1259 return; // |this| has been deleted.
1261 NotifyWindowVisibilityChangedUp(target, visible);
1264 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target,
1266 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one
1267 // of the observers. We create an local observer for that. In that case we
1268 // exit without further access to any members.
1269 WindowTracker tracker;
1271 FOR_EACH_OBSERVER(WindowObserver, observers_,
1272 OnWindowVisibilityChanged(target, visible));
1273 return tracker.Contains(this);
1276 bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target,
1278 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible))
1279 return false; // |this| was deleted.
1280 std::set<const Window*> child_already_processed;
1281 bool child_destroyed = false;
1283 child_destroyed = false;
1284 for (Window::Windows::const_iterator it = children_.begin();
1285 it != children_.end(); ++it) {
1286 if (!child_already_processed.insert(*it).second)
1288 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) {
1289 // |*it| was deleted, |it| is invalid and |children_| has changed.
1290 // We exit the current for-loop and enter a new one.
1291 child_destroyed = true;
1295 } while (child_destroyed);
1299 void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
1301 for (Window* window = this; window; window = window->parent()) {
1302 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible);
1307 void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds) {
1309 bounds_ = layer()->bounds();
1310 if (parent_ && !parent_->layer()) {
1311 gfx::Vector2d offset;
1312 aura::Window* ancestor_with_layer =
1313 parent_->GetAncestorWithLayer(&offset);
1314 if (ancestor_with_layer)
1315 bounds_.Offset(-offset);
1319 if (layout_manager_)
1320 layout_manager_->OnWindowResized();
1322 delegate_->OnBoundsChanged(old_bounds, bounds());
1323 FOR_EACH_OBSERVER(WindowObserver,
1325 OnWindowBoundsChanged(this, old_bounds, bounds()));
1328 void Window::OnPaintLayer(gfx::Canvas* canvas) {
1332 base::Closure Window::PrepareForLayerBoundsChange() {
1333 return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
1337 bool Window::CanAcceptEvent(const ui::Event& event) {
1338 // The client may forbid certain windows from receiving events at a given
1340 client::EventClient* client = client::GetEventClient(GetRootWindow());
1341 if (client && !client->CanProcessEventsWithinSubtree(this))
1344 // We need to make sure that a touch cancel event and any gesture events it
1345 // creates can always reach the window. This ensures that we receive a valid
1346 // touch / gesture stream.
1347 if (event.IsEndingEvent())
1353 // The top-most window can always process an event.
1357 // For located events (i.e. mouse, touch etc.), an assumption is made that
1358 // windows that don't have a delegate cannot process the event (see more in
1359 // GetWindowForPoint()). This assumption is not made for key events.
1360 return event.IsKeyEvent() || delegate_;
1363 ui::EventTarget* Window::GetParentTarget() {
1364 if (IsRootWindow()) {
1365 return client::GetEventClient(this) ?
1366 client::GetEventClient(this)->GetToplevelEventTarget() :
1372 scoped_ptr<ui::EventTargetIterator> Window::GetChildIterator() const {
1373 return scoped_ptr<ui::EventTargetIterator>(
1374 new ui::EventTargetIteratorImpl<Window>(children()));
1377 ui::EventTargeter* Window::GetEventTargeter() {
1378 return targeter_.get();
1381 void Window::ConvertEventToTarget(ui::EventTarget* target,
1382 ui::LocatedEvent* event) {
1383 event->ConvertLocationToTarget(this,
1384 static_cast<Window*>(target));
1387 void Window::UpdateLayerName() {
1388 #if !defined(NDEBUG)
1391 std::string layer_name(name_);
1392 if (layer_name.empty())
1393 layer_name = "Unnamed Window";
1396 layer_name += " " + base::IntToString(id_);
1398 layer()->set_name(layer_name);
1402 bool Window::ContainsMouse() {
1403 bool contains_mouse = false;
1405 WindowTreeHost* host = GetHost();
1406 contains_mouse = host &&
1407 ContainsPointInRoot(host->dispatcher()->GetLastMouseLocationInRoot());
1409 return contains_mouse;
1412 const Window* Window::GetAncestorWithLayer(gfx::Vector2d* offset) const {
1413 for (const aura::Window* window = this; window; window = window->parent()) {
1414 if (window->layer())
1417 *offset += window->bounds().OffsetFromOrigin();
1420 *offset = gfx::Vector2d();