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

Side by Side Diff: ui/views/corewm/transient_window_manager.cc

Issue 115453004: Moves management of transients out of Window (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix MRUWindowTracker and MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/views/corewm/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/views/corewm/transient_window_stacking_client.h"
15
16 using aura::Window;
17
18 namespace views {
19 namespace corewm {
20
21 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TransientWindowManager, kPropertyKey, NULL);
22
23 Window* GetTransientParent(Window* window) {
24 return const_cast<Window*>(GetTransientParent(
25 const_cast<const Window*>(window)));
26 }
27
28 const Window* GetTransientParent(const Window* window) {
29 const TransientWindowManager* manager = TransientWindowManager::Get(window);
30 return manager ? manager->transient_parent() : NULL;
31 }
32
33 const std::vector<Window*>& GetTransientChildren(
34 const Window* window) {
35 const TransientWindowManager* manager = TransientWindowManager::Get(window);
36 if (manager)
37 return manager->transient_children();
38
39 static std::vector<Window*>* shared = new std::vector<Window*>;
40 return *shared;
41 }
42
43 void AddTransientChild(aura::Window* parent, aura::Window* child) {
44 TransientWindowManager::Get(parent)->AddTransientChild(child);
45 }
46
47 void RemoveTransientChild(aura::Window* parent, aura::Window* child) {
48 TransientWindowManager::Get(parent)->RemoveTransientChild(child);
49 }
50
51 bool HasTransientAncestor(const Window* window, const Window* ancestor) {
52 const Window* transient_parent = GetTransientParent(window);
53 if (transient_parent == ancestor)
54 return true;
55 return transient_parent ?
56 HasTransientAncestor(transient_parent, ancestor) : false;
57 }
58
59 TransientWindowManager::~TransientWindowManager() {
60 }
61
62 // static
63 TransientWindowManager* TransientWindowManager::Get(Window* window) {
64 TransientWindowManager* manager = window->GetProperty(kPropertyKey);
65 if (!manager) {
66 manager = new TransientWindowManager(window);
67 window->SetProperty(kPropertyKey, manager);
68 }
69 return manager;
70 }
71
72 // static
73 const TransientWindowManager* TransientWindowManager::Get(
74 const Window* window) {
75 return window->GetProperty(kPropertyKey);
76 }
77
78 void TransientWindowManager::AddTransientChild(Window* child) {
79 // TransientWindowStackingClient does the stacking of transient windows. If it
80 // isn't installed stacking is going to be wrong.
81 DCHECK(TransientWindowStackingClient::instance_);
82
83 TransientWindowManager* child_manager = Get(child);
84 if (child_manager->transient_parent_)
85 Get(child_manager->transient_parent_)->RemoveTransientChild(child);
86 DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
87 child) == transient_children_.end());
88 transient_children_.push_back(child);
89 child_manager->transient_parent_ = window_;
90 FOR_EACH_OBSERVER(WindowObserver, window_->observers_,
91 OnAddTransientChild(window_, child));
92 }
93
94 void TransientWindowManager::RemoveTransientChild(Window* child) {
95 Windows::iterator i =
96 std::find(transient_children_.begin(), transient_children_.end(), child);
97 DCHECK(i != transient_children_.end());
98 transient_children_.erase(i);
99 TransientWindowManager* child_manager = Get(child);
100 DCHECK_EQ(window_, child_manager->transient_parent_);
101 child_manager->transient_parent_ = NULL;
102 FOR_EACH_OBSERVER(WindowObserver, window_->observers_,
103 OnRemoveTransientChild(window_, child));
104 }
105
106 bool TransientWindowManager::IsStackingTransient(
107 const aura::Window* child,
108 const aura::Window* target) const {
109 return stacking_pair_ && stacking_pair_->child == child &&
110 stacking_pair_->target == target;
111 }
112
113 void TransientWindowManager::OnWindowVisibilityChanging(Window* window,
114 bool visible) {
115 // TODO(sky): move handling of becoming visible here.
116 if (!visible) {
117 std::for_each(transient_children_.begin(), transient_children_.end(),
118 std::mem_fun(&Window::Hide));
119 }
120 }
121
122 void TransientWindowManager::OnWindowStackingChanged(Window* window) {
123 TransientWindowManager* parent_manager = Get(window->parent());
124 parent_manager->OnChildStackingChanged(window);
125 }
126
127 void TransientWindowManager::OnWindowDestroying(Window* window) {
128 // TODO(sky): remove notes after safely landing and baking.
129
130 // Removes ourselves from our transient parent (if it hasn't been done by the
131 // RootWindow).
132 // NOTE: This use to be done after children where removed, now it is before.
133 if (transient_parent_) {
134 TransientWindowManager::Get(transient_parent_)->RemoveTransientChild(
135 window_);
136 }
137
138 // Destroy transient children, only after we've removed ourselves from our
139 // parent, as destroying an active transient child may otherwise attempt to
140 // refocus us.
141 // NOTE: this use to be after removed from parent, now its before.
142 Windows transient_children(transient_children_);
143 STLDeleteElements(&transient_children);
144 DCHECK(transient_children_.empty());
145 }
146
147 TransientWindowManager::TransientWindowManager(Window* window)
148 : window_(window),
149 transient_parent_(NULL),
150 stacking_pair_(NULL) {
151 window_->AddObserver(this);
152 }
153
154 void TransientWindowManager::OnChildStackingChanged(aura::Window* child) {
155 // Do nothing if we initiated the stacking change.
156 // TODO(sky): change args to OnWindowStackingChanged() so that this lookup
157 // can be simpler.
158 if (stacking_pair_ && stacking_pair_->child == child) {
159 Windows::const_iterator child_i = std::find(
160 window_->children().begin(), window_->children().end(), child);
161 DCHECK(child_i != window_->children().end());
162 if (child_i != window_->children().begin() &&
163 (*(child_i - 1) == stacking_pair_->target))
164 return;
165 }
166
167 // Stack any transient children that share the same parent to be in front of
168 // |child|. The existing stacking order is preserved by iterating backwards
169 // and always stacking on top.
170 Window::Windows children(window_->children());
171 for (Window::Windows::reverse_iterator it = children.rbegin();
172 it != children.rend(); ++it) {
173 if ((*it) != child && HasTransientAncestor(*it, child)) {
174 StackingPair pair(*it, child);
175 base::AutoReset<StackingPair*> resetter(&stacking_pair_, &pair);
176 window_->StackChildAbove((*it), child);
177 }
178 }
179 }
180
181 } // namespace corewm
182 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698