| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/corewm/transient_window_stacking_client.h" | 5 #include "ui/views/corewm/transient_window_stacking_client.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ui/views/corewm/transient_window_manager.h" |
| 10 #include "ui/views/corewm/window_util.h" |
| 11 |
| 9 using aura::Window; | 12 using aura::Window; |
| 10 | 13 |
| 11 namespace views { | 14 namespace views { |
| 12 namespace corewm { | 15 namespace corewm { |
| 13 | 16 |
| 14 namespace { | 17 namespace { |
| 15 | 18 |
| 16 // Populates |ancestors| with all transient ancestors of |window| that are | 19 // Populates |ancestors| with all transient ancestors of |window| that are |
| 17 // siblings of |window|. Returns true if any ancestors were found, false if not. | 20 // siblings of |window|. Returns true if any ancestors were found, false if not. |
| 18 bool GetAllTransientAncestors(Window* window, Window::Windows* ancestors) { | 21 bool GetAllTransientAncestors(Window* window, Window::Windows* ancestors) { |
| 19 Window* parent = window->parent(); | 22 Window* parent = window->parent(); |
| 20 for (; window; window = window->transient_parent()) { | 23 for (; window; window = GetTransientParent(window)) { |
| 21 if (window->parent() == parent) | 24 if (window->parent() == parent) |
| 22 ancestors->push_back(window); | 25 ancestors->push_back(window); |
| 23 } | 26 } |
| 24 return (!ancestors->empty()); | 27 return (!ancestors->empty()); |
| 25 } | 28 } |
| 26 | 29 |
| 27 // Replaces |window1| and |window2| with their possible transient ancestors that | 30 // Replaces |window1| and |window2| with their possible transient ancestors that |
| 28 // are still siblings (have a common transient parent). |window1| and |window2| | 31 // are still siblings (have a common transient parent). |window1| and |window2| |
| 29 // are not modified if such ancestors cannot be found. | 32 // are not modified if such ancestors cannot be found. |
| 30 void FindCommonTransientAncestor(Window** window1, Window** window2) { | 33 void FindCommonTransientAncestor(Window** window1, Window** window2) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 44 Window::Windows::const_reverse_iterator it2 = ancestors2.rbegin(); | 47 Window::Windows::const_reverse_iterator it2 = ancestors2.rbegin(); |
| 45 for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) { | 48 for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) { |
| 46 if (*it1 != *it2) { | 49 if (*it1 != *it2) { |
| 47 *window1 = *it1; | 50 *window1 = *it1; |
| 48 *window2 = *it2; | 51 *window2 = *it2; |
| 49 break; | 52 break; |
| 50 } | 53 } |
| 51 } | 54 } |
| 52 } | 55 } |
| 53 | 56 |
| 54 // Returns true if |window| has |ancestor| as a transient ancestor. A transient | 57 // Adjusts |target| so that we don't attempt to stack on top of a window with a |
| 55 // ancestor is found by following the transient parent chain of the window. | 58 // NULL delegate. |
| 56 bool HasTransientAncestor(const Window* window, const Window* ancestor) { | 59 void SkipNullDelegates(Window::StackDirection direction, Window** target) { |
| 57 if (window->transient_parent() == ancestor) | 60 const Window::Windows& children((*target)->parent()->children()); |
| 58 return true; | 61 size_t target_i = |
| 59 return window->transient_parent() ? | 62 std::find(children.begin(), children.end(), *target) - |
| 60 HasTransientAncestor(window->transient_parent(), ancestor) : false; | 63 children.begin(); |
| 64 |
| 65 // By convention we don't stack on top of windows with layers with NULL |
| 66 // delegates. Walk backward to find a valid target window. See tests |
| 67 // TransientWindowManagerTest.StackingMadrigal and StackOverClosingTransient |
| 68 // for an explanation of this. |
| 69 while (target_i > 0) { |
| 70 const size_t index = direction == Window::STACK_ABOVE ? |
| 71 target_i : target_i - 1; |
| 72 if (!children[index]->layer() || |
| 73 children[index]->layer()->delegate() != NULL) |
| 74 break; |
| 75 --target_i; |
| 76 } |
| 77 *target = children[target_i]; |
| 61 } | 78 } |
| 62 | 79 |
| 63 } // namespace | 80 } // namespace |
| 64 | 81 |
| 82 // static |
| 83 TransientWindowStackingClient* TransientWindowStackingClient::instance_ = NULL; |
| 84 |
| 65 TransientWindowStackingClient::TransientWindowStackingClient() { | 85 TransientWindowStackingClient::TransientWindowStackingClient() { |
| 86 instance_ = this; |
| 66 } | 87 } |
| 67 | 88 |
| 68 TransientWindowStackingClient::~TransientWindowStackingClient() { | 89 TransientWindowStackingClient::~TransientWindowStackingClient() { |
| 90 if (instance_ == this) |
| 91 instance_ = NULL; |
| 69 } | 92 } |
| 70 | 93 |
| 71 bool TransientWindowStackingClient::AdjustStacking( | 94 bool TransientWindowStackingClient::AdjustStacking( |
| 72 Window** child, | 95 Window** child, |
| 73 Window** target, | 96 Window** target, |
| 74 Window::StackDirection* direction) { | 97 Window::StackDirection* direction) { |
| 98 const TransientWindowManager* transient_manager = |
| 99 TransientWindowManager::Get((*child)->parent()); |
| 100 if (transient_manager && |
| 101 transient_manager->IsStackingTransient(*child, *target)) |
| 102 return true; |
| 103 |
| 75 // For windows that have transient children stack the transient ancestors that | 104 // For windows that have transient children stack the transient ancestors that |
| 76 // are siblings. This prevents one transient group from being inserted in the | 105 // are siblings. This prevents one transient group from being inserted in the |
| 77 // middle of another. | 106 // middle of another. |
| 78 FindCommonTransientAncestor(child, target); | 107 FindCommonTransientAncestor(child, target); |
| 79 | 108 |
| 80 // When stacking above skip to the topmost transient descendant of the target. | 109 // When stacking above skip to the topmost transient descendant of the target. |
| 81 if (*direction == Window::STACK_ABOVE && | 110 if (*direction == Window::STACK_ABOVE && |
| 82 !HasTransientAncestor(*child, *target)) { | 111 !HasTransientAncestor(*child, *target)) { |
| 83 const Window::Windows& siblings((*child)->parent()->children()); | 112 const Window::Windows& siblings((*child)->parent()->children()); |
| 84 size_t target_i = | 113 size_t target_i = |
| 85 std::find(siblings.begin(), siblings.end(), *target) - siblings.begin(); | 114 std::find(siblings.begin(), siblings.end(), *target) - siblings.begin(); |
| 86 while (target_i + 1 < siblings.size() && | 115 while (target_i + 1 < siblings.size() && |
| 87 HasTransientAncestor(siblings[target_i + 1], *target)) { | 116 HasTransientAncestor(siblings[target_i + 1], *target)) { |
| 88 ++target_i; | 117 ++target_i; |
| 89 } | 118 } |
| 90 *target = siblings[target_i]; | 119 *target = siblings[target_i]; |
| 91 } | 120 } |
| 92 return true; | 121 |
| 122 SkipNullDelegates(*direction, target); |
| 123 |
| 124 // If we couldn't find a valid target position, don't move anything. |
| 125 if (*direction == Window::STACK_ABOVE && |
| 126 ((*target)->layer() && (*target)->layer()->delegate() == NULL)) { |
| 127 return false; |
| 128 } |
| 129 |
| 130 return *child != *target; |
| 93 } | 131 } |
| 94 | 132 |
| 95 } // namespace corewm | 133 } // namespace corewm |
| 96 } // namespace views | 134 } // namespace views |
| OLD | NEW |