| Index: ui/views/corewm/transient_window_stacking_client.cc
|
| diff --git a/ui/views/corewm/transient_window_stacking_client.cc b/ui/views/corewm/transient_window_stacking_client.cc
|
| index e3373ffacf0d6462ce8406d68175748594cc78c3..ef08cc0ed7bf01402b14a5145a2b1ea5a1be27da 100644
|
| --- a/ui/views/corewm/transient_window_stacking_client.cc
|
| +++ b/ui/views/corewm/transient_window_stacking_client.cc
|
| @@ -6,6 +6,9 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "ui/views/corewm/transient_window_manager.h"
|
| +#include "ui/views/corewm/window_util.h"
|
| +
|
| using aura::Window;
|
|
|
| namespace views {
|
| @@ -17,7 +20,7 @@ namespace {
|
| // siblings of |window|. Returns true if any ancestors were found, false if not.
|
| bool GetAllTransientAncestors(Window* window, Window::Windows* ancestors) {
|
| Window* parent = window->parent();
|
| - for (; window; window = window->transient_parent()) {
|
| + for (; window; window = GetTransientParent(window)) {
|
| if (window->parent() == parent)
|
| ancestors->push_back(window);
|
| }
|
| @@ -51,27 +54,53 @@ void FindCommonTransientAncestor(Window** window1, Window** window2) {
|
| }
|
| }
|
|
|
| -// Returns true if |window| has |ancestor| as a transient ancestor. A transient
|
| -// ancestor is found by following the transient parent chain of the window.
|
| -bool HasTransientAncestor(const Window* window, const Window* ancestor) {
|
| - if (window->transient_parent() == ancestor)
|
| - return true;
|
| - return window->transient_parent() ?
|
| - HasTransientAncestor(window->transient_parent(), ancestor) : false;
|
| +// Adjusts |target| so that we don't attempt to stack on top of a window with a
|
| +// NULL delegate.
|
| +void SkipNullDelegates(Window::StackDirection direction, Window** target) {
|
| + const Window::Windows& children((*target)->parent()->children());
|
| + size_t target_i =
|
| + std::find(children.begin(), children.end(), *target) -
|
| + children.begin();
|
| +
|
| + // By convention we don't stack on top of windows with layers with NULL
|
| + // delegates. Walk backward to find a valid target window. See tests
|
| + // TransientWindowManagerTest.StackingMadrigal and StackOverClosingTransient
|
| + // for an explanation of this.
|
| + while (target_i > 0) {
|
| + const size_t index = direction == Window::STACK_ABOVE ?
|
| + target_i : target_i - 1;
|
| + if (!children[index]->layer() ||
|
| + children[index]->layer()->delegate() != NULL)
|
| + break;
|
| + --target_i;
|
| + }
|
| + *target = children[target_i];
|
| }
|
|
|
| } // namespace
|
|
|
| +// static
|
| +TransientWindowStackingClient* TransientWindowStackingClient::instance_ = NULL;
|
| +
|
| TransientWindowStackingClient::TransientWindowStackingClient() {
|
| + instance_ = this;
|
| }
|
|
|
| TransientWindowStackingClient::~TransientWindowStackingClient() {
|
| + if (instance_ == this)
|
| + instance_ = NULL;
|
| }
|
|
|
| bool TransientWindowStackingClient::AdjustStacking(
|
| Window** child,
|
| Window** target,
|
| Window::StackDirection* direction) {
|
| + const TransientWindowManager* transient_manager =
|
| + TransientWindowManager::Get((*child)->parent());
|
| + if (transient_manager &&
|
| + transient_manager->IsStackingTransient(*child, *target))
|
| + return true;
|
| +
|
| // For windows that have transient children stack the transient ancestors that
|
| // are siblings. This prevents one transient group from being inserted in the
|
| // middle of another.
|
| @@ -89,7 +118,16 @@ bool TransientWindowStackingClient::AdjustStacking(
|
| }
|
| *target = siblings[target_i];
|
| }
|
| - return true;
|
| +
|
| + SkipNullDelegates(*direction, target);
|
| +
|
| + // If we couldn't find a valid target position, don't move anything.
|
| + if (*direction == Window::STACK_ABOVE &&
|
| + ((*target)->layer() && (*target)->layer()->delegate() == NULL)) {
|
| + return false;
|
| + }
|
| +
|
| + return *child != *target;
|
| }
|
|
|
| } // namespace corewm
|
|
|