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

Side by Side Diff: ui/views/widget/native_widget_window_reorderer_aura.cc

Issue 15114002: Reorder the NativeViews attached to a view via kViewHostKey according to the position of the view (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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 | 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/widget/native_widget_window_reorderer_aura.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "ui/aura/window.h"
11 #include "ui/views/view.h"
12 #include "ui/views/view_constants_aura.h"
13
14 namespace views {
15
16 namespace {
17
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);
28 if (host_view)
29 (*hosted_windows)[host_view] = child;
30 }
31 }
32
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
35 // the views.
36 // |hosts| are the views with an associated window whose layer is a child of
37 // |parent_layer|.
38 void GetOrderOfViewsWithLayers(
39 views::View* view,
40 ui::Layer* parent_layer,
41 const std::map<views::View*, aura::Window*>& hosts,
42 std::vector<views::View*>* order) {
43 DCHECK(view);
44 DCHECK(parent_layer);
45 DCHECK(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);
51 }
52
53 for (int i = 0; i < view->child_count(); ++i)
54 GetOrderOfViewsWithLayers(view->child_at(i), parent_layer, hosts, order);
55 }
56
57 } // namespace
58
59 // Class which reorders windows as a result of the views::kHostViewKey being set
60 // on the window.
61 class NativeWidgetWindowReordererAura::AssociationObserver
62 : public aura::WindowObserver {
63 public:
64 explicit AssociationObserver(NativeWidgetWindowReordererAura* reorderer);
65 virtual ~AssociationObserver();
66
67 // Start/stop observing changes in the views::kHostViewKey property on
68 // |window|.
69 void StartObserving(aura::Window* window);
70 void StopObserving(aura::Window* window);
71
72 private:
73 // aura::WindowObserver overrides:
74 virtual void OnWindowPropertyChanged(aura::Window* window,
75 const void* key,
76 intptr_t old) OVERRIDE;
77 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
78
79 // Not owned.
80 NativeWidgetWindowReordererAura* reorderer_;
81
82 std::set<aura::Window*> windows_;
83
84 DISALLOW_COPY_AND_ASSIGN(AssociationObserver);
85 };
86
87 NativeWidgetWindowReordererAura::AssociationObserver::AssociationObserver(
88 NativeWidgetWindowReordererAura* reorderer)
89 : reorderer_(reorderer) {
90 }
91
92 NativeWidgetWindowReordererAura::AssociationObserver::~AssociationObserver() {
93 while (!windows_.empty())
94 StopObserving(*windows_.begin());
95 }
96
97 void NativeWidgetWindowReordererAura::AssociationObserver::StartObserving(
98 aura::Window* window) {
99 windows_.insert(window);
100 window->AddObserver(this);
101 }
102
103 void NativeWidgetWindowReordererAura::AssociationObserver::StopObserving(
104 aura::Window* window) {
105 windows_.erase(window);
106 window->RemoveObserver(this);
107 }
108
109 void NativeWidgetWindowReordererAura::AssociationObserver::
110 OnWindowPropertyChanged(
111 aura::Window* window,
112 const void* key,
113 intptr_t old) {
114 if (key == views::kHostViewKey)
115 reorderer_->ReorderChildWindows();
116 }
117
118 void NativeWidgetWindowReordererAura::AssociationObserver::OnWindowDestroying(
119 aura::Window* window) {
120 windows_.erase(window);
121 window->RemoveObserver(this);
122 }
123
124 NativeWidgetWindowReordererAura::NativeWidgetWindowReordererAura(
125 aura::Window* parent_window,
126 View* root_view)
127 : parent_window_(parent_window),
128 root_view_(root_view),
129 association_observer_(new AssociationObserver(this)) {
130 parent_window_->AddObserver(this);
131 const std::vector<aura::Window*>& windows = parent_window_->children();
132 for (size_t i = 0; i < windows.size(); ++i)
133 association_observer_->StartObserving(windows[i]);
134 }
135
136 NativeWidgetWindowReordererAura::~NativeWidgetWindowReordererAura() {
137 if (parent_window_) {
138 parent_window_->RemoveObserver(this);
139 // |association_observer_| stops observing any windows it is observing upon
140 // destruction.
141 }
142 }
143
144 void NativeWidgetWindowReordererAura::ReorderChildWindows() {
145 DCHECK(parent_window_);
146
147 std::map<View*, aura::Window*> hosted_windows;
148 GetViewsWithAssociatedWindow(*parent_window_, &hosted_windows);
149
150 if (hosted_windows.empty()) {
151 // Exit early if there are no views with associated windows.
152 // View::ReorderLayers() should have already reordered the layers owned by
153 // views.
154 return;
155 }
156
157 // Compute the desired z-order of the layers based on the order of the views
158 // with layers and views with associated windows in the view tree.
159 std::vector<View*> view_with_layer_order;
160 GetOrderOfViewsWithLayers(root_view_, parent_window_->layer(), hosted_windows,
161 &view_with_layer_order);
162
163 // For the sake of simplicity, reorder both the layers owned by views and the
164 // layers of windows associated with a view. Iterate through
165 // |view_with_layer_order| backwards and stack windows at the bottom so that
166 // windows not associated to a view are stacked above windows with an
167 // associated view.
168 for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin();
169 it != view_with_layer_order.rend(); ++it) {
170 View* view = *it;
171 ui::Layer* layer = view->layer();
172 aura::Window* window = NULL;
173
174 std::map<View*, aura::Window*>::iterator hosted_window_it =
175 hosted_windows.find(view);
176 if (hosted_window_it != hosted_windows.end()) {
177 window = hosted_window_it->second;
178 layer = window->layer();
179 }
180
181 DCHECK(layer);
182 if (window)
183 parent_window_->StackChildAtBottom(window);
184 parent_window_->layer()->StackAtBottom(layer);
185 }
186 }
187
188 void NativeWidgetWindowReordererAura::OnWindowAdded(aura::Window* new_window) {
189 association_observer_->StartObserving(new_window);
190 }
191
192 void NativeWidgetWindowReordererAura::OnWillRemoveWindow(aura::Window* window) {
193 association_observer_->StopObserving(window);
194 }
195
196 void NativeWidgetWindowReordererAura::OnWindowDestroying(aura::Window* window) {
197 parent_window_->RemoveObserver(this);
198 parent_window_ = NULL;
199 association_observer_.reset();
200 }
201
202 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698