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..6579f5ff0b99255522f896bd939ba4f80e8ae97e |
| --- /dev/null |
| +++ b/ui/views/widget/native_widget_layer_reorderer_aura.cc |
| @@ -0,0 +1,163 @@ |
| +// 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()) { |
|
pkotwicz
2013/05/23 02:28:07
I think that this is ok because |hosts| is small i
|
| + 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::ReorderLayers() { |
| + DCHECK(window_); |
| + |
| + std::map<View*, aura::Window*> hosted_windows; |
| + GetViewsWithAttachedWindow(*window_, &hosted_windows); |
| + |
| + // 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); |
| + |
| + if (view_with_layer_order.empty()) |
| + return; |
| + |
| + // Find the bottommost window with a NULL layer delegate below which the |
| + // reordered windows and layers should be stacked. |stack_below_window| should |
| + // be NULL if the reordered windows and layers should be stacked at the top. |
| + const std::vector<aura::Window*>& child_windows = window_->children(); |
| + aura::Window* stack_below_window = NULL; |
| + for (size_t i = 0; i < child_windows.size(); ++i) { |
| + aura::Window* child = child_windows[i]; |
| + if (!child->layer()->delegate()) { |
| + stack_below_window = child; |
| + break; |
| + } |
| + } |
| + |
| + // Reorder the layers and windows. |
| + for (size_t i = 0; i < view_with_layer_order.size(); ++i) { |
| + View* view = view_with_layer_order[i]; |
| + 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 (stack_below_window) { |
| + if (window) |
| + window_->StackChildBelow(window, stack_below_window); |
| + window_->layer()->StackBelow(layer, stack_below_window->layer()); |
| + } else { |
| + if (window) |
| + window_->StackChildAtTop(window); |
| + window_->layer()->StackAtTop(layer); |
| + } |
| + } |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::StopObserving(aura::Window* window) { |
| + window->RemoveObserver(this); |
| + 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); |
| + ReorderLayers(); |
| + } |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWillRemoveWindow(aura::Window* window) { |
| + if (window->parent() == window_) |
| + StopObserving(window); |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWindowPropertyChanged( |
| + aura::Window* window, |
| + const void* key, |
| + intptr_t old) { |
| + if (window != window_ && key == kHostViewKey) |
| + ReorderLayers(); |
| +} |
| + |
| +void NativeWidgetLayerReordererAura::OnWindowDestroying(aura::Window* window) { |
| + StopObserving(window); |
| +} |
| + |
| +} // namespace views |