1 // Copyright 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.
5 #include "ui/views/widget/window_reorderer.h"
10 #include "ui/aura/window.h"
11 #include "ui/views/view.h"
12 #include "ui/views/view_constants_aura.h"
18 // Sets |hosted_windows| to a mapping of the views with an associated window to
19 // the window that they are associated to. Only views associated to a child of
20 // |parent_window| are returned.
21 void GetViewsWithAssociatedWindow(
22 const aura::Window
& parent_window
,
23 std::map
<views::View
*, aura::Window
*>* hosted_windows
) {
24 const std::vector
<aura::Window
*>& child_windows
= parent_window
.children();
25 for (size_t i
= 0; i
< child_windows
.size(); ++i
) {
26 aura::Window
* child
= child_windows
[i
];
27 View
* host_view
= child
->GetProperty(kHostViewKey
);
29 (*hosted_windows
)[host_view
] = child
;
33 // Sets |order| to the list of views whose layer / associated window's layer
34 // is a child of |parent_layer|. |order| is sorted in ascending z-order of
36 // |hosts| are the views with an associated window whose layer is a child of
38 void GetOrderOfViewsWithLayers(
40 ui::Layer
* parent_layer
,
41 const std::map
<views::View
*, aura::Window
*>& hosts
,
42 std::vector
<views::View
*>* order
) {
46 if (view
->layer() && view
->layer()->parent() == parent_layer
) {
47 order
->push_back(view
);
48 // |hosts| may contain a child of |view|.
49 } else if (hosts
.find(view
) != hosts
.end()) {
50 order
->push_back(view
);
53 for (int i
= 0; i
< view
->child_count(); ++i
)
54 GetOrderOfViewsWithLayers(view
->child_at(i
), parent_layer
, hosts
, order
);
59 // Class which reorders windows as a result of the kHostViewKey property being
61 class WindowReorderer::AssociationObserver
: public aura::WindowObserver
{
63 explicit AssociationObserver(WindowReorderer
* reorderer
);
64 ~AssociationObserver() override
;
66 // Start/stop observing changes in the kHostViewKey property on |window|.
67 void StartObserving(aura::Window
* window
);
68 void StopObserving(aura::Window
* window
);
71 // aura::WindowObserver overrides:
72 void OnWindowPropertyChanged(aura::Window
* window
,
74 intptr_t old
) override
;
75 void OnWindowDestroying(aura::Window
* window
) override
;
78 WindowReorderer
* reorderer_
;
80 std::set
<aura::Window
*> windows_
;
82 DISALLOW_COPY_AND_ASSIGN(AssociationObserver
);
85 WindowReorderer::AssociationObserver::AssociationObserver(
86 WindowReorderer
* reorderer
)
87 : reorderer_(reorderer
) {
90 WindowReorderer::AssociationObserver::~AssociationObserver() {
91 while (!windows_
.empty())
92 StopObserving(*windows_
.begin());
95 void WindowReorderer::AssociationObserver::StartObserving(
96 aura::Window
* window
) {
97 windows_
.insert(window
);
98 window
->AddObserver(this);
101 void WindowReorderer::AssociationObserver::StopObserving(
102 aura::Window
* window
) {
103 windows_
.erase(window
);
104 window
->RemoveObserver(this);
107 void WindowReorderer::AssociationObserver::OnWindowPropertyChanged(
108 aura::Window
* window
,
111 if (key
== kHostViewKey
)
112 reorderer_
->ReorderChildWindows();
115 void WindowReorderer::AssociationObserver::OnWindowDestroying(
116 aura::Window
* window
) {
117 windows_
.erase(window
);
118 window
->RemoveObserver(this);
121 WindowReorderer::WindowReorderer(aura::Window
* parent_window
,
123 : parent_window_(parent_window
),
124 root_view_(root_view
),
125 association_observer_(new AssociationObserver(this)) {
126 parent_window_
->AddObserver(this);
127 const std::vector
<aura::Window
*>& windows
= parent_window_
->children();
128 for (size_t i
= 0; i
< windows
.size(); ++i
)
129 association_observer_
->StartObserving(windows
[i
]);
130 ReorderChildWindows();
133 WindowReorderer::~WindowReorderer() {
134 if (parent_window_
) {
135 parent_window_
->RemoveObserver(this);
136 // |association_observer_| stops observing any windows it is observing upon
141 void WindowReorderer::ReorderChildWindows() {
145 std::map
<View
*, aura::Window
*> hosted_windows
;
146 GetViewsWithAssociatedWindow(*parent_window_
, &hosted_windows
);
148 if (hosted_windows
.empty()) {
149 // Exit early if there are no views with associated windows.
150 // View::ReorderLayers() should have already reordered the layers owned by
155 // Compute the desired z-order of the layers based on the order of the views
156 // with layers and views with associated windows in the view tree.
157 std::vector
<View
*> view_with_layer_order
;
158 GetOrderOfViewsWithLayers(root_view_
, parent_window_
->layer(), hosted_windows
,
159 &view_with_layer_order
);
161 // For the sake of simplicity, reorder both the layers owned by views and the
162 // layers of windows associated with a view. Iterate through
163 // |view_with_layer_order| backwards and stack windows at the bottom so that
164 // windows not associated to a view are stacked above windows with an
166 for (std::vector
<View
*>::reverse_iterator it
= view_with_layer_order
.rbegin();
167 it
!= view_with_layer_order
.rend(); ++it
) {
169 ui::Layer
* layer
= view
->layer();
170 aura::Window
* window
= NULL
;
172 std::map
<View
*, aura::Window
*>::iterator hosted_window_it
=
173 hosted_windows
.find(view
);
174 if (hosted_window_it
!= hosted_windows
.end()) {
175 window
= hosted_window_it
->second
;
176 layer
= window
->layer();
181 parent_window_
->StackChildAtBottom(window
);
182 parent_window_
->layer()->StackAtBottom(layer
);
186 void WindowReorderer::OnWindowAdded(aura::Window
* new_window
) {
187 association_observer_
->StartObserving(new_window
);
188 ReorderChildWindows();
191 void WindowReorderer::OnWillRemoveWindow(aura::Window
* window
) {
192 association_observer_
->StopObserving(window
);
195 void WindowReorderer::OnWindowDestroying(aura::Window
* window
) {
196 parent_window_
->RemoveObserver(this);
197 parent_window_
= NULL
;
198 association_observer_
.reset();