Fix OOP <webview> resize and autosize.
[chromium-blink-merge.git] / ui / aura / window.cc
blob6cde8c2603cc53fece1c26f8c1748b0f2bde275c
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/profiler/scoped_tracker.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/cursor_client.h"
19 #include "ui/aura/client/event_client.h"
20 #include "ui/aura/client/focus_client.h"
21 #include "ui/aura/client/screen_position_client.h"
22 #include "ui/aura/client/visibility_client.h"
23 #include "ui/aura/client/window_stacking_client.h"
24 #include "ui/aura/env.h"
25 #include "ui/aura/layout_manager.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_tracker.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/compositor/compositor.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/events/event_target_iterator.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"
39 namespace aura {
41 class ScopedCursorHider {
42 public:
43 explicit ScopedCursorHider(Window* window)
44 : window_(window),
45 hid_cursor_(false) {
46 if (!window_->IsRootWindow())
47 return;
48 const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
49 Env::GetInstance()->last_mouse_location());
50 client::CursorClient* cursor_client = client::GetCursorClient(window_);
51 if (cursor_is_in_bounds && cursor_client &&
52 cursor_client->IsCursorVisible()) {
53 cursor_client->HideCursor();
54 hid_cursor_ = true;
57 ~ScopedCursorHider() {
58 if (!window_->IsRootWindow())
59 return;
61 // Update the device scale factor of the cursor client only when the last
62 // mouse location is on this root window.
63 if (hid_cursor_) {
64 client::CursorClient* cursor_client = client::GetCursorClient(window_);
65 if (cursor_client) {
66 const gfx::Display& display =
67 gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(
68 window_);
69 cursor_client->SetDisplay(display);
70 cursor_client->ShowCursor();
75 private:
76 Window* window_;
77 bool hid_cursor_;
79 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider);
82 Window::Window(WindowDelegate* delegate)
83 : host_(NULL),
84 type_(ui::wm::WINDOW_TYPE_UNKNOWN),
85 owned_by_parent_(true),
86 delegate_(delegate),
87 parent_(NULL),
88 visible_(false),
89 id_(-1),
90 transparent_(false),
91 user_data_(NULL),
92 ignore_events_(false),
93 // Don't notify newly added observers during notification. This causes
94 // problems for code that adds an observer as part of an observer
95 // notification (such as the workspace code).
96 observers_(base::ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) {
97 set_target_handler(delegate_);
100 Window::~Window() {
101 if (layer()->owner() == this)
102 layer()->CompleteAllAnimations();
103 layer()->SuppressPaint();
105 // Let the delegate know we're in the processing of destroying.
106 if (delegate_)
107 delegate_->OnWindowDestroying(this);
108 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this));
110 // While we are being destroyed, our target handler may also be in the
111 // process of destruction or already destroyed, so do not forward any
112 // input events at the ui::EP_TARGET phase.
113 set_target_handler(nullptr);
115 // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
116 // necessary but unfortunately is right now due to ordering
117 // peculiarities. WED must be notified _after_ other observers
118 // are notified of pending teardown but before the hierarchy
119 // is actually torn down.
120 WindowTreeHost* host = GetHost();
121 if (host)
122 host->dispatcher()->OnPostNotifiedWindowDestroying(this);
124 // The window should have already had its state cleaned up in
125 // WindowEventDispatcher::OnWindowHidden(), but there have been some crashes
126 // involving windows being destroyed without being hidden first. See
127 // crbug.com/342040. This should help us debug the issue. TODO(tdresser):
128 // remove this once we determine why we have windows that are destroyed
129 // without being hidden.
130 bool window_incorrectly_cleaned_up = CleanupGestureState();
131 CHECK(!window_incorrectly_cleaned_up);
133 // Then destroy the children.
134 RemoveOrDestroyChildren();
136 // The window needs to be removed from the parent before calling the
137 // WindowDestroyed callbacks of delegate and the observers.
138 if (parent_)
139 parent_->RemoveChild(this);
141 if (delegate_)
142 delegate_->OnWindowDestroyed(this);
143 base::ObserverListBase<WindowObserver>::Iterator iter(&observers_);
144 for (WindowObserver* observer = iter.GetNext(); observer;
145 observer = iter.GetNext()) {
146 RemoveObserver(observer);
147 observer->OnWindowDestroyed(this);
150 // Clear properties.
151 for (std::map<const void*, Value>::const_iterator iter = prop_map_.begin();
152 iter != prop_map_.end();
153 ++iter) {
154 if (iter->second.deallocator)
155 (*iter->second.deallocator)(iter->second.value);
157 prop_map_.clear();
159 // The layer will either be destroyed by |layer_owner_|'s dtor, or by whoever
160 // acquired it.
161 layer()->set_delegate(NULL);
162 DestroyLayer();
165 void Window::Init(ui::LayerType layer_type) {
166 SetLayer(new ui::Layer(layer_type));
167 layer()->SetVisible(false);
168 layer()->set_delegate(this);
169 UpdateLayerName();
170 layer()->SetFillsBoundsOpaquely(!transparent_);
171 Env::GetInstance()->NotifyWindowInitialized(this);
174 void Window::SetType(ui::wm::WindowType type) {
175 // Cannot change type after the window is initialized.
176 DCHECK(!layer());
177 type_ = type;
180 void Window::SetName(const std::string& name) {
181 name_ = name;
182 if (layer())
183 UpdateLayerName();
186 void Window::SetTitle(const base::string16& title) {
187 title_ = title;
188 FOR_EACH_OBSERVER(WindowObserver,
189 observers_,
190 OnWindowTitleChanged(this));
193 void Window::SetTransparent(bool transparent) {
194 transparent_ = transparent;
195 if (layer())
196 layer()->SetFillsBoundsOpaquely(!transparent_);
199 void Window::SetFillsBoundsCompletely(bool fills_bounds) {
200 layer()->SetFillsBoundsCompletely(fills_bounds);
203 Window* Window::GetRootWindow() {
204 return const_cast<Window*>(
205 static_cast<const Window*>(this)->GetRootWindow());
208 const Window* Window::GetRootWindow() const {
209 return IsRootWindow() ? this : parent_ ? parent_->GetRootWindow() : NULL;
212 WindowTreeHost* Window::GetHost() {
213 return const_cast<WindowTreeHost*>(const_cast<const Window*>(this)->
214 GetHost());
217 const WindowTreeHost* Window::GetHost() const {
218 const Window* root_window = GetRootWindow();
219 return root_window ? root_window->host_ : NULL;
222 void Window::Show() {
223 DCHECK_EQ(visible_, layer()->GetTargetVisibility());
224 // It is not allowed that a window is visible but the layers alpha is fully
225 // transparent since the window would still be considered to be active but
226 // could not be seen.
227 DCHECK_IMPLIES(visible_, layer()->GetTargetOpacity() > 0.0f);
228 SetVisible(true);
231 void Window::Hide() {
232 // RootWindow::OnVisibilityChanged will call ReleaseCapture.
233 SetVisible(false);
236 bool Window::IsVisible() const {
237 // Layer visibility can be inconsistent with window visibility, for example
238 // when a Window is hidden, we want this function to return false immediately
239 // after, even though the client may decide to animate the hide effect (and
240 // so the layer will be visible for some time after Hide() is called).
241 return visible_ ? layer()->IsDrawn() : false;
244 gfx::Rect Window::GetBoundsInRootWindow() const {
245 // TODO(beng): There may be a better way to handle this, and the existing code
246 // is likely wrong anyway in a multi-display world, but this will
247 // do for now.
248 if (!GetRootWindow())
249 return bounds();
250 gfx::Rect bounds_in_root(bounds().size());
251 ConvertRectToTarget(this, GetRootWindow(), &bounds_in_root);
252 return bounds_in_root;
255 gfx::Rect Window::GetBoundsInScreen() const {
256 gfx::Rect bounds(GetBoundsInRootWindow());
257 const Window* root = GetRootWindow();
258 if (root) {
259 aura::client::ScreenPositionClient* screen_position_client =
260 aura::client::GetScreenPositionClient(root);
261 if (screen_position_client) {
262 gfx::Point origin = bounds.origin();
263 screen_position_client->ConvertPointToScreen(root, &origin);
264 bounds.set_origin(origin);
267 return bounds;
270 void Window::SetTransform(const gfx::Transform& transform) {
271 FOR_EACH_OBSERVER(WindowObserver, observers_,
272 OnWindowTransforming(this));
273 layer()->SetTransform(transform);
274 FOR_EACH_OBSERVER(WindowObserver, observers_,
275 OnWindowTransformed(this));
276 NotifyAncestorWindowTransformed(this);
279 void Window::SetLayoutManager(LayoutManager* layout_manager) {
280 if (layout_manager == layout_manager_)
281 return;
282 layout_manager_.reset(layout_manager);
283 if (!layout_manager)
284 return;
285 // If we're changing to a new layout manager, ensure it is aware of all the
286 // existing child windows.
287 for (Windows::const_iterator it = children_.begin();
288 it != children_.end();
289 ++it)
290 layout_manager_->OnWindowAddedToLayout(*it);
293 scoped_ptr<ui::EventTargeter>
294 Window::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) {
295 scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass();
296 targeter_ = targeter.Pass();
297 return old_targeter.Pass();
300 void Window::SetBounds(const gfx::Rect& new_bounds) {
301 if (parent_ && parent_->layout_manager())
302 parent_->layout_manager()->SetChildBounds(this, new_bounds);
303 else {
304 // Ensure we don't go smaller than our minimum bounds.
305 gfx::Rect final_bounds(new_bounds);
306 if (delegate_) {
307 const gfx::Size& min_size = delegate_->GetMinimumSize();
308 final_bounds.set_width(std::max(min_size.width(), final_bounds.width()));
309 final_bounds.set_height(std::max(min_size.height(),
310 final_bounds.height()));
312 SetBoundsInternal(final_bounds);
316 void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
317 const gfx::Display& dst_display) {
318 Window* root = GetRootWindow();
319 if (root) {
320 aura::client::ScreenPositionClient* screen_position_client =
321 aura::client::GetScreenPositionClient(root);
322 screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display);
323 return;
325 SetBounds(new_bounds_in_screen);
328 gfx::Rect Window::GetTargetBounds() const {
329 return layer() ? layer()->GetTargetBounds() : bounds();
332 void Window::SchedulePaintInRect(const gfx::Rect& rect) {
333 layer()->SchedulePaint(rect);
336 void Window::StackChildAtTop(Window* child) {
337 if (children_.size() <= 1 || child == children_.back())
338 return; // In the front already.
339 StackChildAbove(child, children_.back());
342 void Window::StackChildAbove(Window* child, Window* target) {
343 StackChildRelativeTo(child, target, STACK_ABOVE);
346 void Window::StackChildAtBottom(Window* child) {
347 if (children_.size() <= 1 || child == children_.front())
348 return; // At the bottom already.
349 StackChildBelow(child, children_.front());
352 void Window::StackChildBelow(Window* child, Window* target) {
353 StackChildRelativeTo(child, target, STACK_BELOW);
356 void Window::AddChild(Window* child) {
357 DCHECK(layer()) << "Parent has not been Init()ed yet.";
358 DCHECK(child->layer()) << "Child has not been Init()ed yt.";
359 WindowObserver::HierarchyChangeParams params;
360 params.target = child;
361 params.new_parent = this;
362 params.old_parent = child->parent();
363 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
364 NotifyWindowHierarchyChange(params);
366 Window* old_root = child->GetRootWindow();
368 DCHECK(std::find(children_.begin(), children_.end(), child) ==
369 children_.end());
370 if (child->parent())
371 child->parent()->RemoveChildImpl(child, this);
373 child->parent_ = this;
374 layer()->Add(child->layer());
376 children_.push_back(child);
377 if (layout_manager_)
378 layout_manager_->OnWindowAddedToLayout(child);
379 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child));
380 child->OnParentChanged();
382 Window* root_window = GetRootWindow();
383 if (root_window && old_root != root_window) {
384 root_window->GetHost()->dispatcher()->OnWindowAddedToRootWindow(child);
385 child->NotifyAddedToRootWindow();
388 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
389 NotifyWindowHierarchyChange(params);
392 void Window::RemoveChild(Window* child) {
393 WindowObserver::HierarchyChangeParams params;
394 params.target = child;
395 params.new_parent = NULL;
396 params.old_parent = this;
397 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
398 NotifyWindowHierarchyChange(params);
400 RemoveChildImpl(child, NULL);
402 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
403 NotifyWindowHierarchyChange(params);
406 bool Window::Contains(const Window* other) const {
407 for (const Window* parent = other; parent; parent = parent->parent_) {
408 if (parent == this)
409 return true;
411 return false;
414 Window* Window::GetChildById(int id) {
415 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id));
418 const Window* Window::GetChildById(int id) const {
419 Windows::const_iterator i;
420 for (i = children_.begin(); i != children_.end(); ++i) {
421 if ((*i)->id() == id)
422 return *i;
423 const Window* result = (*i)->GetChildById(id);
424 if (result)
425 return result;
427 return NULL;
430 // static
431 void Window::ConvertPointToTarget(const Window* source,
432 const Window* target,
433 gfx::Point* point) {
434 if (!source)
435 return;
436 if (source->GetRootWindow() != target->GetRootWindow()) {
437 client::ScreenPositionClient* source_client =
438 client::GetScreenPositionClient(source->GetRootWindow());
439 // |source_client| can be NULL in tests.
440 if (source_client)
441 source_client->ConvertPointToScreen(source, point);
443 client::ScreenPositionClient* target_client =
444 client::GetScreenPositionClient(target->GetRootWindow());
445 // |target_client| can be NULL in tests.
446 if (target_client)
447 target_client->ConvertPointFromScreen(target, point);
448 } else {
449 ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point);
453 // static
454 void Window::ConvertRectToTarget(const Window* source,
455 const Window* target,
456 gfx::Rect* rect) {
457 DCHECK(rect);
458 gfx::Point origin = rect->origin();
459 ConvertPointToTarget(source, target, &origin);
460 rect->set_origin(origin);
463 void Window::MoveCursorTo(const gfx::Point& point_in_window) {
464 Window* root_window = GetRootWindow();
465 DCHECK(root_window);
466 gfx::Point point_in_root(point_in_window);
467 ConvertPointToTarget(this, root_window, &point_in_root);
468 root_window->GetHost()->MoveCursorTo(point_in_root);
471 gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const {
472 return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor;
475 void Window::AddObserver(WindowObserver* observer) {
476 observer->OnObservingWindow(this);
477 observers_.AddObserver(observer);
480 void Window::RemoveObserver(WindowObserver* observer) {
481 observer->OnUnobservingWindow(this);
482 observers_.RemoveObserver(observer);
485 bool Window::HasObserver(const WindowObserver* observer) const {
486 return observers_.HasObserver(observer);
489 bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const {
490 const Window* root_window = GetRootWindow();
491 if (!root_window)
492 return false;
493 gfx::Point local_point(point_in_root);
494 ConvertPointToTarget(root_window, this, &local_point);
495 return gfx::Rect(GetTargetBounds().size()).Contains(local_point);
498 bool Window::ContainsPoint(const gfx::Point& local_point) const {
499 return gfx::Rect(bounds().size()).Contains(local_point);
502 Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) {
503 return GetWindowForPoint(local_point, true, true);
506 Window* Window::GetTopWindowContainingPoint(const gfx::Point& local_point) {
507 return GetWindowForPoint(local_point, false, false);
510 Window* Window::GetToplevelWindow() {
511 Window* topmost_window_with_delegate = NULL;
512 for (aura::Window* window = this; window != NULL; window = window->parent()) {
513 if (window->delegate())
514 topmost_window_with_delegate = window;
516 return topmost_window_with_delegate;
519 void Window::Focus() {
520 client::FocusClient* client = client::GetFocusClient(this);
521 DCHECK(client);
522 client->FocusWindow(this);
525 bool Window::HasFocus() const {
526 client::FocusClient* client = client::GetFocusClient(this);
527 return client && client->GetFocusedWindow() == this;
530 bool Window::CanFocus() const {
531 if (IsRootWindow())
532 return IsVisible();
534 // NOTE: as part of focusing the window the ActivationClient may make the
535 // window visible (by way of making a hidden ancestor visible). For this
536 // reason we can't check visibility here and assume the client is doing it.
537 if (!parent_ || (delegate_ && !delegate_->CanFocus()))
538 return false;
540 // The client may forbid certain windows from receiving focus at a given point
541 // in time.
542 client::EventClient* client = client::GetEventClient(GetRootWindow());
543 if (client && !client->CanProcessEventsWithinSubtree(this))
544 return false;
546 return parent_->CanFocus();
549 bool Window::CanReceiveEvents() const {
550 if (IsRootWindow())
551 return IsVisible();
553 // The client may forbid certain windows from receiving events at a given
554 // point in time.
555 client::EventClient* client = client::GetEventClient(GetRootWindow());
556 if (client && !client->CanProcessEventsWithinSubtree(this))
557 return false;
559 return parent_ && IsVisible() && parent_->CanReceiveEvents();
562 void Window::SetCapture() {
563 if (!IsVisible())
564 return;
566 Window* root_window = GetRootWindow();
567 if (!root_window)
568 return;
569 client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
570 if (!capture_client)
571 return;
572 client::GetCaptureClient(root_window)->SetCapture(this);
575 void Window::ReleaseCapture() {
576 Window* root_window = GetRootWindow();
577 if (!root_window)
578 return;
579 client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
580 if (!capture_client)
581 return;
582 client::GetCaptureClient(root_window)->ReleaseCapture(this);
585 bool Window::HasCapture() {
586 Window* root_window = GetRootWindow();
587 if (!root_window)
588 return false;
589 client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
590 return capture_client && capture_client->GetCaptureWindow() == this;
593 void Window::SuppressPaint() {
594 layer()->SuppressPaint();
597 // {Set,Get,Clear}Property are implemented in window_property.h.
599 void Window::SetNativeWindowProperty(const char* key, void* value) {
600 SetPropertyInternal(
601 key, key, NULL, reinterpret_cast<int64>(value), 0);
604 void* Window::GetNativeWindowProperty(const char* key) const {
605 return reinterpret_cast<void*>(GetPropertyInternal(key, 0));
608 void Window::OnDeviceScaleFactorChanged(float device_scale_factor) {
609 ScopedCursorHider hider(this);
610 if (delegate_)
611 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
614 #if !defined(NDEBUG)
615 std::string Window::GetDebugInfo() const {
616 return base::StringPrintf(
617 "%s<%d> bounds(%d, %d, %d, %d) %s %s opacity=%.1f",
618 name().empty() ? "Unknown" : name().c_str(), id(),
619 bounds().x(), bounds().y(), bounds().width(), bounds().height(),
620 visible_ ? "WindowVisible" : "WindowHidden",
621 layer() ?
622 (layer()->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") :
623 "NoLayer",
624 layer() ? layer()->opacity() : 1.0f);
627 void Window::PrintWindowHierarchy(int depth) const {
628 VLOG(0) << base::StringPrintf(
629 "%*s%s", depth * 2, "", GetDebugInfo().c_str());
630 for (Windows::const_iterator it = children_.begin();
631 it != children_.end(); ++it) {
632 Window* child = *it;
633 child->PrintWindowHierarchy(depth + 1);
636 #endif
638 void Window::RemoveOrDestroyChildren() {
639 while (!children_.empty()) {
640 Window* child = children_[0];
641 if (child->owned_by_parent_) {
642 delete child;
643 // Deleting the child so remove it from out children_ list.
644 DCHECK(std::find(children_.begin(), children_.end(), child) ==
645 children_.end());
646 } else {
647 // Even if we can't delete the child, we still need to remove it from the
648 // parent so that relevant bookkeeping (parent_ back-pointers etc) are
649 // updated.
650 RemoveChild(child);
655 ///////////////////////////////////////////////////////////////////////////////
656 // Window, private:
658 int64 Window::SetPropertyInternal(const void* key,
659 const char* name,
660 PropertyDeallocator deallocator,
661 int64 value,
662 int64 default_value) {
663 int64 old = GetPropertyInternal(key, default_value);
664 if (value == default_value) {
665 prop_map_.erase(key);
666 } else {
667 Value prop_value;
668 prop_value.name = name;
669 prop_value.value = value;
670 prop_value.deallocator = deallocator;
671 prop_map_[key] = prop_value;
673 FOR_EACH_OBSERVER(WindowObserver, observers_,
674 OnWindowPropertyChanged(this, key, old));
675 return old;
678 int64 Window::GetPropertyInternal(const void* key,
679 int64 default_value) const {
680 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
681 if (iter == prop_map_.end())
682 return default_value;
683 return iter->second.value;
686 bool Window::HitTest(const gfx::Point& local_point) {
687 gfx::Rect local_bounds(bounds().size());
688 if (!delegate_ || !delegate_->HasHitTestMask())
689 return local_bounds.Contains(local_point);
691 gfx::Path mask;
692 delegate_->GetHitTestMask(&mask);
694 SkRegion clip_region;
695 clip_region.setRect(local_bounds.x(), local_bounds.y(),
696 local_bounds.width(), local_bounds.height());
697 SkRegion mask_region;
698 return mask_region.setPath(mask, clip_region) &&
699 mask_region.contains(local_point.x(), local_point.y());
702 void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
703 gfx::Rect old_bounds = GetTargetBounds();
705 // Always need to set the layer's bounds -- even if it is to the same thing.
706 // This may cause important side effects such as stopping animation.
707 layer()->SetBounds(new_bounds);
709 // If we are currently not the layer's delegate, we will not get bounds
710 // changed notification from the layer (this typically happens after animating
711 // hidden). We must notify ourselves.
712 if (layer()->delegate() != this)
713 OnWindowBoundsChanged(old_bounds);
716 void Window::SetVisible(bool visible) {
717 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
718 tracked_objects::ScopedTracker tracking_profile(
719 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 Window::SetVisible"));
721 if (visible == layer()->GetTargetVisibility())
722 return; // No change.
724 FOR_EACH_OBSERVER(WindowObserver, observers_,
725 OnWindowVisibilityChanging(this, visible));
727 client::VisibilityClient* visibility_client =
728 client::GetVisibilityClient(this);
729 if (visibility_client)
730 visibility_client->UpdateLayerVisibility(this, visible);
731 else
732 layer()->SetVisible(visible);
733 visible_ = visible;
734 SchedulePaint();
735 if (parent_ && parent_->layout_manager_)
736 parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible);
738 if (delegate_)
739 delegate_->OnWindowTargetVisibilityChanged(visible);
741 NotifyWindowVisibilityChanged(this, visible);
744 void Window::SchedulePaint() {
745 SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height()));
748 void Window::Paint(const ui::PaintContext& context) {
749 if (delegate_)
750 delegate_->OnPaint(context);
753 Window* Window::GetWindowForPoint(const gfx::Point& local_point,
754 bool return_tightest,
755 bool for_event_handling) {
756 if (!IsVisible())
757 return NULL;
759 if ((for_event_handling && !HitTest(local_point)) ||
760 (!for_event_handling && !ContainsPoint(local_point)))
761 return NULL;
763 // Check if I should claim this event and not pass it to my children because
764 // the location is inside my hit test override area. For details, see
765 // set_hit_test_bounds_override_inner().
766 if (for_event_handling && !hit_test_bounds_override_inner_.empty()) {
767 gfx::Rect inset_local_bounds(gfx::Point(), bounds().size());
768 inset_local_bounds.Inset(hit_test_bounds_override_inner_);
769 // We know we're inside the normal local bounds, so if we're outside the
770 // inset bounds we must be in the special hit test override area.
771 DCHECK(HitTest(local_point));
772 if (!inset_local_bounds.Contains(local_point))
773 return delegate_ ? this : NULL;
776 if (!return_tightest && delegate_)
777 return this;
779 for (Windows::const_reverse_iterator it = children_.rbegin(),
780 rend = children_.rend();
781 it != rend; ++it) {
782 Window* child = *it;
784 if (for_event_handling) {
785 if (child->ignore_events_)
786 continue;
787 // The client may not allow events to be processed by certain subtrees.
788 client::EventClient* client = client::GetEventClient(GetRootWindow());
789 if (client && !client->CanProcessEventsWithinSubtree(child))
790 continue;
791 if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling(
792 child, local_point))
793 continue;
796 gfx::Point point_in_child_coords(local_point);
797 ConvertPointToTarget(this, child, &point_in_child_coords);
798 Window* match = child->GetWindowForPoint(point_in_child_coords,
799 return_tightest,
800 for_event_handling);
801 if (match)
802 return match;
805 return delegate_ ? this : NULL;
808 void Window::RemoveChildImpl(Window* child, Window* new_parent) {
809 if (layout_manager_)
810 layout_manager_->OnWillRemoveWindowFromLayout(child);
811 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child));
812 Window* root_window = child->GetRootWindow();
813 Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL;
814 if (root_window && root_window != new_root_window)
815 child->NotifyRemovingFromRootWindow(new_root_window);
817 if (child->OwnsLayer())
818 layer()->Remove(child->layer());
819 child->parent_ = NULL;
820 Windows::iterator i = std::find(children_.begin(), children_.end(), child);
821 DCHECK(i != children_.end());
822 children_.erase(i);
823 child->OnParentChanged();
824 if (layout_manager_)
825 layout_manager_->OnWindowRemovedFromLayout(child);
828 void Window::OnParentChanged() {
829 FOR_EACH_OBSERVER(
830 WindowObserver, observers_, OnWindowParentChanged(this, parent_));
833 void Window::StackChildRelativeTo(Window* child,
834 Window* target,
835 StackDirection direction) {
836 DCHECK_NE(child, target);
837 DCHECK(child);
838 DCHECK(target);
839 DCHECK_EQ(this, child->parent());
840 DCHECK_EQ(this, target->parent());
842 client::WindowStackingClient* stacking_client =
843 client::GetWindowStackingClient();
844 if (stacking_client &&
845 !stacking_client->AdjustStacking(&child, &target, &direction))
846 return;
848 const size_t child_i =
849 std::find(children_.begin(), children_.end(), child) - children_.begin();
850 const size_t target_i =
851 std::find(children_.begin(), children_.end(), target) - children_.begin();
853 // Don't move the child if it is already in the right place.
854 if ((direction == STACK_ABOVE && child_i == target_i + 1) ||
855 (direction == STACK_BELOW && child_i + 1 == target_i))
856 return;
858 const size_t dest_i =
859 direction == STACK_ABOVE ?
860 (child_i < target_i ? target_i : target_i + 1) :
861 (child_i < target_i ? target_i - 1 : target_i);
862 children_.erase(children_.begin() + child_i);
863 children_.insert(children_.begin() + dest_i, child);
865 StackChildLayerRelativeTo(child, target, direction);
867 child->OnStackingChanged();
870 void Window::StackChildLayerRelativeTo(Window* child,
871 Window* target,
872 StackDirection direction) {
873 DCHECK(layer() && child->layer() && target->layer());
874 if (direction == STACK_ABOVE)
875 layer()->StackAbove(child->layer(), target->layer());
876 else
877 layer()->StackBelow(child->layer(), target->layer());
880 void Window::OnStackingChanged() {
881 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
884 void Window::NotifyRemovingFromRootWindow(Window* new_root) {
885 FOR_EACH_OBSERVER(WindowObserver, observers_,
886 OnWindowRemovingFromRootWindow(this, new_root));
887 for (Window::Windows::const_iterator it = children_.begin();
888 it != children_.end(); ++it) {
889 (*it)->NotifyRemovingFromRootWindow(new_root);
893 void Window::NotifyAddedToRootWindow() {
894 FOR_EACH_OBSERVER(WindowObserver, observers_,
895 OnWindowAddedToRootWindow(this));
896 for (Window::Windows::const_iterator it = children_.begin();
897 it != children_.end(); ++it) {
898 (*it)->NotifyAddedToRootWindow();
902 void Window::NotifyWindowHierarchyChange(
903 const WindowObserver::HierarchyChangeParams& params) {
904 params.target->NotifyWindowHierarchyChangeDown(params);
905 switch (params.phase) {
906 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
907 if (params.old_parent)
908 params.old_parent->NotifyWindowHierarchyChangeUp(params);
909 break;
910 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
911 if (params.new_parent)
912 params.new_parent->NotifyWindowHierarchyChangeUp(params);
913 break;
914 default:
915 NOTREACHED();
916 break;
920 void Window::NotifyWindowHierarchyChangeDown(
921 const WindowObserver::HierarchyChangeParams& params) {
922 NotifyWindowHierarchyChangeAtReceiver(params);
923 for (Window::Windows::const_iterator it = children_.begin();
924 it != children_.end(); ++it) {
925 (*it)->NotifyWindowHierarchyChangeDown(params);
929 void Window::NotifyWindowHierarchyChangeUp(
930 const WindowObserver::HierarchyChangeParams& params) {
931 for (Window* window = this; window; window = window->parent())
932 window->NotifyWindowHierarchyChangeAtReceiver(params);
935 void Window::NotifyWindowHierarchyChangeAtReceiver(
936 const WindowObserver::HierarchyChangeParams& params) {
937 WindowObserver::HierarchyChangeParams local_params = params;
938 local_params.receiver = this;
940 switch (params.phase) {
941 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
942 FOR_EACH_OBSERVER(WindowObserver, observers_,
943 OnWindowHierarchyChanging(local_params));
944 break;
945 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
946 FOR_EACH_OBSERVER(WindowObserver, observers_,
947 OnWindowHierarchyChanged(local_params));
948 break;
949 default:
950 NOTREACHED();
951 break;
955 void Window::NotifyWindowVisibilityChanged(aura::Window* target,
956 bool visible) {
957 if (!NotifyWindowVisibilityChangedDown(target, visible)) {
958 return; // |this| has been deleted.
960 NotifyWindowVisibilityChangedUp(target, visible);
963 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target,
964 bool visible) {
965 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one
966 // of the observers. We create an local observer for that. In that case we
967 // exit without further access to any members.
968 WindowTracker tracker;
969 tracker.Add(this);
970 FOR_EACH_OBSERVER(WindowObserver, observers_,
971 OnWindowVisibilityChanged(target, visible));
972 return tracker.Contains(this);
975 bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target,
976 bool visible) {
977 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible))
978 return false; // |this| was deleted.
979 std::set<const Window*> child_already_processed;
980 bool child_destroyed = false;
981 do {
982 child_destroyed = false;
983 for (Window::Windows::const_iterator it = children_.begin();
984 it != children_.end(); ++it) {
985 if (!child_already_processed.insert(*it).second)
986 continue;
987 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) {
988 // |*it| was deleted, |it| is invalid and |children_| has changed.
989 // We exit the current for-loop and enter a new one.
990 child_destroyed = true;
991 break;
994 } while (child_destroyed);
995 return true;
998 void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
999 bool visible) {
1000 // Start with the parent as we already notified |this|
1001 // in NotifyWindowVisibilityChangedDown.
1002 for (Window* window = parent(); window; window = window->parent()) {
1003 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible);
1004 DCHECK(ret);
1008 void Window::NotifyAncestorWindowTransformed(Window* source) {
1009 FOR_EACH_OBSERVER(WindowObserver, observers_,
1010 OnAncestorWindowTransformed(source, this));
1011 for (Window::Windows::const_iterator it = children_.begin();
1012 it != children_.end(); ++it) {
1013 (*it)->NotifyAncestorWindowTransformed(source);
1017 void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds) {
1018 bounds_ = layer()->bounds();
1019 if (layout_manager_)
1020 layout_manager_->OnWindowResized();
1021 if (delegate_)
1022 delegate_->OnBoundsChanged(old_bounds, bounds());
1023 FOR_EACH_OBSERVER(WindowObserver,
1024 observers_,
1025 OnWindowBoundsChanged(this, old_bounds, bounds()));
1028 bool Window::CleanupGestureState() {
1029 bool state_modified = false;
1030 state_modified |= ui::GestureRecognizer::Get()->CancelActiveTouches(this);
1031 state_modified |=
1032 ui::GestureRecognizer::Get()->CleanupStateForConsumer(this);
1033 for (Window::Windows::iterator iter = children_.begin();
1034 iter != children_.end();
1035 ++iter) {
1036 state_modified |= (*iter)->CleanupGestureState();
1038 return state_modified;
1041 void Window::OnPaintLayer(const ui::PaintContext& context) {
1042 Paint(context);
1045 void Window::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
1046 DCHECK(layer());
1047 FOR_EACH_OBSERVER(WindowObserver,
1048 observers_,
1049 OnDelegatedFrameDamage(this, damage_rect_in_dip));
1052 base::Closure Window::PrepareForLayerBoundsChange() {
1053 return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
1054 bounds());
1057 bool Window::CanAcceptEvent(const ui::Event& event) {
1058 // The client may forbid certain windows from receiving events at a given
1059 // point in time.
1060 client::EventClient* client = client::GetEventClient(GetRootWindow());
1061 if (client && !client->CanProcessEventsWithinSubtree(this))
1062 return false;
1064 // We need to make sure that a touch cancel event and any gesture events it
1065 // creates can always reach the window. This ensures that we receive a valid
1066 // touch / gesture stream.
1067 if (event.IsEndingEvent())
1068 return true;
1070 if (!IsVisible())
1071 return false;
1073 // The top-most window can always process an event.
1074 if (!parent_)
1075 return true;
1077 // For located events (i.e. mouse, touch etc.), an assumption is made that
1078 // windows that don't have a default event-handler cannot process the event
1079 // (see more in GetWindowForPoint()). This assumption is not made for key
1080 // events.
1081 return event.IsKeyEvent() || target_handler();
1084 ui::EventTarget* Window::GetParentTarget() {
1085 if (IsRootWindow()) {
1086 return client::GetEventClient(this) ?
1087 client::GetEventClient(this)->GetToplevelEventTarget() :
1088 Env::GetInstance();
1090 return parent_;
1093 scoped_ptr<ui::EventTargetIterator> Window::GetChildIterator() const {
1094 return make_scoped_ptr(new ui::EventTargetIteratorImpl<Window>(children()));
1097 ui::EventTargeter* Window::GetEventTargeter() {
1098 return targeter_.get();
1101 void Window::ConvertEventToTarget(ui::EventTarget* target,
1102 ui::LocatedEvent* event) {
1103 event->ConvertLocationToTarget(this,
1104 static_cast<Window*>(target));
1107 void Window::UpdateLayerName() {
1108 #if !defined(NDEBUG)
1109 DCHECK(layer());
1111 std::string layer_name(name_);
1112 if (layer_name.empty())
1113 layer_name = "Unnamed Window";
1115 if (id_ != -1)
1116 layer_name += " " + base::IntToString(id_);
1118 layer()->set_name(layer_name);
1119 #endif
1122 } // namespace aura