Chromium Code Reviews| Index: ui/views/widget/native_widget_layer_reorderer_aura.cc |
| diff --git a/ui/views/widget/native_widget_layer_reorderer_aura.cc b/ui/views/widget/native_widget_layer_reorderer_aura.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..538ebb8a2450fd26133f760612c47f8f101e4f33 |
| --- /dev/null |
| +++ b/ui/views/widget/native_widget_layer_reorderer_aura.cc |
| @@ -0,0 +1,149 @@ |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "ui/views/widget/native_widget_layer_reorderer_aura.h" |
| + |
| +#include <map> |
| +#include <vector> |
| + |
| +#include "ui/aura/window.h" |
| +#include "ui/views/view.h" |
| +#include "ui/views/view_constants_aura.h" |
| + |
| +namespace views { |
| + |
| +namespace { |
| + |
| +// Sets |hosted_windows| to a mapping of the views with an attached window to |
| +// the window that they are attached to. Only views attached to a child of |
| +// |parent_window| are returned. |
| +void GetViewsWithAttachedWindow( |
| + const aura::Window& parent_window, |
| + std::map<views::View*, aura::Window*>* hosted_windows) { |
| + const std::vector<aura::Window*>& child_windows = parent_window.children(); |
| + for (size_t i = 0; i < child_windows.size(); ++i) { |
| + aura::Window* child = child_windows[i]; |
| + View* host_view = child->GetProperty(kHostViewKey); |
| + if (host_view) |
| + (*hosted_windows)[host_view] = child; |
| + } |
| +} |
| + |
| +// Sets |order| to the list of views whose layer / attached window's layer |
| +// is a child of |parent_layer|. |order| is sorted in ascending z-order of |
| +// the views. |
| +// |hosts| are the views with an attached window whose layer is a child of |
| +// |parent_layer|. |
| +void GetOrderOfViewsWithLayers( |
| + views::View* view, |
| + ui::Layer* parent_layer, |
| + const std::map<views::View*, aura::Window*>& hosts, |
| + std::vector<views::View*>* order) { |
| + DCHECK(view); |
| + DCHECK(parent_layer); |
| + DCHECK(order); |
| + if (view->layer() && view->layer()->parent() == parent_layer) { |
| + order->push_back(view); |
| + // |hosts| may contain a child of |view|. |
| + } else if (hosts.find(view) != hosts.end()) { |
| + order->push_back(view); |
| + } |
| + |
| + for (int i = 0; i < view->child_count(); ++i) |
| + GetOrderOfViewsWithLayers(view->child_at(i), parent_layer, hosts, order); |
| +} |
| + |
| +} // namespace |
| + |
| +NativeWidgetLayerReordererAura::NativeWidgetLayerReordererAura( |
| + aura::Window* window, |
| + View* root_view) |
| + : window_(window), |
| + root_view_(root_view) { |
| + window_->AddObserver(this); |
| + const std::vector<aura::Window*>& child_windows = window_->children(); |
| + for (size_t i = 0; i < child_windows.size(); ++i) |
| + child_windows[i]->AddObserver(this); |
| +} |
| + |
| +NativeWidgetLayerReordererAura::~NativeWidgetLayerReordererAura() { |
| + if (window_) |
| + StopObserving(window_); |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::ReorderChildWindowLayers() { |
| + DCHECK(window_); |
| + |
| + std::map<View*, aura::Window*> hosted_windows; |
| + GetViewsWithAttachedWindow(*window_, &hosted_windows); |
| + |
| + if (hosted_windows.empty()) { |
| + // Exit early if there are no views with attached windows. |
| + // View::ReorderLayers() should have already reordered the layers owned by |
| + // views. |
| + return; |
| + } |
| + |
| + // Compute the desired z-order of the layers based on the order of the views |
| + // with layers and views with attached windows in the view tree. |
| + std::vector<View*> view_with_layer_order; |
| + GetOrderOfViewsWithLayers(root_view_, window_->layer(), hosted_windows, |
| + &view_with_layer_order); |
| + |
| + // Reorder the layers and windows. |
| + for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin(); |
| + it != view_with_layer_order.rend(); ++it) { |
| + View* view = *it; |
| + ui::Layer* layer = view->layer(); |
| + aura::Window* window = NULL; |
| + |
| + std::map<View*, aura::Window*>::iterator hosted_window_it = |
| + hosted_windows.find(view); |
| + if (hosted_window_it != hosted_windows.end()) { |
| + window = hosted_window_it->second; |
| + layer = window->layer(); |
| + } |
| + |
| + DCHECK(layer); |
| + if (window) |
| + window_->StackChildAtBottom(window); |
| + window_->layer()->StackAtBottom(layer); |
|
sky
2013/05/24 15:57:26
Don't we only care about items in hosted_windows h
pkotwicz
2013/05/26 04:12:15
IMHO, it's simpler (and safer) to reorder both lay
|
| + } |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::StopObserving(aura::Window* window) { |
| + window->RemoveObserver(this); |
|
sky
2013/05/24 15:57:26
It's subtle and easy to get wrong that you're obse
pkotwicz
2013/05/26 04:12:15
Added a separate class
|
| + if (window_ == window){ |
| + const std::vector<aura::Window*>& child_windows = window_->children(); |
| + for (size_t i = 0; i < child_windows.size(); ++i) |
| + child_windows[i]->RemoveObserver(this); |
| + window_ = NULL; |
| + } |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWindowAdded(aura::Window* new_window) { |
| + if (new_window->parent() == window_) { |
| + new_window->AddObserver(this); |
| + ReorderChildWindowLayers(); |
| + } |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWillRemoveWindow(aura::Window* window) { |
| + if (window->parent() == window_) |
|
sky
2013/05/24 15:57:26
Why do you care about this case?
pkotwicz
2013/05/26 04:12:15
This is no longer relevant because I separated the
|
| + StopObserving(window); |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWindowPropertyChanged( |
| + aura::Window* window, |
| + const void* key, |
| + intptr_t old) { |
| + if (key == kHostViewKey && window != window_) |
| + ReorderChildWindowLayers(); |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWindowDestroying(aura::Window* window) { |
| + StopObserving(window); |
| +} |
| + |
| +} // namespace views |