Roll src/third_party/skia b14e4a0:3c29c4d
[chromium-blink-merge.git] / ui / wm / core / transient_window_manager.cc
blob120af84786c5b98a717491d7b4ff263d8facef53
1 // Copyright 2014 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/wm/core/transient_window_manager.h"
7 #include <algorithm>
8 #include <functional>
10 #include "base/auto_reset.h"
11 #include "base/stl_util.h"
12 #include "ui/aura/window.h"
13 #include "ui/aura/window_property.h"
14 #include "ui/wm/core/transient_window_observer.h"
15 #include "ui/wm/core/transient_window_stacking_client.h"
16 #include "ui/wm/core/window_util.h"
18 using aura::Window;
20 namespace wm {
22 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TransientWindowManager, kPropertyKey, NULL);
24 TransientWindowManager::~TransientWindowManager() {
27 // static
28 TransientWindowManager* TransientWindowManager::Get(Window* window) {
29 TransientWindowManager* manager = window->GetProperty(kPropertyKey);
30 if (!manager) {
31 manager = new TransientWindowManager(window);
32 window->SetProperty(kPropertyKey, manager);
34 return manager;
37 // static
38 const TransientWindowManager* TransientWindowManager::Get(
39 const Window* window) {
40 return window->GetProperty(kPropertyKey);
43 void TransientWindowManager::AddObserver(TransientWindowObserver* observer) {
44 observers_.AddObserver(observer);
47 void TransientWindowManager::RemoveObserver(TransientWindowObserver* observer) {
48 observers_.RemoveObserver(observer);
51 void TransientWindowManager::AddTransientChild(Window* child) {
52 // TransientWindowStackingClient does the stacking of transient windows. If it
53 // isn't installed stacking is going to be wrong.
54 DCHECK(TransientWindowStackingClient::instance_);
56 TransientWindowManager* child_manager = Get(child);
57 if (child_manager->transient_parent_)
58 Get(child_manager->transient_parent_)->RemoveTransientChild(child);
59 DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
60 child) == transient_children_.end());
61 transient_children_.push_back(child);
62 child_manager->transient_parent_ = window_;
64 // Restack |child| properly above its transient parent, if they share the same
65 // parent.
66 if (child->parent() == window_->parent())
67 RestackTransientDescendants();
69 FOR_EACH_OBSERVER(TransientWindowObserver, observers_,
70 OnTransientChildAdded(window_, child));
73 void TransientWindowManager::RemoveTransientChild(Window* child) {
74 Windows::iterator i =
75 std::find(transient_children_.begin(), transient_children_.end(), child);
76 DCHECK(i != transient_children_.end());
77 transient_children_.erase(i);
78 TransientWindowManager* child_manager = Get(child);
79 DCHECK_EQ(window_, child_manager->transient_parent_);
80 child_manager->transient_parent_ = NULL;
82 // If |child| and its former transient parent share the same parent, |child|
83 // should be restacked properly so it is not among transient children of its
84 // former parent, anymore.
85 if (window_->parent() == child->parent())
86 RestackTransientDescendants();
88 FOR_EACH_OBSERVER(TransientWindowObserver, observers_,
89 OnTransientChildRemoved(window_, child));
92 bool TransientWindowManager::IsStackingTransient(
93 const aura::Window* target) const {
94 return stacking_target_ == target;
97 TransientWindowManager::TransientWindowManager(Window* window)
98 : window_(window),
99 transient_parent_(NULL),
100 stacking_target_(NULL) {
101 window_->AddObserver(this);
104 void TransientWindowManager::RestackTransientDescendants() {
105 Window* parent = window_->parent();
106 if (!parent)
107 return;
109 // Stack any transient children that share the same parent to be in front of
110 // |window_|. The existing stacking order is preserved by iterating backwards
111 // and always stacking on top.
112 Window::Windows children(parent->children());
113 for (Window::Windows::reverse_iterator it = children.rbegin();
114 it != children.rend(); ++it) {
115 if ((*it) != window_ && HasTransientAncestor(*it, window_)) {
116 TransientWindowManager* descendant_manager = Get(*it);
117 base::AutoReset<Window*> resetter(
118 &descendant_manager->stacking_target_,
119 window_);
120 parent->StackChildAbove((*it), window_);
125 void TransientWindowManager::OnWindowParentChanged(aura::Window* window,
126 aura::Window* parent) {
127 DCHECK_EQ(window_, window);
128 // Stack |window| properly if it is transient child of a sibling.
129 Window* transient_parent = wm::GetTransientParent(window);
130 if (transient_parent && transient_parent->parent() == parent) {
131 TransientWindowManager* transient_parent_manager =
132 Get(transient_parent);
133 transient_parent_manager->RestackTransientDescendants();
137 void TransientWindowManager::OnWindowVisibilityChanging(Window* window,
138 bool visible) {
139 // TODO(sky): move handling of becoming visible here.
140 if (!visible) {
141 std::for_each(transient_children_.begin(), transient_children_.end(),
142 std::mem_fun(&Window::Hide));
146 void TransientWindowManager::OnWindowStackingChanged(Window* window) {
147 DCHECK_EQ(window_, window);
149 // Do nothing if we initiated the stacking change.
150 const TransientWindowManager* transient_manager =
151 Get(static_cast<const Window*>(window));
152 if (transient_manager && transient_manager->stacking_target_) {
153 Windows::const_iterator window_i = std::find(
154 window->parent()->children().begin(),
155 window->parent()->children().end(),
156 window);
157 DCHECK(window_i != window->parent()->children().end());
158 if (window_i != window->parent()->children().begin() &&
159 (*(window_i - 1) == transient_manager->stacking_target_))
160 return;
163 RestackTransientDescendants();
166 void TransientWindowManager::OnWindowDestroying(Window* window) {
167 // Removes ourselves from our transient parent (if it hasn't been done by the
168 // RootWindow).
169 if (transient_parent_) {
170 TransientWindowManager::Get(transient_parent_)->RemoveTransientChild(
171 window_);
174 // Destroy transient children, only after we've removed ourselves from our
175 // parent, as destroying an active transient child may otherwise attempt to
176 // refocus us.
177 Windows transient_children(transient_children_);
178 STLDeleteElements(&transient_children);
179 DCHECK(transient_children_.empty());
182 } // namespace wm