| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "ui/views/widget/window_reorderer.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 kHostViewKey property being | |
| 60 // set on the window. | |
| 61 class WindowReorderer::AssociationObserver : public aura::WindowObserver { | |
| 62 public: | |
| 63 explicit AssociationObserver(WindowReorderer* reorderer); | |
| 64 virtual ~AssociationObserver(); | |
| 65 | |
| 66 // Start/stop observing changes in the kHostViewKey property on |window|. | |
| 67 void StartObserving(aura::Window* window); | |
| 68 void StopObserving(aura::Window* window); | |
| 69 | |
| 70 private: | |
| 71 // aura::WindowObserver overrides: | |
| 72 virtual void OnWindowPropertyChanged(aura::Window* window, | |
| 73 const void* key, | |
| 74 intptr_t old) override; | |
| 75 virtual void OnWindowDestroying(aura::Window* window) override; | |
| 76 | |
| 77 // Not owned. | |
| 78 WindowReorderer* reorderer_; | |
| 79 | |
| 80 std::set<aura::Window*> windows_; | |
| 81 | |
| 82 DISALLOW_COPY_AND_ASSIGN(AssociationObserver); | |
| 83 }; | |
| 84 | |
| 85 WindowReorderer::AssociationObserver::AssociationObserver( | |
| 86 WindowReorderer* reorderer) | |
| 87 : reorderer_(reorderer) { | |
| 88 } | |
| 89 | |
| 90 WindowReorderer::AssociationObserver::~AssociationObserver() { | |
| 91 while (!windows_.empty()) | |
| 92 StopObserving(*windows_.begin()); | |
| 93 } | |
| 94 | |
| 95 void WindowReorderer::AssociationObserver::StartObserving( | |
| 96 aura::Window* window) { | |
| 97 windows_.insert(window); | |
| 98 window->AddObserver(this); | |
| 99 } | |
| 100 | |
| 101 void WindowReorderer::AssociationObserver::StopObserving( | |
| 102 aura::Window* window) { | |
| 103 windows_.erase(window); | |
| 104 window->RemoveObserver(this); | |
| 105 } | |
| 106 | |
| 107 void WindowReorderer::AssociationObserver::OnWindowPropertyChanged( | |
| 108 aura::Window* window, | |
| 109 const void* key, | |
| 110 intptr_t old) { | |
| 111 if (key == kHostViewKey) | |
| 112 reorderer_->ReorderChildWindows(); | |
| 113 } | |
| 114 | |
| 115 void WindowReorderer::AssociationObserver::OnWindowDestroying( | |
| 116 aura::Window* window) { | |
| 117 windows_.erase(window); | |
| 118 window->RemoveObserver(this); | |
| 119 } | |
| 120 | |
| 121 WindowReorderer::WindowReorderer(aura::Window* parent_window, | |
| 122 View* root_view) | |
| 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(); | |
| 131 } | |
| 132 | |
| 133 WindowReorderer::~WindowReorderer() { | |
| 134 if (parent_window_) { | |
| 135 parent_window_->RemoveObserver(this); | |
| 136 // |association_observer_| stops observing any windows it is observing upon | |
| 137 // destruction. | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 void WindowReorderer::ReorderChildWindows() { | |
| 142 if (!parent_window_) | |
| 143 return; | |
| 144 | |
| 145 std::map<View*, aura::Window*> hosted_windows; | |
| 146 GetViewsWithAssociatedWindow(*parent_window_, &hosted_windows); | |
| 147 | |
| 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 | |
| 151 // views. | |
| 152 return; | |
| 153 } | |
| 154 | |
| 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); | |
| 160 | |
| 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 | |
| 165 // associated view. | |
| 166 for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin(); | |
| 167 it != view_with_layer_order.rend(); ++it) { | |
| 168 View* view = *it; | |
| 169 ui::Layer* layer = view->layer(); | |
| 170 aura::Window* window = NULL; | |
| 171 | |
| 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(); | |
| 177 } | |
| 178 | |
| 179 DCHECK(layer); | |
| 180 if (window) | |
| 181 parent_window_->StackChildAtBottom(window); | |
| 182 parent_window_->layer()->StackAtBottom(layer); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 void WindowReorderer::OnWindowAdded(aura::Window* new_window) { | |
| 187 association_observer_->StartObserving(new_window); | |
| 188 ReorderChildWindows(); | |
| 189 } | |
| 190 | |
| 191 void WindowReorderer::OnWillRemoveWindow(aura::Window* window) { | |
| 192 association_observer_->StopObserving(window); | |
| 193 } | |
| 194 | |
| 195 void WindowReorderer::OnWindowDestroying(aura::Window* window) { | |
| 196 parent_window_->RemoveObserver(this); | |
| 197 parent_window_ = NULL; | |
| 198 association_observer_.reset(); | |
| 199 } | |
| 200 | |
| 201 } // namespace views | |
| OLD | NEW |