1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/aura/window.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/logging.h"
13 #include "base/stl_util.h"
14 #include "base/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/root_window.h"
27 #include "ui/aura/window_delegate.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/animation/multi_animation.h"
35 #include "ui/gfx/canvas.h"
36 #include "ui/gfx/path.h"
37 #include "ui/gfx/scoped_canvas.h"
38 #include "ui/gfx/screen.h"
39
40 namespace aura {
41
42 namespace {
43
UILayerTypeToWindowLayerType(ui::LayerType layer_type)44 WindowLayerType UILayerTypeToWindowLayerType(ui::LayerType layer_type) {
45 switch (layer_type) {
46 case ui::LAYER_NOT_DRAWN:
47 return WINDOW_LAYER_NOT_DRAWN;
48 case ui::LAYER_TEXTURED:
49 return WINDOW_LAYER_TEXTURED;
50 case ui::LAYER_SOLID_COLOR:
51 return WINDOW_LAYER_SOLID_COLOR;
52 }
53 NOTREACHED();
54 return WINDOW_LAYER_NOT_DRAWN;
55 }
56
WindowLayerTypeToUILayerType(WindowLayerType window_layer_type)57 ui::LayerType WindowLayerTypeToUILayerType(WindowLayerType window_layer_type) {
58 switch (window_layer_type) {
59 case WINDOW_LAYER_NONE:
60 break;
61 case WINDOW_LAYER_NOT_DRAWN:
62 return ui::LAYER_NOT_DRAWN;
63 case WINDOW_LAYER_TEXTURED:
64 return ui::LAYER_TEXTURED;
65 case WINDOW_LAYER_SOLID_COLOR:
66 return ui::LAYER_SOLID_COLOR;
67 }
68 NOTREACHED();
69 return ui::LAYER_NOT_DRAWN;
70 }
71
72 // Used when searching for a Window to stack relative to.
73 template <class T>
74 T IteratorForDirectionBegin(aura::Window* window);
75
76 template <>
IteratorForDirectionBegin(aura::Window * window)77 Window::Windows::const_iterator IteratorForDirectionBegin(
78 aura::Window* window) {
79 return window->children().begin();
80 }
81
82 template <>
IteratorForDirectionBegin(aura::Window * window)83 Window::Windows::const_reverse_iterator IteratorForDirectionBegin(
84 aura::Window* window) {
85 return window->children().rbegin();
86 }
87
88 template <class T>
89 T IteratorForDirectionEnd(aura::Window* window);
90
91 template <>
IteratorForDirectionEnd(aura::Window * window)92 Window::Windows::const_iterator IteratorForDirectionEnd(aura::Window* window) {
93 return window->children().end();
94 }
95
96 template <>
IteratorForDirectionEnd(aura::Window * window)97 Window::Windows::const_reverse_iterator IteratorForDirectionEnd(
98 aura::Window* window) {
99 return window->children().rend();
100 }
101
102 // Depth first search for the first Window with a layer to stack relative
103 // to. Starts at target. Does not descend into |ignore|.
104 template <class T>
FindStackingTargetLayerDown(aura::Window * target,aura::Window * ignore)105 ui::Layer* FindStackingTargetLayerDown(aura::Window* target,
106 aura::Window* ignore) {
107 if (target == ignore)
108 return NULL;
109
110 if (target->layer())
111 return target->layer();
112
113 for (T i = IteratorForDirectionBegin<T>(target);
114 i != IteratorForDirectionEnd<T>(target); ++i) {
115 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore);
116 if (layer)
117 return layer;
118 }
119 return NULL;
120 }
121
122 // Depth first search through the siblings of |target||. This does not search
123 // all the siblings, only those before/after |target| (depening upon the
124 // template type) and ignoring |ignore|. Returns the Layer of the first Window
125 // encountered with a Layer.
126 template <class T>
FindStackingLayerInSiblings(aura::Window * target,aura::Window * ignore)127 ui::Layer* FindStackingLayerInSiblings(aura::Window* target,
128 aura::Window* ignore) {
129 aura::Window* parent = target->parent();
130 for (T i = std::find(IteratorForDirectionBegin<T>(parent),
131 IteratorForDirectionEnd<T>(parent), target);
132 i != IteratorForDirectionEnd<T>(parent); ++i) {
133 ui::Layer* layer = FindStackingTargetLayerDown<T>(*i, ignore);
134 if (layer)
135 return layer;
136 }
137 return NULL;
138 }
139
140 // Returns the first Window that has a Layer. This does a depth first search
141 // through the descendants of |target| first, then ascends up doing a depth
142 // first search through siblings of all ancestors until a Layer is found or an
143 // ancestor with a layer is found. This is intended to locate a layer to stack
144 // other layers relative to.
145 template <class T>
FindStackingTargetLayer(aura::Window * target,aura::Window * ignore)146 ui::Layer* FindStackingTargetLayer(aura::Window* target, aura::Window* ignore) {
147 ui::Layer* result = FindStackingTargetLayerDown<T>(target, ignore);
148 if (result)
149 return result;
150 while (target->parent()) {
151 ui::Layer* result = FindStackingLayerInSiblings<T>(target, ignore);
152 if (result)
153 return result;
154 target = target->parent();
155 if (target->layer())
156 return NULL;
157 }
158 return NULL;
159 }
160
161 // Does a depth first search for all descendants of |child| that have layers.
162 // This stops at any descendants that have layers (and adds them to |layers|).
GetLayersToStack(aura::Window * child,std::vector<ui::Layer * > * layers)163 void GetLayersToStack(aura::Window* child, std::vector<ui::Layer*>* layers) {
164 if (child->layer()) {
165 layers->push_back(child->layer());
166 return;
167 }
168 for (size_t i = 0; i < child->children().size(); ++i)
169 GetLayersToStack(child->children()[i], layers);
170 }
171
172 } // namespace
173
174 class ScopedCursorHider {
175 public:
ScopedCursorHider(Window * window)176 explicit ScopedCursorHider(Window* window)
177 : window_(window),
178 hid_cursor_(false) {
179 if (!window_->HasDispatcher())
180 return;
181 const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
182 Env::GetInstance()->last_mouse_location());
183 client::CursorClient* cursor_client = client::GetCursorClient(window_);
184 if (cursor_is_in_bounds && cursor_client &&
185 cursor_client->IsCursorVisible()) {
186 cursor_client->HideCursor();
187 hid_cursor_ = true;
188 }
189 }
~ScopedCursorHider()190 ~ScopedCursorHider() {
191 if (!window_->HasDispatcher())
192 return;
193
194 // Update the device scale factor of the cursor client only when the last
195 // mouse location is on this root window.
196 if (hid_cursor_) {
197 client::CursorClient* cursor_client = client::GetCursorClient(window_);
198 if (cursor_client) {
199 const gfx::Display& display =
200 gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(
201 window_);
202 cursor_client->SetDisplay(display);
203 cursor_client->ShowCursor();
204 }
205 }
206 }
207
208 private:
209 Window* window_;
210 bool hid_cursor_;
211
212 DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider);
213 };
214
Window(WindowDelegate * delegate)215 Window::Window(WindowDelegate* delegate)
216 : dispatcher_(NULL),
217 type_(client::WINDOW_TYPE_UNKNOWN),
218 owned_by_parent_(true),
219 delegate_(delegate),
220 parent_(NULL),
221 transient_parent_(NULL),
222 visible_(false),
223 id_(-1),
224 transparent_(false),
225 user_data_(NULL),
226 ignore_events_(false),
227 // Don't notify newly added observers during notification. This causes
228 // problems for code that adds an observer as part of an observer
229 // notification (such as the workspace code).
230 observers_(ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) {
231 set_target_handler(delegate_);
232 }
233
~Window()234 Window::~Window() {
235 // |layer_| can be NULL during tests, or if this Window is layerless.
236 if (layer_)
237 layer_->SuppressPaint();
238
239 // Let the delegate know we're in the processing of destroying.
240 if (delegate_)
241 delegate_->OnWindowDestroying();
242 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this));
243
244 // Let the root know so that it can remove any references to us.
245 WindowEventDispatcher* dispatcher = GetDispatcher();
246 if (dispatcher)
247 dispatcher->OnWindowDestroying(this);
248
249 // Then destroy the children.
250 RemoveOrDestroyChildren();
251
252 // Removes ourselves from our transient parent (if it hasn't been done by the
253 // RootWindow).
254 if (transient_parent_)
255 transient_parent_->RemoveTransientChild(this);
256
257 // The window needs to be removed from the parent before calling the
258 // WindowDestroyed callbacks of delegate and the observers.
259 if (parent_)
260 parent_->RemoveChild(this);
261
262 // Destroy transient children, only after we've removed ourselves from our
263 // parent, as destroying an active transient child may otherwise attempt to
264 // refocus us.
265 Windows transient_children(transient_children_);
266 STLDeleteElements(&transient_children);
267 DCHECK(transient_children_.empty());
268
269 // Delegate and observers need to be notified after transients are deleted.
270 if (delegate_)
271 delegate_->OnWindowDestroyed();
272 ObserverListBase<WindowObserver>::Iterator iter(observers_);
273 WindowObserver* observer;
274 while ((observer = iter.GetNext())) {
275 RemoveObserver(observer);
276 observer->OnWindowDestroyed(this);
277 }
278
279 // Clear properties.
280 for (std::map<const void*, Value>::const_iterator iter = prop_map_.begin();
281 iter != prop_map_.end();
282 ++iter) {
283 if (iter->second.deallocator)
284 (*iter->second.deallocator)(iter->second.value);
285 }
286 prop_map_.clear();
287
288 // If we have layer it will either be destroyed by |layer_owner_|'s dtor, or
289 // by whoever acquired it. We don't have a layer if Init() wasn't invoked or
290 // we are layerless.
291 if (layer_) {
292 layer_->set_delegate(NULL);
293 layer_ = NULL;
294 }
295 }
296
Init(ui::LayerType layer_type)297 void Window::Init(ui::LayerType layer_type) {
298 InitWithWindowLayerType(UILayerTypeToWindowLayerType(layer_type));
299 }
300
InitWithWindowLayerType(WindowLayerType window_layer_type)301 void Window::InitWithWindowLayerType(WindowLayerType window_layer_type) {
302 if (window_layer_type != WINDOW_LAYER_NONE) {
303 layer_ = new ui::Layer(WindowLayerTypeToUILayerType(window_layer_type));
304 layer_owner_.reset(layer_);
305 layer_->SetVisible(false);
306 layer_->set_delegate(this);
307 UpdateLayerName(name_);
308 layer_->SetFillsBoundsOpaquely(!transparent_);
309 }
310
311 Env::GetInstance()->NotifyWindowInitialized(this);
312 }
313
RecreateLayer()314 ui::Layer* Window::RecreateLayer() {
315 // Disconnect the old layer, but don't delete it.
316 ui::Layer* old_layer = AcquireLayer();
317 if (!old_layer)
318 return NULL;
319
320 old_layer->set_delegate(NULL);
321
322 layer_ = new ui::Layer(old_layer->type());
323 layer_owner_.reset(layer_);
324 layer_->SetVisible(old_layer->visible());
325 layer_->set_scale_content(old_layer->scale_content());
326 layer_->set_delegate(this);
327 layer_->SetMasksToBounds(old_layer->GetMasksToBounds());
328
329 if (delegate_)
330 delegate_->DidRecreateLayer(old_layer, layer_);
331
332 UpdateLayerName(name_);
333 layer_->SetFillsBoundsOpaquely(!transparent_);
334 // Install new layer as a sibling of the old layer, stacked below it.
335 if (old_layer->parent()) {
336 old_layer->parent()->Add(layer_);
337 old_layer->parent()->StackBelow(layer_, old_layer);
338 }
339 // Migrate all the child layers over to the new layer. Copy the list because
340 // the items are removed during iteration.
341 std::vector<ui::Layer*> children_copy = old_layer->children();
342 for (std::vector<ui::Layer*>::const_iterator it = children_copy.begin();
343 it != children_copy.end();
344 ++it) {
345 ui::Layer* child = *it;
346 layer_->Add(child);
347 }
348 return old_layer;
349 }
350
SetType(client::WindowType type)351 void Window::SetType(client::WindowType type) {
352 // Cannot change type after the window is initialized.
353 DCHECK(!layer_);
354 type_ = type;
355 }
356
SetName(const std::string & name)357 void Window::SetName(const std::string& name) {
358 name_ = name;
359
360 if (layer_)
361 UpdateLayerName(name_);
362 }
363
SetTransparent(bool transparent)364 void Window::SetTransparent(bool transparent) {
365 transparent_ = transparent;
366 if (layer_)
367 layer_->SetFillsBoundsOpaquely(!transparent_);
368 }
369
GetRootWindow()370 Window* Window::GetRootWindow() {
371 return const_cast<Window*>(
372 static_cast<const Window*>(this)->GetRootWindow());
373 }
374
GetRootWindow() const375 const Window* Window::GetRootWindow() const {
376 return dispatcher_ ? this : parent_ ? parent_->GetRootWindow() : NULL;
377 }
378
GetDispatcher()379 WindowEventDispatcher* Window::GetDispatcher() {
380 return const_cast<WindowEventDispatcher*>(const_cast<const Window*>(this)->
381 GetDispatcher());
382 }
383
GetDispatcher() const384 const WindowEventDispatcher* Window::GetDispatcher() const {
385 const Window* root_window = GetRootWindow();
386 return root_window ? root_window->dispatcher_ : NULL;
387 }
388
Show()389 void Window::Show() {
390 SetVisible(true);
391 }
392
Hide()393 void Window::Hide() {
394 for (Windows::iterator it = transient_children_.begin();
395 it != transient_children_.end(); ++it) {
396 (*it)->Hide();
397 }
398 SetVisible(false);
399 ReleaseCapture();
400 }
401
IsVisible() const402 bool Window::IsVisible() const {
403 // Layer visibility can be inconsistent with window visibility, for example
404 // when a Window is hidden, we want this function to return false immediately
405 // after, even though the client may decide to animate the hide effect (and
406 // so the layer will be visible for some time after Hide() is called).
407 for (const Window* window = this; window; window = window->parent()) {
408 if (!window->visible_)
409 return false;
410 if (window->layer_)
411 return window->layer_->IsDrawn();
412 }
413 return false;
414 }
415
GetBoundsInRootWindow() const416 gfx::Rect Window::GetBoundsInRootWindow() const {
417 // TODO(beng): There may be a better way to handle this, and the existing code
418 // is likely wrong anyway in a multi-display world, but this will
419 // do for now.
420 if (!GetRootWindow())
421 return bounds();
422 gfx::Point origin = bounds().origin();
423 ConvertPointToTarget(parent_, GetRootWindow(), &origin);
424 return gfx::Rect(origin, bounds().size());
425 }
426
GetBoundsInScreen() const427 gfx::Rect Window::GetBoundsInScreen() const {
428 gfx::Rect bounds(GetBoundsInRootWindow());
429 const Window* root = GetRootWindow();
430 if (root) {
431 aura::client::ScreenPositionClient* screen_position_client =
432 aura::client::GetScreenPositionClient(root);
433 if (screen_position_client) {
434 gfx::Point origin = bounds.origin();
435 screen_position_client->ConvertPointToScreen(root, &origin);
436 bounds.set_origin(origin);
437 }
438 }
439 return bounds;
440 }
441
SetTransform(const gfx::Transform & transform)442 void Window::SetTransform(const gfx::Transform& transform) {
443 if (!layer_) {
444 // Transforms aren't supported on layerless windows.
445 NOTREACHED();
446 return;
447 }
448 WindowEventDispatcher* dispatcher = GetDispatcher();
449 bool contained_mouse = IsVisible() && dispatcher &&
450 ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
451 layer_->SetTransform(transform);
452 if (dispatcher)
453 dispatcher->OnWindowTransformed(this, contained_mouse);
454 }
455
SetLayoutManager(LayoutManager * layout_manager)456 void Window::SetLayoutManager(LayoutManager* layout_manager) {
457 if (layout_manager == layout_manager_)
458 return;
459 layout_manager_.reset(layout_manager);
460 if (!layout_manager)
461 return;
462 // If we're changing to a new layout manager, ensure it is aware of all the
463 // existing child windows.
464 for (Windows::const_iterator it = children_.begin();
465 it != children_.end();
466 ++it)
467 layout_manager_->OnWindowAddedToLayout(*it);
468 }
469
SetBounds(const gfx::Rect & new_bounds)470 void Window::SetBounds(const gfx::Rect& new_bounds) {
471 if (parent_ && parent_->layout_manager())
472 parent_->layout_manager()->SetChildBounds(this, new_bounds);
473 else
474 SetBoundsInternal(new_bounds);
475 }
476
SetBoundsInScreen(const gfx::Rect & new_bounds_in_screen,const gfx::Display & dst_display)477 void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
478 const gfx::Display& dst_display) {
479 Window* root = GetRootWindow();
480 if (root) {
481 gfx::Point origin = new_bounds_in_screen.origin();
482 aura::client::ScreenPositionClient* screen_position_client =
483 aura::client::GetScreenPositionClient(root);
484 screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display);
485 return;
486 }
487 SetBounds(new_bounds_in_screen);
488 }
489
GetTargetBounds() const490 gfx::Rect Window::GetTargetBounds() const {
491 if (!layer_)
492 return bounds();
493
494 if (!parent_ || parent_->layer_)
495 return layer_->GetTargetBounds();
496
497 // We have a layer but our parent (who is valid) doesn't. This means the
498 // coordinates of the layer are relative to the first ancestor with a layer;
499 // convert to be relative to parent.
500 gfx::Vector2d offset;
501 const aura::Window* ancestor_with_layer =
502 parent_->GetAncestorWithLayer(&offset);
503 if (!ancestor_with_layer)
504 return layer_->GetTargetBounds();
505
506 gfx::Rect layer_target_bounds = layer_->GetTargetBounds();
507 layer_target_bounds -= offset;
508 return layer_target_bounds;
509 }
510
SchedulePaintInRect(const gfx::Rect & rect)511 void Window::SchedulePaintInRect(const gfx::Rect& rect) {
512 if (!layer_ && parent_) {
513 // Notification of paint scheduled happens for the window with a layer.
514 gfx::Rect parent_rect(bounds().size());
515 parent_rect.Intersect(rect);
516 if (!parent_rect.IsEmpty()) {
517 parent_rect.Offset(bounds().origin().OffsetFromOrigin());
518 parent_->SchedulePaintInRect(parent_rect);
519 }
520 } else if (layer_ && layer_->SchedulePaint(rect)) {
521 FOR_EACH_OBSERVER(
522 WindowObserver, observers_, OnWindowPaintScheduled(this, rect));
523 }
524 }
525
StackChildAtTop(Window * child)526 void Window::StackChildAtTop(Window* child) {
527 if (children_.size() <= 1 || child == children_.back())
528 return; // In the front already.
529 StackChildAbove(child, children_.back());
530 }
531
StackChildAbove(Window * child,Window * target)532 void Window::StackChildAbove(Window* child, Window* target) {
533 StackChildRelativeTo(child, target, STACK_ABOVE);
534 }
535
StackChildAtBottom(Window * child)536 void Window::StackChildAtBottom(Window* child) {
537 if (children_.size() <= 1 || child == children_.front())
538 return; // At the bottom already.
539 StackChildBelow(child, children_.front());
540 }
541
StackChildBelow(Window * child,Window * target)542 void Window::StackChildBelow(Window* child, Window* target) {
543 StackChildRelativeTo(child, target, STACK_BELOW);
544 }
545
AddChild(Window * child)546 void Window::AddChild(Window* child) {
547 WindowObserver::HierarchyChangeParams params;
548 params.target = child;
549 params.new_parent = this;
550 params.old_parent = child->parent();
551 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
552 NotifyWindowHierarchyChange(params);
553
554 Window* old_root = child->GetRootWindow();
555
556 DCHECK(std::find(children_.begin(), children_.end(), child) ==
557 children_.end());
558 if (child->parent())
559 child->parent()->RemoveChildImpl(child, this);
560
561 gfx::Vector2d offset;
562 aura::Window* ancestor_with_layer = GetAncestorWithLayer(&offset);
563 if (ancestor_with_layer) {
564 offset += child->bounds().OffsetFromOrigin();
565 child->ReparentLayers(ancestor_with_layer->layer(), offset);
566 }
567
568 child->parent_ = this;
569
570 children_.push_back(child);
571 if (layout_manager_)
572 layout_manager_->OnWindowAddedToLayout(child);
573 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowAdded(child));
574 child->OnParentChanged();
575
576 Window* root_window = GetRootWindow();
577 if (root_window && old_root != root_window) {
578 root_window->GetDispatcher()->OnWindowAddedToRootWindow(child);
579 child->NotifyAddedToRootWindow();
580 }
581
582 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
583 NotifyWindowHierarchyChange(params);
584 }
585
RemoveChild(Window * child)586 void Window::RemoveChild(Window* child) {
587 WindowObserver::HierarchyChangeParams params;
588 params.target = child;
589 params.new_parent = NULL;
590 params.old_parent = this;
591 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
592 NotifyWindowHierarchyChange(params);
593
594 RemoveChildImpl(child, NULL);
595
596 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
597 NotifyWindowHierarchyChange(params);
598 }
599
Contains(const Window * other) const600 bool Window::Contains(const Window* other) const {
601 for (const Window* parent = other; parent; parent = parent->parent_) {
602 if (parent == this)
603 return true;
604 }
605 return false;
606 }
607
AddTransientChild(Window * child)608 void Window::AddTransientChild(Window* child) {
609 if (child->transient_parent_)
610 child->transient_parent_->RemoveTransientChild(child);
611 DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
612 child) == transient_children_.end());
613 transient_children_.push_back(child);
614 child->transient_parent_ = this;
615 FOR_EACH_OBSERVER(WindowObserver, observers_,
616 OnAddTransientChild(this, child));
617 }
618
RemoveTransientChild(Window * child)619 void Window::RemoveTransientChild(Window* child) {
620 Windows::iterator i =
621 std::find(transient_children_.begin(), transient_children_.end(), child);
622 DCHECK(i != transient_children_.end());
623 transient_children_.erase(i);
624 if (child->transient_parent_ == this)
625 child->transient_parent_ = NULL;
626 FOR_EACH_OBSERVER(WindowObserver, observers_,
627 OnRemoveTransientChild(this, child));
628 }
629
GetChildById(int id)630 Window* Window::GetChildById(int id) {
631 return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id));
632 }
633
GetChildById(int id) const634 const Window* Window::GetChildById(int id) const {
635 Windows::const_iterator i;
636 for (i = children_.begin(); i != children_.end(); ++i) {
637 if ((*i)->id() == id)
638 return *i;
639 const Window* result = (*i)->GetChildById(id);
640 if (result)
641 return result;
642 }
643 return NULL;
644 }
645
646 // static
ConvertPointToTarget(const Window * source,const Window * target,gfx::Point * point)647 void Window::ConvertPointToTarget(const Window* source,
648 const Window* target,
649 gfx::Point* point) {
650 if (!source)
651 return;
652 if (source->GetRootWindow() != target->GetRootWindow()) {
653 client::ScreenPositionClient* source_client =
654 client::GetScreenPositionClient(source->GetRootWindow());
655 source_client->ConvertPointToScreen(source, point);
656
657 client::ScreenPositionClient* target_client =
658 client::GetScreenPositionClient(target->GetRootWindow());
659 target_client->ConvertPointFromScreen(target, point);
660 } else if ((source != target) && (!source->layer_ || !target->layer_)) {
661 if (!source->layer_) {
662 gfx::Vector2d offset_to_layer;
663 source = source->GetAncestorWithLayer(&offset_to_layer);
664 *point += offset_to_layer;
665 }
666 if (!target->layer_) {
667 gfx::Vector2d offset_to_layer;
668 target = target->GetAncestorWithLayer(&offset_to_layer);
669 *point -= offset_to_layer;
670 }
671 ui::Layer::ConvertPointToLayer(source->layer_, target->layer_, point);
672 } else {
673 ui::Layer::ConvertPointToLayer(source->layer_, target->layer_, point);
674 }
675 }
676
MoveCursorTo(const gfx::Point & point_in_window)677 void Window::MoveCursorTo(const gfx::Point& point_in_window) {
678 Window* root_window = GetRootWindow();
679 DCHECK(root_window);
680 gfx::Point point_in_root(point_in_window);
681 ConvertPointToTarget(this, root_window, &point_in_root);
682 root_window->GetDispatcher()->MoveCursorTo(point_in_root);
683 }
684
GetCursor(const gfx::Point & point) const685 gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const {
686 return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor;
687 }
688
SetEventFilter(ui::EventHandler * event_filter)689 void Window::SetEventFilter(ui::EventHandler* event_filter) {
690 if (event_filter_)
691 RemovePreTargetHandler(event_filter_.get());
692 event_filter_.reset(event_filter);
693 if (event_filter)
694 AddPreTargetHandler(event_filter);
695 }
696
AddObserver(WindowObserver * observer)697 void Window::AddObserver(WindowObserver* observer) {
698 observers_.AddObserver(observer);
699 }
700
RemoveObserver(WindowObserver * observer)701 void Window::RemoveObserver(WindowObserver* observer) {
702 observers_.RemoveObserver(observer);
703 }
704
HasObserver(WindowObserver * observer)705 bool Window::HasObserver(WindowObserver* observer) {
706 return observers_.HasObserver(observer);
707 }
708
ContainsPointInRoot(const gfx::Point & point_in_root) const709 bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const {
710 const Window* root_window = GetRootWindow();
711 if (!root_window)
712 return false;
713 gfx::Point local_point(point_in_root);
714 ConvertPointToTarget(root_window, this, &local_point);
715 return gfx::Rect(GetTargetBounds().size()).Contains(local_point);
716 }
717
ContainsPoint(const gfx::Point & local_point) const718 bool Window::ContainsPoint(const gfx::Point& local_point) const {
719 return gfx::Rect(bounds().size()).Contains(local_point);
720 }
721
HitTest(const gfx::Point & local_point)722 bool Window::HitTest(const gfx::Point& local_point) {
723 // Expand my bounds for hit testing (override is usually zero but it's
724 // probably cheaper to do the math every time than to branch).
725 gfx::Rect local_bounds(gfx::Point(), bounds().size());
726 local_bounds.Inset(aura::Env::GetInstance()->is_touch_down() ?
727 hit_test_bounds_override_outer_touch_ :
728 hit_test_bounds_override_outer_mouse_);
729
730 if (!delegate_ || !delegate_->HasHitTestMask())
731 return local_bounds.Contains(local_point);
732
733 gfx::Path mask;
734 delegate_->GetHitTestMask(&mask);
735
736 SkRegion clip_region;
737 clip_region.setRect(local_bounds.x(), local_bounds.y(),
738 local_bounds.width(), local_bounds.height());
739 SkRegion mask_region;
740 return mask_region.setPath(mask, clip_region) &&
741 mask_region.contains(local_point.x(), local_point.y());
742 }
743
GetEventHandlerForPoint(const gfx::Point & local_point)744 Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) {
745 return GetWindowForPoint(local_point, true, true);
746 }
747
GetTopWindowContainingPoint(const gfx::Point & local_point)748 Window* Window::GetTopWindowContainingPoint(const gfx::Point& local_point) {
749 return GetWindowForPoint(local_point, false, false);
750 }
751
GetToplevelWindow()752 Window* Window::GetToplevelWindow() {
753 Window* topmost_window_with_delegate = NULL;
754 for (aura::Window* window = this; window != NULL; window = window->parent()) {
755 if (window->delegate())
756 topmost_window_with_delegate = window;
757 }
758 return topmost_window_with_delegate;
759 }
760
Focus()761 void Window::Focus() {
762 client::FocusClient* client = client::GetFocusClient(this);
763 DCHECK(client);
764 client->FocusWindow(this);
765 }
766
Blur()767 void Window::Blur() {
768 client::FocusClient* client = client::GetFocusClient(this);
769 DCHECK(client);
770 client->FocusWindow(NULL);
771 }
772
HasFocus() const773 bool Window::HasFocus() const {
774 client::FocusClient* client = client::GetFocusClient(this);
775 return client && client->GetFocusedWindow() == this;
776 }
777
CanFocus() const778 bool Window::CanFocus() const {
779 if (dispatcher_)
780 return IsVisible();
781
782 // NOTE: as part of focusing the window the ActivationClient may make the
783 // window visible (by way of making a hidden ancestor visible). For this
784 // reason we can't check visibility here and assume the client is doing it.
785 if (!parent_ || (delegate_ && !delegate_->CanFocus()))
786 return false;
787
788 // The client may forbid certain windows from receiving focus at a given point
789 // in time.
790 client::EventClient* client = client::GetEventClient(GetRootWindow());
791 if (client && !client->CanProcessEventsWithinSubtree(this))
792 return false;
793
794 return parent_->CanFocus();
795 }
796
CanReceiveEvents() const797 bool Window::CanReceiveEvents() const {
798 if (dispatcher_)
799 return IsVisible();
800
801 // The client may forbid certain windows from receiving events at a given
802 // point in time.
803 client::EventClient* client = client::GetEventClient(GetRootWindow());
804 if (client && !client->CanProcessEventsWithinSubtree(this))
805 return false;
806
807 return parent_ && IsVisible() && parent_->CanReceiveEvents();
808 }
809
SetCapture()810 void Window::SetCapture() {
811 if (!IsVisible())
812 return;
813
814 Window* root_window = GetRootWindow();
815 if (!root_window)
816 return;
817 client::GetCaptureClient(root_window)->SetCapture(this);
818 }
819
ReleaseCapture()820 void Window::ReleaseCapture() {
821 Window* root_window = GetRootWindow();
822 if (!root_window)
823 return;
824 client::GetCaptureClient(root_window)->ReleaseCapture(this);
825 }
826
HasCapture()827 bool Window::HasCapture() {
828 Window* root_window = GetRootWindow();
829 if (!root_window)
830 return false;
831 client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
832 return capture_client && capture_client->GetCaptureWindow() == this;
833 }
834
SuppressPaint()835 void Window::SuppressPaint() {
836 if (layer_)
837 layer_->SuppressPaint();
838 }
839
840 // {Set,Get,Clear}Property are implemented in window_property.h.
841
SetNativeWindowProperty(const char * key,void * value)842 void Window::SetNativeWindowProperty(const char* key, void* value) {
843 SetPropertyInternal(
844 key, key, NULL, reinterpret_cast<int64>(value), 0);
845 }
846
GetNativeWindowProperty(const char * key) const847 void* Window::GetNativeWindowProperty(const char* key) const {
848 return reinterpret_cast<void*>(GetPropertyInternal(key, 0));
849 }
850
OnDeviceScaleFactorChanged(float device_scale_factor)851 void Window::OnDeviceScaleFactorChanged(float device_scale_factor) {
852 ScopedCursorHider hider(this);
853 if (dispatcher_)
854 dispatcher_->host()->OnDeviceScaleFactorChanged(device_scale_factor);
855 if (delegate_)
856 delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
857 }
858
859 #if !defined(NDEBUG)
GetDebugInfo() const860 std::string Window::GetDebugInfo() const {
861 return base::StringPrintf(
862 "%s<%d> bounds(%d, %d, %d, %d) %s %s opacity=%.1f",
863 name().empty() ? "Unknown" : name().c_str(), id(),
864 bounds().x(), bounds().y(), bounds().width(), bounds().height(),
865 visible_ ? "WindowVisible" : "WindowHidden",
866 layer_ ?
867 (layer_->GetTargetVisibility() ? "LayerVisible" : "LayerHidden") :
868 "NoLayer",
869 layer_ ? layer_->opacity() : 1.0f);
870 }
871
PrintWindowHierarchy(int depth) const872 void Window::PrintWindowHierarchy(int depth) const {
873 VLOG(0) << base::StringPrintf(
874 "%*s%s", depth * 2, "", GetDebugInfo().c_str());
875 for (Windows::const_iterator it = children_.begin();
876 it != children_.end(); ++it) {
877 Window* child = *it;
878 child->PrintWindowHierarchy(depth + 1);
879 }
880 }
881 #endif
882
RemoveOrDestroyChildren()883 void Window::RemoveOrDestroyChildren() {
884 while (!children_.empty()) {
885 Window* child = children_[0];
886 if (child->owned_by_parent_) {
887 delete child;
888 // Deleting the child so remove it from out children_ list.
889 DCHECK(std::find(children_.begin(), children_.end(), child) ==
890 children_.end());
891 } else {
892 // Even if we can't delete the child, we still need to remove it from the
893 // parent so that relevant bookkeeping (parent_ back-pointers etc) are
894 // updated.
895 RemoveChild(child);
896 }
897 }
898 }
899
900 ///////////////////////////////////////////////////////////////////////////////
901 // Window, private:
902
SetPropertyInternal(const void * key,const char * name,PropertyDeallocator deallocator,int64 value,int64 default_value)903 int64 Window::SetPropertyInternal(const void* key,
904 const char* name,
905 PropertyDeallocator deallocator,
906 int64 value,
907 int64 default_value) {
908 int64 old = GetPropertyInternal(key, default_value);
909 if (value == default_value) {
910 prop_map_.erase(key);
911 } else {
912 Value prop_value;
913 prop_value.name = name;
914 prop_value.value = value;
915 prop_value.deallocator = deallocator;
916 prop_map_[key] = prop_value;
917 }
918 FOR_EACH_OBSERVER(WindowObserver, observers_,
919 OnWindowPropertyChanged(this, key, old));
920 return old;
921 }
922
GetPropertyInternal(const void * key,int64 default_value) const923 int64 Window::GetPropertyInternal(const void* key,
924 int64 default_value) const {
925 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
926 if (iter == prop_map_.end())
927 return default_value;
928 return iter->second.value;
929 }
930
SetBoundsInternal(const gfx::Rect & new_bounds)931 void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
932 gfx::Rect actual_new_bounds(new_bounds);
933
934 // Ensure we don't go smaller than our minimum bounds.
935 if (delegate_) {
936 const gfx::Size& min_size = delegate_->GetMinimumSize();
937 actual_new_bounds.set_width(
938 std::max(min_size.width(), actual_new_bounds.width()));
939 actual_new_bounds.set_height(
940 std::max(min_size.height(), actual_new_bounds.height()));
941 }
942
943 gfx::Rect old_bounds = GetTargetBounds();
944
945 // Always need to set the layer's bounds -- even if it is to the same thing.
946 // This may cause important side effects such as stopping animation.
947 if (!layer_) {
948 const gfx::Vector2d origin_delta = new_bounds.OffsetFromOrigin() -
949 bounds_.OffsetFromOrigin();
950 bounds_ = new_bounds;
951 OffsetLayerBounds(origin_delta);
952 } else {
953 if (parent_ && !parent_->layer_) {
954 gfx::Vector2d offset;
955 const aura::Window* ancestor_with_layer =
956 parent_->GetAncestorWithLayer(&offset);
957 if (ancestor_with_layer)
958 actual_new_bounds.Offset(offset);
959 }
960 layer_->SetBounds(actual_new_bounds);
961 }
962
963 // If we are currently not the layer's delegate, we will not get bounds
964 // changed notification from the layer (this typically happens after animating
965 // hidden). We must notify ourselves.
966 if (!layer_ || layer_->delegate() != this)
967 OnWindowBoundsChanged(old_bounds, ContainsMouse());
968 }
969
SetVisible(bool visible)970 void Window::SetVisible(bool visible) {
971 if ((layer_ && visible == layer_->GetTargetVisibility()) ||
972 (!layer_ && visible == visible_))
973 return; // No change.
974
975 FOR_EACH_OBSERVER(WindowObserver, observers_,
976 OnWindowVisibilityChanging(this, visible));
977
978 WindowEventDispatcher* dispatcher = GetDispatcher();
979 if (dispatcher)
980 dispatcher->DispatchMouseExitToHidingWindow(this);
981
982 client::VisibilityClient* visibility_client =
983 client::GetVisibilityClient(this);
984 if (visibility_client)
985 visibility_client->UpdateLayerVisibility(this, visible);
986 else if (layer_)
987 layer_->SetVisible(visible);
988 visible_ = visible;
989 SchedulePaint();
990 if (parent_ && parent_->layout_manager_)
991 parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible);
992
993 if (delegate_)
994 delegate_->OnWindowTargetVisibilityChanged(visible);
995
996 NotifyWindowVisibilityChanged(this, visible);
997
998 if (dispatcher)
999 dispatcher->OnWindowVisibilityChanged(this, visible);
1000 }
1001
SchedulePaint()1002 void Window::SchedulePaint() {
1003 SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height()));
1004 }
1005
Paint(gfx::Canvas * canvas)1006 void Window::Paint(gfx::Canvas* canvas) {
1007 if (delegate_)
1008 delegate_->OnPaint(canvas);
1009 PaintLayerlessChildren(canvas);
1010 }
1011
PaintLayerlessChildren(gfx::Canvas * canvas)1012 void Window::PaintLayerlessChildren(gfx::Canvas* canvas) {
1013 for (size_t i = 0, count = children_.size(); i < count; ++i) {
1014 Window* child = children_[i];
1015 if (!child->layer_ && child->visible_) {
1016 gfx::ScopedCanvas scoped_canvas(canvas);
1017 if (canvas->ClipRect(child->bounds())) {
1018 canvas->Translate(child->bounds().OffsetFromOrigin());
1019 child->Paint(canvas);
1020 }
1021 }
1022 }
1023 }
1024
GetWindowForPoint(const gfx::Point & local_point,bool return_tightest,bool for_event_handling)1025 Window* Window::GetWindowForPoint(const gfx::Point& local_point,
1026 bool return_tightest,
1027 bool for_event_handling) {
1028 if (!IsVisible())
1029 return NULL;
1030
1031 if ((for_event_handling && !HitTest(local_point)) ||
1032 (!for_event_handling && !ContainsPoint(local_point)))
1033 return NULL;
1034
1035 // Check if I should claim this event and not pass it to my children because
1036 // the location is inside my hit test override area. For details, see
1037 // set_hit_test_bounds_override_inner().
1038 if (for_event_handling && !hit_test_bounds_override_inner_.empty()) {
1039 gfx::Rect inset_local_bounds(gfx::Point(), bounds().size());
1040 inset_local_bounds.Inset(hit_test_bounds_override_inner_);
1041 // We know we're inside the normal local bounds, so if we're outside the
1042 // inset bounds we must be in the special hit test override area.
1043 DCHECK(HitTest(local_point));
1044 if (!inset_local_bounds.Contains(local_point))
1045 return delegate_ ? this : NULL;
1046 }
1047
1048 if (!return_tightest && delegate_)
1049 return this;
1050
1051 for (Windows::const_reverse_iterator it = children_.rbegin(),
1052 rend = children_.rend();
1053 it != rend; ++it) {
1054 Window* child = *it;
1055
1056 if (for_event_handling) {
1057 if (child->ignore_events_)
1058 continue;
1059 // The client may not allow events to be processed by certain subtrees.
1060 client::EventClient* client = client::GetEventClient(GetRootWindow());
1061 if (client && !client->CanProcessEventsWithinSubtree(child))
1062 continue;
1063 if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling(
1064 child, local_point))
1065 continue;
1066 }
1067
1068 gfx::Point point_in_child_coords(local_point);
1069 ConvertPointToTarget(this, child, &point_in_child_coords);
1070 Window* match = child->GetWindowForPoint(point_in_child_coords,
1071 return_tightest,
1072 for_event_handling);
1073 if (match)
1074 return match;
1075 }
1076
1077 return delegate_ ? this : NULL;
1078 }
1079
RemoveChildImpl(Window * child,Window * new_parent)1080 void Window::RemoveChildImpl(Window* child, Window* new_parent) {
1081 if (layout_manager_)
1082 layout_manager_->OnWillRemoveWindowFromLayout(child);
1083 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child));
1084 Window* root_window = child->GetRootWindow();
1085 Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL;
1086 if (root_window && root_window != new_root_window) {
1087 root_window->GetDispatcher()->OnWindowRemovedFromRootWindow(
1088 child, new_root_window);
1089 child->NotifyRemovingFromRootWindow();
1090 }
1091
1092 gfx::Vector2d offset;
1093 GetAncestorWithLayer(&offset);
1094 child->UnparentLayers(!layer_, offset);
1095 child->parent_ = NULL;
1096 Windows::iterator i = std::find(children_.begin(), children_.end(), child);
1097 DCHECK(i != children_.end());
1098 children_.erase(i);
1099 child->OnParentChanged();
1100 if (layout_manager_)
1101 layout_manager_->OnWindowRemovedFromLayout(child);
1102 }
1103
UnparentLayers(bool has_layerless_ancestor,const gfx::Vector2d & offset)1104 void Window::UnparentLayers(bool has_layerless_ancestor,
1105 const gfx::Vector2d& offset) {
1106 if (!layer_) {
1107 const gfx::Vector2d new_offset = offset + bounds().OffsetFromOrigin();
1108 for (size_t i = 0; i < children_.size(); ++i) {
1109 children_[i]->UnparentLayers(true, new_offset);
1110 }
1111 } else {
1112 // Only remove the layer if we still own it. Someone else may have acquired
1113 // ownership of it via AcquireLayer() and may expect the hierarchy to go
1114 // unchanged as the Window is destroyed.
1115 if (layer_owner_) {
1116 if (layer_->parent())
1117 layer_->parent()->Remove(layer_);
1118 if (has_layerless_ancestor) {
1119 const gfx::Rect real_bounds(bounds_);
1120 gfx::Rect layer_bounds(layer_->bounds());
1121 layer_bounds.Offset(-offset);
1122 layer_->SetBounds(layer_bounds);
1123 bounds_ = real_bounds;
1124 }
1125 }
1126 }
1127 }
1128
ReparentLayers(ui::Layer * parent_layer,const gfx::Vector2d & offset)1129 void Window::ReparentLayers(ui::Layer* parent_layer,
1130 const gfx::Vector2d& offset) {
1131 if (!layer_) {
1132 for (size_t i = 0; i < children_.size(); ++i) {
1133 children_[i]->ReparentLayers(
1134 parent_layer,
1135 offset + children_[i]->bounds().OffsetFromOrigin());
1136 }
1137 } else {
1138 const gfx::Rect real_bounds(bounds());
1139 parent_layer->Add(layer_);
1140 gfx::Rect layer_bounds(layer_->bounds().size());
1141 layer_bounds += offset;
1142 layer_->SetBounds(layer_bounds);
1143 bounds_ = real_bounds;
1144 }
1145 }
1146
OffsetLayerBounds(const gfx::Vector2d & offset)1147 void Window::OffsetLayerBounds(const gfx::Vector2d& offset) {
1148 if (!layer_) {
1149 for (size_t i = 0; i < children_.size(); ++i)
1150 children_[i]->OffsetLayerBounds(offset);
1151 } else {
1152 gfx::Rect layer_bounds(layer_->bounds());
1153 layer_bounds += offset;
1154 layer_->SetBounds(layer_bounds);
1155 }
1156 }
1157
OnParentChanged()1158 void Window::OnParentChanged() {
1159 FOR_EACH_OBSERVER(
1160 WindowObserver, observers_, OnWindowParentChanged(this, parent_));
1161 }
1162
HasTransientAncestor(const Window * ancestor) const1163 bool Window::HasTransientAncestor(const Window* ancestor) const {
1164 if (transient_parent_ == ancestor)
1165 return true;
1166 return transient_parent_ ?
1167 transient_parent_->HasTransientAncestor(ancestor) : false;
1168 }
1169
SkipNullDelegatesForStacking(StackDirection direction,Window ** target) const1170 void Window::SkipNullDelegatesForStacking(StackDirection direction,
1171 Window** target) const {
1172 DCHECK_EQ(this, (*target)->parent());
1173 size_t target_i =
1174 std::find(children_.begin(), children_.end(), *target) -
1175 children_.begin();
1176
1177 // By convention we don't stack on top of windows with layers with NULL
1178 // delegates. Walk backward to find a valid target window.
1179 // See tests WindowTest.StackingMadrigal and StackOverClosingTransient
1180 // for an explanation of this.
1181 while (target_i > 0) {
1182 const size_t index = direction == STACK_ABOVE ? target_i : target_i - 1;
1183 if (!children_[index]->layer_ ||
1184 children_[index]->layer_->delegate() != NULL)
1185 break;
1186 --target_i;
1187 }
1188 *target = children_[target_i];
1189 }
1190
StackChildRelativeTo(Window * child,Window * target,StackDirection direction)1191 void Window::StackChildRelativeTo(Window* child,
1192 Window* target,
1193 StackDirection direction) {
1194 DCHECK_NE(child, target);
1195 DCHECK(child);
1196 DCHECK(target);
1197 DCHECK_EQ(this, child->parent());
1198 DCHECK_EQ(this, target->parent());
1199
1200 client::WindowStackingClient* stacking_client =
1201 client::GetWindowStackingClient();
1202 if (stacking_client)
1203 stacking_client->AdjustStacking(&child, &target, &direction);
1204
1205 SkipNullDelegatesForStacking(direction, &target);
1206
1207 // If we couldn't find a valid target position, don't move anything.
1208 if (direction == STACK_ABOVE &&
1209 (target->layer_ && target->layer_->delegate() == NULL))
1210 return;
1211
1212 // Don't try to stack a child above itself.
1213 if (child == target)
1214 return;
1215
1216 // Move the child.
1217 StackChildRelativeToImpl(child, target, direction);
1218
1219 // Stack any transient children that share the same parent to be in front of
1220 // 'child'. Preserve the existing stacking order by iterating in the order
1221 // those children appear in children_ array.
1222 Window* last_transient = child;
1223 Windows children(children_);
1224 for (Windows::iterator it = children.begin(); it != children.end(); ++it) {
1225 Window* transient_child = *it;
1226 if (transient_child != last_transient &&
1227 transient_child->HasTransientAncestor(child)) {
1228 StackChildRelativeToImpl(transient_child, last_transient, STACK_ABOVE);
1229 last_transient = transient_child;
1230 }
1231 }
1232 }
1233
StackChildRelativeToImpl(Window * child,Window * target,StackDirection direction)1234 void Window::StackChildRelativeToImpl(Window* child,
1235 Window* target,
1236 StackDirection direction) {
1237 DCHECK_NE(child, target);
1238 DCHECK(child);
1239 DCHECK(target);
1240 DCHECK_EQ(this, child->parent());
1241 DCHECK_EQ(this, target->parent());
1242
1243 const size_t child_i =
1244 std::find(children_.begin(), children_.end(), child) - children_.begin();
1245 const size_t target_i =
1246 std::find(children_.begin(), children_.end(), target) - children_.begin();
1247
1248 // Don't move the child if it is already in the right place.
1249 if ((direction == STACK_ABOVE && child_i == target_i + 1) ||
1250 (direction == STACK_BELOW && child_i + 1 == target_i))
1251 return;
1252
1253 const size_t dest_i =
1254 direction == STACK_ABOVE ?
1255 (child_i < target_i ? target_i : target_i + 1) :
1256 (child_i < target_i ? target_i - 1 : target_i);
1257 children_.erase(children_.begin() + child_i);
1258 children_.insert(children_.begin() + dest_i, child);
1259
1260 StackChildLayerRelativeTo(child, target, direction);
1261
1262 child->OnStackingChanged();
1263 }
1264
StackChildLayerRelativeTo(Window * child,Window * target,StackDirection direction)1265 void Window::StackChildLayerRelativeTo(Window* child,
1266 Window* target,
1267 StackDirection direction) {
1268 Window* ancestor_with_layer = GetAncestorWithLayer(NULL);
1269 ui::Layer* ancestor_layer =
1270 ancestor_with_layer ? ancestor_with_layer->layer() : NULL;
1271 if (!ancestor_layer)
1272 return;
1273
1274 if (child->layer_ && target->layer_) {
1275 if (direction == STACK_ABOVE)
1276 ancestor_layer->StackAbove(child->layer_, target->layer_);
1277 else
1278 ancestor_layer->StackBelow(child->layer_, target->layer_);
1279 return;
1280 }
1281 typedef std::vector<ui::Layer*> Layers;
1282 Layers layers;
1283 GetLayersToStack(child, &layers);
1284 if (layers.empty())
1285 return;
1286
1287 ui::Layer* target_layer;
1288 if (direction == STACK_ABOVE) {
1289 target_layer =
1290 FindStackingTargetLayer<Windows::const_reverse_iterator>(target, child);
1291 } else {
1292 target_layer =
1293 FindStackingTargetLayer<Windows::const_iterator>(target, child);
1294 }
1295
1296 if (!target_layer) {
1297 if (direction == STACK_ABOVE) {
1298 for (Layers::const_reverse_iterator i = layers.rbegin();
1299 i != layers.rend(); ++i) {
1300 ancestor_layer->StackAtBottom(*i);
1301 }
1302 } else {
1303 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i)
1304 ancestor_layer->StackAtTop(*i);
1305 }
1306 return;
1307 }
1308
1309 if (direction == STACK_ABOVE) {
1310 for (Layers::const_reverse_iterator i = layers.rbegin();
1311 i != layers.rend(); ++i) {
1312 ancestor_layer->StackAbove(*i, target_layer);
1313 }
1314 } else {
1315 for (Layers::const_iterator i = layers.begin(); i != layers.end(); ++i)
1316 ancestor_layer->StackBelow(*i, target_layer);
1317 }
1318 }
1319
OnStackingChanged()1320 void Window::OnStackingChanged() {
1321 FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
1322 }
1323
NotifyRemovingFromRootWindow()1324 void Window::NotifyRemovingFromRootWindow() {
1325 FOR_EACH_OBSERVER(WindowObserver, observers_,
1326 OnWindowRemovingFromRootWindow(this));
1327 for (Window::Windows::const_iterator it = children_.begin();
1328 it != children_.end(); ++it) {
1329 (*it)->NotifyRemovingFromRootWindow();
1330 }
1331 }
1332
NotifyAddedToRootWindow()1333 void Window::NotifyAddedToRootWindow() {
1334 FOR_EACH_OBSERVER(WindowObserver, observers_,
1335 OnWindowAddedToRootWindow(this));
1336 for (Window::Windows::const_iterator it = children_.begin();
1337 it != children_.end(); ++it) {
1338 (*it)->NotifyAddedToRootWindow();
1339 }
1340 }
1341
NotifyWindowHierarchyChange(const WindowObserver::HierarchyChangeParams & params)1342 void Window::NotifyWindowHierarchyChange(
1343 const WindowObserver::HierarchyChangeParams& params) {
1344 params.target->NotifyWindowHierarchyChangeDown(params);
1345 switch (params.phase) {
1346 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
1347 if (params.old_parent)
1348 params.old_parent->NotifyWindowHierarchyChangeUp(params);
1349 break;
1350 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
1351 if (params.new_parent)
1352 params.new_parent->NotifyWindowHierarchyChangeUp(params);
1353 break;
1354 default:
1355 NOTREACHED();
1356 break;
1357 }
1358 }
1359
NotifyWindowHierarchyChangeDown(const WindowObserver::HierarchyChangeParams & params)1360 void Window::NotifyWindowHierarchyChangeDown(
1361 const WindowObserver::HierarchyChangeParams& params) {
1362 NotifyWindowHierarchyChangeAtReceiver(params);
1363 for (Window::Windows::const_iterator it = children_.begin();
1364 it != children_.end(); ++it) {
1365 (*it)->NotifyWindowHierarchyChangeDown(params);
1366 }
1367 }
1368
NotifyWindowHierarchyChangeUp(const WindowObserver::HierarchyChangeParams & params)1369 void Window::NotifyWindowHierarchyChangeUp(
1370 const WindowObserver::HierarchyChangeParams& params) {
1371 for (Window* window = this; window; window = window->parent())
1372 window->NotifyWindowHierarchyChangeAtReceiver(params);
1373 }
1374
NotifyWindowHierarchyChangeAtReceiver(const WindowObserver::HierarchyChangeParams & params)1375 void Window::NotifyWindowHierarchyChangeAtReceiver(
1376 const WindowObserver::HierarchyChangeParams& params) {
1377 WindowObserver::HierarchyChangeParams local_params = params;
1378 local_params.receiver = this;
1379
1380 switch (params.phase) {
1381 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
1382 FOR_EACH_OBSERVER(WindowObserver, observers_,
1383 OnWindowHierarchyChanging(local_params));
1384 break;
1385 case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
1386 FOR_EACH_OBSERVER(WindowObserver, observers_,
1387 OnWindowHierarchyChanged(local_params));
1388 break;
1389 default:
1390 NOTREACHED();
1391 break;
1392 }
1393 }
1394
NotifyWindowVisibilityChanged(aura::Window * target,bool visible)1395 void Window::NotifyWindowVisibilityChanged(aura::Window* target,
1396 bool visible) {
1397 if (!NotifyWindowVisibilityChangedDown(target, visible)) {
1398 return; // |this| has been deleted.
1399 }
1400 NotifyWindowVisibilityChangedUp(target, visible);
1401 }
1402
NotifyWindowVisibilityChangedAtReceiver(aura::Window * target,bool visible)1403 bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target,
1404 bool visible) {
1405 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one
1406 // of the observers. We create an local observer for that. In that case we
1407 // exit without further access to any members.
1408 WindowTracker tracker;
1409 tracker.Add(this);
1410 FOR_EACH_OBSERVER(WindowObserver, observers_,
1411 OnWindowVisibilityChanged(target, visible));
1412 return tracker.Contains(this);
1413 }
1414
NotifyWindowVisibilityChangedDown(aura::Window * target,bool visible)1415 bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target,
1416 bool visible) {
1417 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible))
1418 return false; // |this| was deleted.
1419 std::set<const Window*> child_already_processed;
1420 bool child_destroyed = false;
1421 do {
1422 child_destroyed = false;
1423 for (Window::Windows::const_iterator it = children_.begin();
1424 it != children_.end(); ++it) {
1425 if (!child_already_processed.insert(*it).second)
1426 continue;
1427 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) {
1428 // |*it| was deleted, |it| is invalid and |children_| has changed.
1429 // We exit the current for-loop and enter a new one.
1430 child_destroyed = true;
1431 break;
1432 }
1433 }
1434 } while (child_destroyed);
1435 return true;
1436 }
1437
NotifyWindowVisibilityChangedUp(aura::Window * target,bool visible)1438 void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
1439 bool visible) {
1440 for (Window* window = this; window; window = window->parent()) {
1441 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible);
1442 DCHECK(ret);
1443 }
1444 }
1445
OnWindowBoundsChanged(const gfx::Rect & old_bounds,bool contained_mouse)1446 void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds,
1447 bool contained_mouse) {
1448 if (layer_) {
1449 bounds_ = layer_->bounds();
1450 if (parent_ && !parent_->layer_) {
1451 gfx::Vector2d offset;
1452 aura::Window* ancestor_with_layer =
1453 parent_->GetAncestorWithLayer(&offset);
1454 if (ancestor_with_layer)
1455 bounds_.Offset(-offset);
1456 }
1457 }
1458
1459 if (layout_manager_)
1460 layout_manager_->OnWindowResized();
1461 if (delegate_)
1462 delegate_->OnBoundsChanged(old_bounds, bounds());
1463 FOR_EACH_OBSERVER(WindowObserver,
1464 observers_,
1465 OnWindowBoundsChanged(this, old_bounds, bounds()));
1466 WindowEventDispatcher* dispatcher = GetDispatcher();
1467 if (dispatcher)
1468 dispatcher->OnWindowBoundsChanged(this, contained_mouse);
1469 }
1470
OnPaintLayer(gfx::Canvas * canvas)1471 void Window::OnPaintLayer(gfx::Canvas* canvas) {
1472 Paint(canvas);
1473 }
1474
PrepareForLayerBoundsChange()1475 base::Closure Window::PrepareForLayerBoundsChange() {
1476 return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
1477 bounds(), ContainsMouse());
1478 }
1479
CanAcceptEvent(const ui::Event & event)1480 bool Window::CanAcceptEvent(const ui::Event& event) {
1481 // The client may forbid certain windows from receiving events at a given
1482 // point in time.
1483 client::EventClient* client = client::GetEventClient(GetRootWindow());
1484 if (client && !client->CanProcessEventsWithinSubtree(this))
1485 return false;
1486
1487 // We need to make sure that a touch cancel event and any gesture events it
1488 // creates can always reach the window. This ensures that we receive a valid
1489 // touch / gesture stream.
1490 if (event.IsEndingEvent())
1491 return true;
1492
1493 if (!IsVisible())
1494 return false;
1495
1496 // The top-most window can always process an event.
1497 if (!parent_)
1498 return true;
1499
1500 // For located events (i.e. mouse, touch etc.), an assumption is made that
1501 // windows that don't have a delegate cannot process the event (see more in
1502 // GetWindowForPoint()). This assumption is not made for key events.
1503 return event.IsKeyEvent() || delegate_;
1504 }
1505
GetParentTarget()1506 ui::EventTarget* Window::GetParentTarget() {
1507 if (dispatcher_) {
1508 return client::GetEventClient(this) ?
1509 client::GetEventClient(this)->GetToplevelEventTarget() :
1510 Env::GetInstance();
1511 }
1512 return parent_;
1513 }
1514
GetChildIterator() const1515 scoped_ptr<ui::EventTargetIterator> Window::GetChildIterator() const {
1516 return scoped_ptr<ui::EventTargetIterator>(
1517 new ui::EventTargetIteratorImpl<Window>(children()));
1518 }
1519
GetEventTargeter()1520 ui::EventTargeter* Window::GetEventTargeter() {
1521 return targeter_.get();
1522 }
1523
ConvertEventToTarget(ui::EventTarget * target,ui::LocatedEvent * event)1524 void Window::ConvertEventToTarget(ui::EventTarget* target,
1525 ui::LocatedEvent* event) {
1526 event->ConvertLocationToTarget(this,
1527 static_cast<Window*>(target));
1528 }
1529
UpdateLayerName(const std::string & name)1530 void Window::UpdateLayerName(const std::string& name) {
1531 #if !defined(NDEBUG)
1532 DCHECK(layer_);
1533
1534 std::string layer_name(name_);
1535 if (layer_name.empty())
1536 layer_name = "Unnamed Window";
1537
1538 if (id_ != -1)
1539 layer_name += " " + base::IntToString(id_);
1540
1541 layer_->set_name(layer_name);
1542 #endif
1543 }
1544
ContainsMouse()1545 bool Window::ContainsMouse() {
1546 bool contains_mouse = false;
1547 if (IsVisible()) {
1548 WindowEventDispatcher* dispatcher = GetDispatcher();
1549 contains_mouse = dispatcher &&
1550 ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
1551 }
1552 return contains_mouse;
1553 }
1554
GetAncestorWithLayer(gfx::Vector2d * offset) const1555 const Window* Window::GetAncestorWithLayer(gfx::Vector2d* offset) const {
1556 for (const aura::Window* window = this; window; window = window->parent()) {
1557 if (window->layer_)
1558 return window;
1559 if (offset)
1560 *offset += window->bounds().OffsetFromOrigin();
1561 }
1562 if (offset)
1563 *offset = gfx::Vector2d();
1564 return NULL;
1565 }
1566
1567 } // namespace aura
1568