Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: ui/wm/core/transient_window_manager.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/wm/core/transient_window_manager.h ('k') | ui/wm/core/transient_window_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "ui/wm/core/transient_window_manager.h"
6
7 #include <algorithm>
8 #include <functional>
9
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"
17
18 using aura::Window;
19
20 namespace wm {
21 namespace {
22
23 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TransientWindowManager, kPropertyKey, NULL);
24
25 } // namespace
26
27 TransientWindowManager::~TransientWindowManager() {
28 }
29
30 // static
31 TransientWindowManager* TransientWindowManager::Get(Window* window) {
32 TransientWindowManager* manager = window->GetProperty(kPropertyKey);
33 if (!manager) {
34 manager = new TransientWindowManager(window);
35 window->SetProperty(kPropertyKey, manager);
36 }
37 return manager;
38 }
39
40 // static
41 const TransientWindowManager* TransientWindowManager::Get(
42 const Window* window) {
43 return window->GetProperty(kPropertyKey);
44 }
45
46 void TransientWindowManager::AddObserver(TransientWindowObserver* observer) {
47 observers_.AddObserver(observer);
48 }
49
50 void TransientWindowManager::RemoveObserver(TransientWindowObserver* observer) {
51 observers_.RemoveObserver(observer);
52 }
53
54 void TransientWindowManager::AddTransientChild(Window* child) {
55 // TransientWindowStackingClient does the stacking of transient windows. If it
56 // isn't installed stacking is going to be wrong.
57 DCHECK(TransientWindowStackingClient::instance_);
58
59 TransientWindowManager* child_manager = Get(child);
60 if (child_manager->transient_parent_)
61 Get(child_manager->transient_parent_)->RemoveTransientChild(child);
62 DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
63 child) == transient_children_.end());
64 transient_children_.push_back(child);
65 child_manager->transient_parent_ = window_;
66
67 // Restack |child| properly above its transient parent, if they share the same
68 // parent.
69 if (child->parent() == window_->parent())
70 RestackTransientDescendants();
71
72 FOR_EACH_OBSERVER(TransientWindowObserver, observers_,
73 OnTransientChildAdded(window_, child));
74 }
75
76 void TransientWindowManager::RemoveTransientChild(Window* child) {
77 Windows::iterator i =
78 std::find(transient_children_.begin(), transient_children_.end(), child);
79 DCHECK(i != transient_children_.end());
80 transient_children_.erase(i);
81 TransientWindowManager* child_manager = Get(child);
82 DCHECK_EQ(window_, child_manager->transient_parent_);
83 child_manager->transient_parent_ = NULL;
84
85 // If |child| and its former transient parent share the same parent, |child|
86 // should be restacked properly so it is not among transient children of its
87 // former parent, anymore.
88 if (window_->parent() == child->parent())
89 RestackTransientDescendants();
90
91 FOR_EACH_OBSERVER(TransientWindowObserver, observers_,
92 OnTransientChildRemoved(window_, child));
93 }
94
95 bool TransientWindowManager::IsStackingTransient(
96 const aura::Window* target) const {
97 return stacking_target_ == target;
98 }
99
100 TransientWindowManager::TransientWindowManager(Window* window)
101 : window_(window),
102 transient_parent_(NULL),
103 stacking_target_(NULL),
104 parent_controls_visibility_(false),
105 show_on_parent_visible_(false),
106 ignore_visibility_changed_event_(false) {
107 window_->AddObserver(this);
108 }
109
110 void TransientWindowManager::RestackTransientDescendants() {
111 Window* parent = window_->parent();
112 if (!parent)
113 return;
114
115 // Stack any transient children that share the same parent to be in front of
116 // |window_|. The existing stacking order is preserved by iterating backwards
117 // and always stacking on top.
118 Window::Windows children(parent->children());
119 for (Window::Windows::reverse_iterator it = children.rbegin();
120 it != children.rend(); ++it) {
121 if ((*it) != window_ && HasTransientAncestor(*it, window_)) {
122 TransientWindowManager* descendant_manager = Get(*it);
123 base::AutoReset<Window*> resetter(
124 &descendant_manager->stacking_target_,
125 window_);
126 parent->StackChildAbove((*it), window_);
127 }
128 }
129 }
130
131 void TransientWindowManager::OnWindowParentChanged(aura::Window* window,
132 aura::Window* parent) {
133 DCHECK_EQ(window_, window);
134 // Stack |window| properly if it is transient child of a sibling.
135 Window* transient_parent = wm::GetTransientParent(window);
136 if (transient_parent && transient_parent->parent() == parent) {
137 TransientWindowManager* transient_parent_manager =
138 Get(transient_parent);
139 transient_parent_manager->RestackTransientDescendants();
140 }
141 }
142
143 void TransientWindowManager::UpdateTransientChildVisibility(
144 bool parent_visible) {
145 base::AutoReset<bool> reset(&ignore_visibility_changed_event_, true);
146 if (!parent_visible) {
147 show_on_parent_visible_ = window_->TargetVisibility();
148 window_->Hide();
149 } else {
150 if (show_on_parent_visible_ && parent_controls_visibility_)
151 window_->Show();
152 show_on_parent_visible_ = false;
153 }
154 }
155
156 void TransientWindowManager::OnWindowVisibilityChanging(Window* window,
157 bool visible) {
158 DCHECK_EQ(window_, window);
159
160 for (auto* child : transient_children_)
161 Get(child)->UpdateTransientChildVisibility(visible);
162 }
163
164 void TransientWindowManager::OnWindowVisibilityChanged(Window* window,
165 bool visible) {
166 if (window_ != window || ignore_visibility_changed_event_ ||
167 !transient_parent_ || !parent_controls_visibility_) {
168 return;
169 }
170 if (!transient_parent_->TargetVisibility() && visible) {
171 base::AutoReset<bool> reset(&ignore_visibility_changed_event_, true);
172 show_on_parent_visible_ = true;
173 window_->Hide();
174 } else if (!visible) {
175 DCHECK(!show_on_parent_visible_);
176 }
177 }
178
179 void TransientWindowManager::OnWindowStackingChanged(Window* window) {
180 DCHECK_EQ(window_, window);
181 // Do nothing if we initiated the stacking change.
182 const TransientWindowManager* transient_manager =
183 Get(static_cast<const Window*>(window));
184 if (transient_manager && transient_manager->stacking_target_) {
185 Windows::const_iterator window_i = std::find(
186 window->parent()->children().begin(),
187 window->parent()->children().end(),
188 window);
189 DCHECK(window_i != window->parent()->children().end());
190 if (window_i != window->parent()->children().begin() &&
191 (*(window_i - 1) == transient_manager->stacking_target_))
192 return;
193 }
194
195 RestackTransientDescendants();
196 }
197
198 void TransientWindowManager::OnWindowDestroying(Window* window) {
199 // Removes ourselves from our transient parent (if it hasn't been done by the
200 // RootWindow).
201 if (transient_parent_) {
202 TransientWindowManager::Get(transient_parent_)->RemoveTransientChild(
203 window_);
204 }
205
206 // Destroy transient children, only after we've removed ourselves from our
207 // parent, as destroying an active transient child may otherwise attempt to
208 // refocus us.
209 Windows transient_children(transient_children_);
210 STLDeleteElements(&transient_children);
211 DCHECK(transient_children_.empty());
212 }
213
214 } // namespace wm
OLDNEW
« no previous file with comments | « ui/wm/core/transient_window_manager.h ('k') | ui/wm/core/transient_window_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698