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